2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company *
25 * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
26 * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc. *
27 * (c) Copyright 1993, 1994, 1996 Novell, Inc. *
28 * (c) Copyright 1996 Digital Equipment Corporation. *
29 * (c) Copyright 1996 FUJITSU LIMITED. *
30 * (c) Copyright 1996 Hitachi. *
33 #include "TermHeader.h"
34 #include "TermPrimOSDepI.h"
35 #include "TermPrimDebug.h"
37 #ifdef ALPHA_ARCHITECTURE
38 #include <sys/ioctl.h>
39 #include <sys/ttydev.h>
40 #endif /* ALPHA_ARCHITECTURE */
43 #ifdef HP_ARCHITECTURE
44 #include <sys/ptyio.h>
45 #endif /* HP_ARCHITECTURE */
47 #if defined(HP_ARCHITECTURE) && !(OSMAJORVERSION > 9)
49 #endif /* defined(HP_ARCHITECTURE) && !(OSMAJORVERSION > 9) */
51 #if defined (USE_SETCSMAP)
53 #include <sys/param.h>
54 #endif /* (USE_SETCSMAP) */
56 #ifdef USE_SRIOCSREDIR
57 #include <sys/strredir.h>
59 #endif /* USE_SRIOCSREDIR */
62 #ifdef IBM_ARCHITECTURE
63 #include <sys/ioctl.h>
64 #endif /* IBM_ARCHITECTURE */
66 #endif /* USE_TIOCCONS */
68 #if defined(LINUX_ARCHITECTURE) || defined(OPENBSD_ARCHITECTURE)
69 #include <sys/ioctl.h>
70 #endif /* LINUX_ARCHITECTURE */
73 #include <sys/types.h>
76 #endif /* USE_STREAMS */
78 #if defined (USE_CSWIDTH)
79 #include <sys/ioctl.h>
80 #include <sys/eucioctl.h>
81 #endif /* (USE_CSWIDTH) */
89 #define XTTYMODE_intr 0
90 #define XTTYMODE_quit 1
91 #define XTTYMODE_erase 2
92 #define XTTYMODE_kill 3
93 #define XTTYMODE_eof 4
94 #define XTTYMODE_eol 5
95 #define XTTYMODE_swtch 6
96 #define XTTYMODE_start 7
97 #define XTTYMODE_stop 8
98 #define XTTYMODE_brk 9
99 #define XTTYMODE_susp 10
100 #define XTTYMODE_dsusp 11
101 #define XTTYMODE_rprnt 12
102 #define XTTYMODE_flush 13
103 #define XTTYMODE_weras 14
104 #define XTTYMODE_lnext 15
105 #define NXTTYMODES 16
107 #if defined(CSRG_BASED)
114 #define TAB3 0x00000000
115 #define NLDLY 0x00000000
116 #define CRDLY 0x00000000
117 #define TABDLY 0x00000000
118 #define BSDLY 0x00000000
119 #define VTDLY 0x00000000
120 #define FFDLY 0x00000000
121 #define CBAUD 0x00000000
123 typedef struct _ttyMode
132 ttyMode _DtTermPrimTtyModeList[] =
134 { "intr" , 4, 0, '\0' }, /* tchars.t_intrc ; VINTR */
135 { "quit" , 4, 0, '\0' }, /* tchars.t_quitc ; VQUIT */
136 { "erase", 5, 0, '\0' }, /* sgttyb.sg_erase ; VERASE */
137 { "kill" , 4, 0, '\0' }, /* sgttyb.sg_kill ; VKILL */
138 { "eof" , 3, 0, '\0' }, /* tchars.t_eofc ; VEOF */
139 { "eol" , 3, 0, '\0' }, /* VEOL */
140 { "swtch", 5, 0, '\0' }, /* VSWTCH */
141 { "start", 5, 0, '\0' }, /* tchars.t_startc */
142 { "stop" , 4, 0, '\0' }, /* tchars.t_stopc */
143 { "brk" , 3, 0, '\0' }, /* tchars.t_brkc */
144 { "susp" , 4, 0, '\0' }, /* ltchars.t_suspc */
145 { "dsusp", 5, 0, '\0' }, /* ltchars.t_dsuspc */
146 { "rprnt", 5, 0, '\0' }, /* ltchars.t_rprntc */
147 { "flush", 5, 0, '\0' }, /* ltchars.t_flushc */
148 { "weras", 5, 0, '\0' }, /* ltchars.t_werasc */
149 { "lnext", 5, 0, '\0' }, /* ltchars.t_lnextc */
150 { NULL, 0, 0, '\0' }, /* NULL terminate the array */
165 ** Search to the end of the.
170 ** Skip white space, if this is the end of the list,
173 while (*modeString && isascii(*modeString) && isspace(*modeString))
180 DebugF('p', 2, fprintf(stderr,
181 ">>parseTtyModes() hit end of mode string, return=%d\n",
187 ** Otherwise, see if 'modeString' is in the list of mode names.
189 for (pMode = modeList; pMode->name; pMode++)
191 DebugF('p', 2, fprintf(stderr,
192 ">>parseTtyModes() comparing %.*s to %s\n",
193 pMode->len, modeString, pMode->name));
194 if (strncmp(modeString, pMode->name, pMode->len) == 0)
196 DebugF('p', 2, fprintf(stderr, ">>parseTtyModes() match!\n"));
202 DebugF('p', 2, fprintf(stderr, ">>parseTtyModes() no match\n"));
207 ** Now look for a value for the setting.
208 ** (Skip white space, return an error if no value.)
210 modeString += pMode->len;
211 while (*modeString && isascii(*modeString) && isspace(*modeString))
217 DebugF('p', 2, fprintf(stderr,
218 ">>parseTtyModes() missing value\n"));
222 ** Make sure we handle control characters correctly.
224 if (*modeString == '^')
230 c = ((*modeString == '?') ? 0177 : *modeString & 31);
237 ** Set the values, and get go back for more.
244 /* return(modeCount); */
247 #if defined (USE_CSWIDTH)
248 #define FIND_NUMBER(x, cp) \
251 while (*cp && isdigit(*cp)) \
260 ** parse the cswidth string
261 ** it should be in the form: X1[[:Y1][,X2[:Y2][,X3[:Y3]]]]
274 ** set all cs widths to 0
276 wp->eucw[1] = wp->eucw[2] = wp->eucw[3] = 0;
277 wp->scrw[1] = wp->scrw[2] = wp->scrw[3] = 0;
283 DebugF('p', 4, fprintf(stderr,
284 ">>parseCSWidth(): csWidthString %s\n", cp));
286 for (i = 1; i <= 3; i++)
295 wp->scrw[i] = wp->eucw[i];
314 wp->scrw[i] = wp->eucw[i];
318 DebugF('p', 4, fprintf(stderr,"parseCSWidth():"));
319 DebugF('p', 4, fprintf(stderr,
320 " eucw[1] : %d, scrw[1] : %d\n", wp->eucw[1], wp->scrw[1]));
321 DebugF('p', 4, fprintf(stderr,
322 " eucw[2] : %d, scrw[2] : %d\n", wp->eucw[2], wp->scrw[2]));
323 DebugF('p', 4, fprintf(stderr,
324 " eucw[3] : %d, scrw[3] : %d\n", wp->eucw[3], wp->scrw[3]));
326 #endif /* (USE_CSWIDTH) */
328 void _DtTermPrimPtySendBreak(int pty, int msec)
330 #if defined(USE_TIOCBREAK)
331 (void) ioctl(pty, TIOCBREAK, 0);
332 #elif defined(USE_TCSBRK)
333 (void) ioctl(pty, TCSBRK, 0);
334 #elif defined(USE_TCSENDBREAK)
335 (void) tcsendbreak(pty, 0);
336 #else /* none specified... */
337 #error "There is no RS232 break code specified for this architecture. See TermPrimOSDepI.h for a list of #defines..."
338 #endif /* rs232 break definition... */
341 void _DtTermPrimPtySetWindowSize(int pty, short pixelWidth, short pixelHeight,
342 short characterRows, short characterColumns)
346 ws.ws_row = characterRows;
347 ws.ws_col = characterColumns;
348 ws.ws_xpixel = pixelWidth;
349 ws.ws_ypixel = pixelHeight;
350 (void) ioctl(pty, TIOCSWINSZ, &ws);
353 static struct termios refTio;
354 static int refValid = 0;
356 #if defined (USE_CSWIDTH)
358 ** default width settings for ldterm
360 static eucioc_t refWp;
361 #endif /* (USE_CSWIDTH) */
364 _DtTermPrimPtyGetDefaultModes(void)
369 #if defined (USE_CSWIDTH)
370 struct strioctl i_str;
371 #endif /* (USE_CSWIDTH) */
373 _DtTermProcessLock();
375 /* see if we can get a reference tty to get our base reference from...
377 if ((tty = open("/dev/tty", O_RDONLY, 0)) >= 0) {
378 if (!tcgetattr(tty, &refTio)) {
379 /* we got a valid reference tty... */
380 DebugF('p', 3, fprintf(stderr,
381 ">>_DtTermPrimPtyGetDefaultModes() valid reference \"/dev/tty\"\n"));
387 for (refTty = 0; refTty < 3; refTty++) {
388 if (!tcgetattr(refTty, &refTio)) {
389 DebugF('p', 3, fprintf(stderr,
390 ">>_DtTermPrimPtyGetDefaultModes() valid reference \fd %d\n", refTty));
397 #if defined (USE_CSWIDTH)
398 if (refValid && (MB_CUR_MAX > 1))
401 ** we are in a wide character locale, get the current
404 i_str.ic_cmd = EUC_WGET;
406 i_str.ic_len = sizeof(struct eucioc);
407 i_str.ic_dp = (char *)&refWp;
408 (void)ioctl(refTty, I_STR, &i_str);
410 #endif /* (USE_CSWIDTH) */
414 /* close off the "/dev/tty" fd... */
419 _DtTermProcessUnlock();
432 #if defined (USE_CSWIDTH)
433 struct strioctl i_str;
435 #endif /* (USE_CSWIDTH) */
437 #if defined (USE_SETCSMAP)
439 ** set thing up so we can use setcsmap()
440 ** for the time being, this is IBM specific
442 char path[MAXPATHLEN];
444 #endif /* (USE_SETCSMAP) */
448 if (ioctl(pty, I_PUSH, "ptem") < 0) {
449 (void) perror("I_PUSH ptem");
452 if (ioctl(pty, I_PUSH, "ldterm") < 0) {
453 (void) perror("I_PUSH ldterm");
456 if (ioctl(pty, I_PUSH, "ttcompat") < 0) {
457 (void) perror("I_PUSH ttcompat");
459 #endif /* USE_STREAMS */
463 /* we will start from the reference tty...
465 /* we already got the termios structure. No need to get again... */
466 DebugF('p', 3, fprintf(stderr,
467 ">>_DtTermPrimPtyInit() using refTio\n"));
470 #if defined (USE_CSWIDTH)
472 ** use the cs width information from the reference...
475 #endif /* (USE_CSWIDTH) */
477 /* DKS: are there any other terminal states we need to get?... */
479 /* let's set a reasonable default... */
480 DebugF('p', 3, fprintf(stderr,
481 ">>_DtTermPrimPtyInit() generating default termio\n"));
482 (void) memset(&tio, '\0', sizeof(tio));
484 tio.c_iflag = ICRNL | IXON | IXOFF;
485 tio.c_oflag = OPOST | ONLCR | TAB3;
486 tio.c_cflag = B9600 | CS8 | CREAD | PARENB | HUPCL;
487 tio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE;
488 /* DKS: this is termio specific. Do we need it?...
491 tio.c_cc[VINTR] = 0x7f; /* DEL */
492 tio.c_cc[VQUIT] = '\\' & 0x3f; /* '^\' */
493 tio.c_cc[VERASE] = '#'; /* '#' */
494 tio.c_cc[VKILL] = '@'; /* '@' */
495 tio.c_cc[VEOF] = 'D' & 0x3f; /* '^D' */
496 tio.c_cc[VEOL] = '@' & 0x3f; /* '^@' */
498 tio.c_cc[VSWITCH] = '@' & 0x3f; /* '^@' */
501 #if defined (USE_CSWIDTH)
503 ** get the cs width information from the resource
505 parseCSWidth(csWidthString, &wp);
506 #endif /* (USE_CSWIDTH) */
510 /* now, let's clean up certain flags... */
511 /* input: nl->nl, don't ignore cr, cr->nl
512 * turn on IXOFF pacing so that we can do paste without
513 * overflowing the buffer...
515 tio.c_iflag &= ~(INLCR | IGNCR);
516 tio.c_iflag |= ICRNL | IXOFF;
518 /* output: cr->cr, nl is not return, no delays, nl->cr/nl
520 tio.c_oflag &= ~(OCRNL | ONLRET | NLDLY | CRDLY | TABDLY |
521 BSDLY | VTDLY | FFDLY);
522 tio.c_oflag |= ONLCR;
524 /* baud rate is 9600 (nice default), turn off clocal and turn on
525 * hupcl so that the last close will SIGHUP processes running on
528 tio.c_cflag &= ~(CBAUD | CLOCAL);
529 tio.c_cflag |= B9600 | HUPCL;
531 /* enable signals, canonical processing (erase, kill, etc), echo...
533 tio.c_lflag |= ISIG | ICANON | ECHO | IEXTEN | ECHOCTL | ECHOKE;
535 /* reset EOL to the default value (ksh mucks this up sometimes)...
537 tio.c_cc[VEOL] = '@' & 0x3f; /* '^@' */
539 /* reset EOF to the default value (ksh and csh muck with this)... */
540 tio.c_cc[VEOF] = 'D' & 0x3f; /* '^D' */
543 ** Now its time to handle the ttyModes
544 ** Decide if the user supplied a ttyModes resource, if so then
545 ** parse it and if it was a legal mode string, pass the parse result
547 #define TMODE(ind,var) if (_DtTermPrimTtyModeList[ind].set) var = _DtTermPrimTtyModeList[ind].value;
549 _DtTermProcessLock();
552 if (parseTtyModes(modeString, _DtTermPrimTtyModeList) < 0)
555 ** NOTE: should we prepend the program name to this string?
557 fprintf(stderr, "Bad tty modes \"%s\"\n", modeString);
561 TMODE (XTTYMODE_intr, tio.c_cc[VINTR]);
562 TMODE (XTTYMODE_quit, tio.c_cc[VQUIT]);
563 TMODE (XTTYMODE_erase, tio.c_cc[VERASE]);
564 TMODE (XTTYMODE_kill, tio.c_cc[VKILL]);
565 TMODE (XTTYMODE_eof, tio.c_cc[VEOF]);
566 TMODE (XTTYMODE_eol, tio.c_cc[VEOL]);
568 #if defined(HP_ARCHITECTURE)
569 TMODE (XTTYMODE_swtch, tio.c_cc[VSWTCH]);
570 TMODE (XTTYMODE_susp, tio.c_cc[VSUSP]);
571 #if OSMAJORVERSION > 9
572 /* HP-UX 10.0 supports the new, extended c_cc[] array...
574 TMODE (XTTYMODE_start, tio.c_cc[VSTART]);
575 TMODE (XTTYMODE_stop, tio.c_cc[VSTOP]);
576 TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]);
578 /* the following two parameters are not supported by
581 TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]);
582 TMODE (XTTYMODE_flush, tio.c_cc[VDISCARD]);
584 TMODE (XTTYMODE_weras, tio.c_cc[VWERASE]);
585 TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]);
586 #else /* OSMAJORVERSION > 9 */
588 /* With HP-UX 9.0 (and earlier) we need to set dsuspc
589 * via the ltchars array. In addition, we have no support
590 * for rprnt, flush, weras, and lnext...
594 if (!ioctl(pty, TIOCGLTC, <c)) {
595 TMODE (XTTYMODE_dsusp, ltc.t_dsuspc);
596 (void) ioctl(pty, TIOCSLTC, <c);
599 #endif /* OSMAJORVERSION > 9 */
601 #elif defined(IBM_ARCHITECTURE)
602 TMODE (XTTYMODE_start, tio.c_cc[VSTRT]);
603 TMODE (XTTYMODE_stop, tio.c_cc[VSTOP]);
604 TMODE (XTTYMODE_susp, tio.c_cc[VSUSP]);
605 TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]);
606 TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]);
607 TMODE (XTTYMODE_flush, tio.c_cc[VDISCRD]);
608 TMODE (XTTYMODE_weras, tio.c_cc[VWERSE]);
609 TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]);
611 #elif defined(SUN_ARCHITECTURE)
612 TMODE (XTTYMODE_swtch, tio.c_cc[VSWTCH]);
613 TMODE (XTTYMODE_start, tio.c_cc[VSTART]);
614 TMODE (XTTYMODE_stop, tio.c_cc[VSTOP]);
615 TMODE (XTTYMODE_susp, tio.c_cc[VSUSP]);
616 TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]);
617 TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]);
618 TMODE (XTTYMODE_flush, tio.c_cc[VDISCARD]);
619 TMODE (XTTYMODE_weras, tio.c_cc[VWERASE]);
620 TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]);
622 #elif defined(ALPHA_ARCHITECTURE)
623 TMODE (XTTYMODE_start, tio.c_cc[VSTART]);
624 TMODE (XTTYMODE_stop, tio.c_cc[VSTOP]);
625 TMODE (XTTYMODE_susp, tio.c_cc[VSUSP]);
626 TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]);
627 TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]);
628 TMODE (XTTYMODE_flush, tio.c_cc[VDISCARD]);
629 TMODE (XTTYMODE_weras, tio.c_cc[VWERASE]);
630 TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]);
635 _DtTermProcessUnlock();
637 (void) tcsetattr(pty, TCSADRAIN, &tio);
639 #if defined (USE_CSWIDTH)
643 ** we are in a wide character locale, set the cs
646 i_str.ic_cmd = EUC_WSET;
648 i_str.ic_len = sizeof(struct eucioc);
649 i_str.ic_dp = (char *)℘
650 (void)ioctl(pty, I_STR, &i_str);
652 #endif /* (USE_CSWIDTH) */
654 #if defined (USE_SETCSMAP)
657 ** Setcsmap() only operates on STDIN, so we have to do some
658 ** munging around to map the pty to STDIN in order to get
659 ** the desired result. This may seem wasteful, but it
660 ** makes it easier to encapsulate the OS dependencies in
665 oldStdin = fcntl(0, F_DUPFD, 1);
670 sprintf(path, "%s%s", CSMAP_DIR, nl_langinfo(CODESET));
671 if(access(path, E_ACC|R_ACC) == 0)
681 (void) dup(oldStdin);
682 (void) close(oldStdin);
685 #endif /* (USE_SETCSMAP) */
689 #if defined(USE_TIOCCONS)
690 #ifndef CONSOLE_DEVICE
691 #define CONSOLE_DEVICE "/dev/console"
692 #endif /* CONSOLE_DEVICE */
693 void _DtTermPrimPtyConsoleModeEnable(int pty)
698 /* check to see if we are the owner of the device... */
699 if (!stat(CONSOLE_DEVICE, &st)) {
700 /* stat succeeded... */
701 if (st.st_uid == getuid()) {
702 /* we are the owner, check the access... */
703 if (!access(CONSOLE_DEVICE, R_OK | W_OK)) {
704 /* and we can read/write it... */
705 /* we need to be setuid root... */
706 (void) _DtTermPrimToggleSuidRoot(True);
708 if (ioctl(pty, TIOCCONS, &one)) {
709 /* failure, errno was set... */
710 (void) perror(CONSOLE_DEVICE);
711 (void) fprintf(stderr,
712 "attempt to make tty the console failed\n");
714 /* we no longer need to be suid root... */
715 (void) _DtTermPrimToggleSuidRoot(False);
717 /* we can't read/write it... */
718 (void) perror(CONSOLE_DEVICE);
719 (void) fprintf(stderr, "-C console access denied\n");
722 /* we are not the owner -- return an access owner... */
724 (void) perror(CONSOLE_DEVICE);
725 (void) fprintf(stderr, "-C console access denied\n");
728 /* we were unable to stat the file, errno is already set,
731 (void) perror(CONSOLE_DEVICE);
732 (void) fprintf(stderr, "-C console access denied\n");
737 #elif defined(USE_SRIOCSREDIR)
738 #ifndef CONSOLE_DEVICE
739 #define CONSOLE_DEVICE "/dev/console"
740 #endif /* CONSOLE_DEVICE */
741 void _DtTermPrimPtyConsoleModeEnable(int pty)
746 /* check to see if we are the owner of the device... */
747 if (!stat(CONSOLE_DEVICE, &st)) {
748 /* stat succeeded... */
749 if (st.st_uid == getuid()) {
750 /* we are the owner, open the file... */
751 if ((consoleFd = open("/dev/console", O_RDWR | O_NOCTTY)) >= 0) {
752 if (ioctl(consoleFd, SRIOCSREDIR, pty) == -1) {
753 (void) perror(CONSOLE_DEVICE);
754 (void) fprintf(stderr,
755 "attempt to make tty the console failed\n");
757 (void) close(consoleFd);
759 /* we can't open it for reading and writing... */
760 (void) perror(CONSOLE_DEVICE);
761 (void) fprintf(stderr, "-C console access denied\n");
764 /* we are not the owner -- return an access owner... */
766 (void) perror(CONSOLE_DEVICE);
767 (void) fprintf(stderr, "-C console access denied\n");
770 /* we were unable to stat the file, errno is already set,
773 (void) perror(CONSOLE_DEVICE);
774 (void) fprintf(stderr, "-C console access denied\n");
780 void _DtTermPrimPtyConsoleModeEnable(int pty)
782 (void) fprintf(stderr,
783 "-C console access not supported on this architecture\n");