]> git.saurik.com Git - apple/system_cmds.git/blame - getty.tproj/subr.c
system_cmds-230.0.2.tar.gz
[apple/system_cmds.git] / getty.tproj / subr.c
CommitLineData
1815bff5
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6d658acd
A
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
1815bff5
A
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
6d658acd
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1815bff5
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/*
26 * Copyright (c) 1983, 1993
27 * The Regents of the University of California. All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 */
57
58#ifndef lint
59/*static char sccsid[] = "from: @(#)subr.c 8.1 (Berkeley) 6/4/93";*/
60static char rcsid[] = "$Id: subr.c,v 1.1.1.2 2000/01/11 02:10:15 wsanchez Exp $";
61#endif /* not lint */
62
63/*
64 * Melbourne getty.
65 */
66#define COMPAT_43 1
67#include <stdlib.h>
68#include <unistd.h>
69#include <string.h>
70#include <termios.h>
71#include <sys/ioctl.h>
72
73#include "gettytab.h"
74#include "pathnames.h"
75#include "extern.h"
76
77extern struct termios tmode, omode;
78
79static void compatflags __P((long));
80
81/*
82 * Get a table entry.
83 */
84void
85gettable(name, buf)
86 char *name, *buf;
87{
88 register struct gettystrs *sp;
89 register struct gettynums *np;
90 register struct gettyflags *fp;
91 long n;
92 char *dba[2];
93 dba[0] = _PATH_GETTYTAB;
94 dba[1] = 0;
95
96 if (cgetent(&buf, dba, name) != 0)
97 return;
98
99 for (sp = gettystrs; sp->field; sp++)
100 cgetstr(buf, sp->field, &sp->value);
101 for (np = gettynums; np->field; np++) {
102 if (cgetnum(buf, np->field, &n) == -1)
103 np->set = 0;
104 else {
105 np->set = 1;
106 np->value = n;
107 }
108 }
109 for (fp = gettyflags; fp->field; fp++) {
110 if (cgetcap(buf, fp->field, ':') == NULL)
111 fp->set = 0;
112 else {
113 fp->set = 1;
114 fp->value = 1 ^ fp->invrt;
115 }
116 }
117#ifdef DEBUG
118 printf("name=\"%s\", buf=\"%s\"\n", name, buf);
119 for (sp = gettystrs; sp->field; sp++)
120 printf("cgetstr: %s=%s\n", sp->field, sp->value);
121 for (np = gettynums; np->field; np++)
122 printf("cgetnum: %s=%d\n", np->field, np->value);
123 for (fp = gettyflags; fp->field; fp++)
124 printf("cgetflags: %s='%c' set='%c'\n", fp->field,
125 fp->value + '0', fp->set + '0');
126 exit(1);
127#endif /* DEBUG */
128}
129
130void
131gendefaults()
132{
133 register struct gettystrs *sp;
134 register struct gettynums *np;
135 register struct gettyflags *fp;
136
137 for (sp = gettystrs; sp->field; sp++)
138 if (sp->value)
139 sp->defalt = sp->value;
140 for (np = gettynums; np->field; np++)
141 if (np->set)
142 np->defalt = np->value;
143 for (fp = gettyflags; fp->field; fp++)
144 if (fp->set)
145 fp->defalt = fp->value;
146 else
147 fp->defalt = fp->invrt;
148}
149
150void
151setdefaults()
152{
153 register struct gettystrs *sp;
154 register struct gettynums *np;
155 register struct gettyflags *fp;
156
157 for (sp = gettystrs; sp->field; sp++)
158 if (!sp->value)
159 sp->value = sp->defalt;
160 for (np = gettynums; np->field; np++)
161 if (!np->set)
162 np->value = np->defalt;
163 for (fp = gettyflags; fp->field; fp++)
164 if (!fp->set)
165 fp->value = fp->defalt;
166}
167
168static char **
169charnames[] = {
170 &ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
171 &SU, &DS, &RP, &FL, &WE, &LN, 0
172};
173
174static char *
175charvars[] = {
176 &tmode.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR],
177 &tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP],
178 &tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP],
179 &tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD],
180 &tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], 0
181};
182
183void
184setchars()
185{
186 register int i;
187 register char *p;
188
189 for (i = 0; charnames[i]; i++) {
190 p = *charnames[i];
191 if (p && *p)
192 *charvars[i] = *p;
193 else
194 *charvars[i] = _POSIX_VDISABLE;
195 }
196}
197
198void
199setflags(n)
200 int n;
201{
202 register tcflag_t iflag, oflag, cflag, lflag;
203
204#ifdef COMPAT_43
205 switch (n) {
206 case 0:
207 if (F0set) {
208 compatflags(F0);
209 return;
210 }
211 break;
212 case 1:
213 if (F1set) {
214 compatflags(F1);
215 return;
216 }
217 break;
218 default:
219 if (F2set) {
220 compatflags(F2);
221 return;
222 }
223 break;
224 }
225#endif
226
227 switch (n) {
228 case 0:
229 if (C0set && I0set && L0set && O0set) {
230 tmode.c_cflag = C0;
231 tmode.c_iflag = I0;
232 tmode.c_lflag = L0;
233 tmode.c_oflag = O0;
234 return;
235 }
236 break;
237 case 1:
238 if (C1set && I1set && L1set && O1set) {
239 tmode.c_cflag = C1;
240 tmode.c_iflag = I1;
241 tmode.c_lflag = L1;
242 tmode.c_oflag = O1;
243 return;
244 }
245 break;
246 default:
247 if (C2set && I2set && L2set && O2set) {
248 tmode.c_cflag = C2;
249 tmode.c_iflag = I2;
250 tmode.c_lflag = L2;
251 tmode.c_oflag = O2;
252 return;
253 }
254 break;
255 }
256
257#define BIC(v,c) (v) &= ~(c)
258#define BIS(v,s) (v) |= (s)
259#define BICS(v,c,s) BIC(v,c),BIS(v,s)
260
261 iflag = omode.c_iflag;
262 oflag = omode.c_oflag;
263 cflag = omode.c_cflag;
264 lflag = omode.c_lflag;
265
266 if (NP) {
267 BIC(iflag, ISTRIP|INPCK|IGNPAR);
268 BICS(cflag, CSIZE|PARENB|PARODD, CS8);
269 } else if (OP && !EP) {
270 BIS(iflag, ISTRIP|INPCK|IGNPAR);
271 BICS(cflag, CSIZE, PARENB|PARODD|CS7);
272 if (AP)
273 BIC(iflag, INPCK);
274 } else if (EP && !OP) {
275 BIS(iflag, ISTRIP|INPCK|IGNPAR);
276 BICS(cflag, CSIZE|PARODD, PARENB|CS7);
277 if (AP)
278 BIC(iflag, INPCK);
279 } else if (AP || EP && OP) {
280 BICS(iflag, INPCK|IGNPAR, ISTRIP);
281 BICS(cflag, CSIZE|PARODD, PARENB|CS7);
282 } /* else, leave as is */
283
284#if 0
285 if (UC)
286 f |= LCASE;
287#endif
288
289 if (HC)
290 cflag |= HUPCL;
291 else
292 cflag &= ~HUPCL;
293
294 if (NL) {
295 iflag |= ICRNL;
296 oflag |= ONLCR;
297 }
298
299#ifdef XXX_DELAY
300 f |= delaybits();
301#endif
302
303 if (n == 1) { /* read mode flags */
304 if (RW) {
305 iflag = 0;
306 oflag = 0;
307 cflag = CREAD|CS8;
308 lflag = 0;
309 } else {
310 lflag &= ~ICANON;
311 }
312 goto out;
313 }
314
315 if (HT)
316 oflag &= ~OXTABS;
317 else
318 oflag |= OXTABS;
319
320 if (n == 0)
321 goto out;
322
323#if 0
324 if (CB)
325 f |= CRTBS;
326#endif
327
328 if (CE)
329 lflag |= ECHOE;
330
331 if (CK)
332 lflag |= ECHOKE;
333
334 if (PE)
335 lflag |= ECHOPRT;
336
337 if (EC)
338 lflag |= ECHO;
339
340 if (XC)
341 lflag |= ECHOCTL;
342
343 if (DX)
344 lflag |= IXANY;
345
346 if (MB)
347 cflag |= MDMBUF;
348 else
349 cflag &= ~MDMBUF;
350
351out:
352 tmode.c_iflag = iflag;
353 tmode.c_oflag = oflag;
354 tmode.c_cflag = cflag;
355 tmode.c_lflag = lflag;
356}
357
358#ifdef COMPAT_43
359/*
360 * Old TTY => termios, snatched from <sys/kern/tty_compat.c>
361 */
362void
363compatflags(flags)
364register long flags;
365{
366 register tcflag_t iflag, oflag, cflag, lflag;
367
368 iflag = (BRKINT|ICRNL|IMAXBEL|IXON|IXANY);
369 oflag = (OPOST|ONLCR|OXTABS);
370 cflag = (CREAD);
371 lflag = (ICANON|ISIG|IEXTEN);
372
373 if (flags & TANDEM)
374 iflag |= IXOFF;
375 else
376 iflag &= ~IXOFF;
377 if (flags & ECHO)
378 lflag |= ECHO;
379 else
380 lflag &= ~ECHO;
381 if (flags & CRMOD) {
382 iflag |= ICRNL;
383 oflag |= ONLCR;
384 } else {
385 iflag &= ~ICRNL;
386 oflag &= ~ONLCR;
387 }
388 if (flags & XTABS)
389 oflag |= OXTABS;
390 else
391 oflag &= ~OXTABS;
392
393 if (flags & RAW) {
394 iflag &= IXOFF;
395 lflag &= ~(ISIG|ICANON|IEXTEN);
396 } else {
397 iflag |= BRKINT|IXON|IMAXBEL;
398 lflag |= ISIG|IEXTEN;
399 if (flags & CBREAK)
400 lflag &= ~ICANON;
401 else
402 lflag |= ICANON;
403 }
404
405 switch (flags & ANYP) {
406 case EVENP:
407 iflag |= INPCK;
408 cflag &= ~PARODD;
409 break;
410 case ODDP:
411 iflag |= INPCK;
412 cflag |= PARODD;
413 break;
414 default:
415 iflag &= ~INPCK;
416 break;
417 }
418
419 if (flags & (RAW|LITOUT|PASS8)) {
420 cflag &= ~(CSIZE|PARENB);
421 cflag |= CS8;
422 if ((flags & (RAW|PASS8)) == 0)
423 iflag |= ISTRIP;
424 else
425 iflag &= ~ISTRIP;
426 if ((flags & (RAW|LITOUT)) == 0)
427 oflag |= OPOST;
428 else
429 oflag &= ~OPOST;
430 } else {
431 cflag &= ~CSIZE;
432 cflag |= CS7|PARENB;
433 iflag |= ISTRIP;
434 oflag |= OPOST;
435 }
436
437 if (flags & PRTERA)
438 lflag |= ECHOPRT;
439 else
440 lflag &= ~ECHOPRT;
441 if (flags & CRTERA)
442 lflag |= ECHOE;
443 else
444 lflag &= ~ECHOE;
445 if (flags & MDMBUF)
446 cflag |= MDMBUF;
447 else
448 cflag &= ~MDMBUF;
449 if (flags & NOHANG)
450 cflag &= ~HUPCL;
451 else
452 cflag |= HUPCL;
453 if (flags & CRTKIL)
454 lflag |= ECHOKE;
455 else
456 lflag &= ~ECHOKE;
457 if (flags & CTLECH)
458 lflag |= ECHOCTL;
459 else
460 lflag &= ~ECHOCTL;
461 if ((flags & DECCTQ) == 0)
462 lflag |= IXANY;
463 else
464 lflag &= ~IXANY;
465 lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH);
466 lflag |= flags & (TOSTOP|FLUSHO|PENDIN|NOFLSH);
467
468 if (flags & (RAW|LITOUT|PASS8)) {
469 cflag &= ~(CSIZE|PARENB);
470 cflag |= CS8;
471 if ((flags & (RAW|PASS8)) == 0)
472 iflag |= ISTRIP;
473 else
474 iflag &= ~ISTRIP;
475 if ((flags & (RAW|LITOUT)) == 0)
476 oflag |= OPOST;
477 else
478 oflag &= ~OPOST;
479 } else {
480 cflag &= ~CSIZE;
481 cflag |= CS7|PARENB;
482 iflag |= ISTRIP;
483 oflag |= OPOST;
484 }
485
486 tmode.c_iflag = iflag;
487 tmode.c_oflag = oflag;
488 tmode.c_cflag = cflag;
489 tmode.c_lflag = lflag;
490}
491#endif
492
493#ifdef XXX_DELAY
494struct delayval {
495 unsigned delay; /* delay in ms */
496 int bits;
497};
498
499/*
500 * below are random guesses, I can't be bothered checking
501 */
502
503struct delayval crdelay[] = {
504 { 1, CR1 },
505 { 2, CR2 },
506 { 3, CR3 },
507 { 83, CR1 },
508 { 166, CR2 },
509 { 0, CR3 },
510};
511
512struct delayval nldelay[] = {
513 { 1, NL1 }, /* special, calculated */
514 { 2, NL2 },
515 { 3, NL3 },
516 { 100, NL2 },
517 { 0, NL3 },
518};
519
520struct delayval bsdelay[] = {
521 { 1, BS1 },
522 { 0, 0 },
523};
524
525struct delayval ffdelay[] = {
526 { 1, FF1 },
527 { 1750, FF1 },
528 { 0, FF1 },
529};
530
531struct delayval tbdelay[] = {
532 { 1, TAB1 },
533 { 2, TAB2 },
534 { 3, XTABS }, /* this is expand tabs */
535 { 100, TAB1 },
536 { 0, TAB2 },
537};
538
539int
540delaybits()
541{
542 register int f;
543
544 f = adelay(CD, crdelay);
545 f |= adelay(ND, nldelay);
546 f |= adelay(FD, ffdelay);
547 f |= adelay(TD, tbdelay);
548 f |= adelay(BD, bsdelay);
549 return (f);
550}
551
552int
553adelay(ms, dp)
554 register ms;
555 register struct delayval *dp;
556{
557 if (ms == 0)
558 return (0);
559 while (dp->delay && ms > dp->delay)
560 dp++;
561 return (dp->bits);
562}
563#endif
564
565char editedhost[32];
566
567void
568edithost(pat)
569 register char *pat;
570{
571 register char *host = HN;
572 register char *res = editedhost;
573
574 if (!pat)
575 pat = "";
576 while (*pat) {
577 switch (*pat) {
578
579 case '#':
580 if (*host)
581 host++;
582 break;
583
584 case '@':
585 if (*host)
586 *res++ = *host++;
587 break;
588
589 default:
590 *res++ = *pat;
591 break;
592
593 }
594 if (res == &editedhost[sizeof editedhost - 1]) {
595 *res = '\0';
596 return;
597 }
598 pat++;
599 }
600 if (*host)
601 strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
602 else
603 *res = '\0';
604 editedhost[sizeof editedhost - 1] = '\0';
605}
606
607void
608makeenv(env)
609 char *env[];
610{
611 static char termbuf[128] = "TERM=";
612 register char *p, *q;
613 register char **ep;
614
615 ep = env;
616 if (TT && *TT) {
617 strcat(termbuf, TT);
618 *ep++ = termbuf;
619 }
620 if (p = EV) {
621 q = p;
622 while (q = strchr(q, ',')) {
623 *q++ = '\0';
624 *ep++ = p;
625 p = q;
626 }
627 if (*p)
628 *ep++ = p;
629 }
630 *ep = (char *)0;
631}
632
633/*
634 * This speed select mechanism is written for the Develcon DATASWITCH.
635 * The Develcon sends a string of the form "B{speed}\n" at a predefined
636 * baud rate. This string indicates the user's actual speed.
637 * The routine below returns the terminal type mapped from derived speed.
638 */
639struct portselect {
640 char *ps_baud;
641 char *ps_type;
642} portspeeds[] = {
643 { "B110", "std.110" },
644 { "B134", "std.134" },
645 { "B150", "std.150" },
646 { "B300", "std.300" },
647 { "B600", "std.600" },
648 { "B1200", "std.1200" },
649 { "B2400", "std.2400" },
650 { "B4800", "std.4800" },
651 { "B9600", "std.9600" },
652 { "B19200", "std.19200" },
653 { 0 }
654};
655
656char *
657portselector()
658{
659 char c, baud[20], *type = "default";
660 register struct portselect *ps;
661 int len;
662
663 alarm(5*60);
664 for (len = 0; len < sizeof (baud) - 1; len++) {
665 if (read(STDIN_FILENO, &c, 1) <= 0)
666 break;
667 c &= 0177;
668 if (c == '\n' || c == '\r')
669 break;
670 if (c == 'B')
671 len = 0; /* in case of leading garbage */
672 baud[len] = c;
673 }
674 baud[len] = '\0';
675 for (ps = portspeeds; ps->ps_baud; ps++)
676 if (strcmp(ps->ps_baud, baud) == 0) {
677 type = ps->ps_type;
678 break;
679 }
680 sleep(2); /* wait for connection to complete */
681 return (type);
682}
683
684/*
685 * This auto-baud speed select mechanism is written for the Micom 600
686 * portselector. Selection is done by looking at how the character '\r'
687 * is garbled at the different speeds.
688 */
689#include <sys/time.h>
690
691char *
692autobaud()
693{
694 int rfds;
695 struct timeval timeout;
696 char c, *type = "9600-baud";
697 int null = 0;
698
699 ioctl(0, TIOCFLUSH, &null);
700 rfds = 1 << 0;
701 timeout.tv_sec = 5;
702 timeout.tv_usec = 0;
703 if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
704 (fd_set *)NULL, &timeout) <= 0)
705 return (type);
706 if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
707 return (type);
708 timeout.tv_sec = 0;
709 timeout.tv_usec = 20;
710 (void) select(32, (fd_set *)NULL, (fd_set *)NULL,
711 (fd_set *)NULL, &timeout);
712 ioctl(0, TIOCFLUSH, &null);
713 switch (c & 0377) {
714
715 case 0200: /* 300-baud */
716 type = "300-baud";
717 break;
718
719 case 0346: /* 1200-baud */
720 type = "1200-baud";
721 break;
722
723 case 015: /* 2400-baud */
724 case 0215:
725 type = "2400-baud";
726 break;
727
728 default: /* 4800-baud */
729 type = "4800-baud";
730 break;
731
732 case 0377: /* 9600-baud */
733 type = "9600-baud";
734 break;
735 }
736 return (type);
737}