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