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 #ifdef VERBOSE_REV_INFO
25 static char rcs_id[] = "$TOG: TermPrimSetPty.c /main/2 1998/04/03 17:11:24 mgreess $";
26 #endif /* VERBOSE_REV_INFO */
30 * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company *
31 * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
32 * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc. *
33 * (c) Copyright 1993, 1994, 1996 Novell, Inc. *
34 * (c) Copyright 1996 Digital Equipment Corporation. *
35 * (c) Copyright 1996 FUJITSU LIMITED. *
36 * (c) Copyright 1996 Hitachi. *
39 #include "TermHeader.h"
40 #include "TermPrimOSDepI.h"
41 #include "TermPrimDebug.h"
43 #ifdef ALPHA_ARCHITECTURE
44 #include <sys/ioctl.h>
45 #include <sys/ttydev.h>
46 #endif /* ALPHA_ARCHITECTURE */
49 #ifdef HP_ARCHITECTURE
50 #include <sys/ptyio.h>
51 #endif /* HP_ARCHITECTURE */
53 #if defined(HP_ARCHITECTURE) && !(OSMAJORVERSION > 9)
55 #endif /* defined(HP_ARCHITECTURE) && !(OSMAJORVERSION > 9) */
57 #if defined (USE_SETCSMAP)
59 #include <sys/param.h>
60 #endif /* (USE_SETCSMAP) */
62 #ifdef USE_SRIOCSREDIR
63 #include <sys/strredir.h>
65 #endif /* USE_SRIOCSREDIR */
68 #ifdef IBM_ARCHITECTURE
69 #include <sys/ioctl.h>
70 #endif /* IBM_ARCHITECTURE */
72 #endif /* USE_TIOCCONS */
74 #if defined(LINUX_ARCHITECTURE) || defined(OPENBSD_ARCHITECTURE)
75 #include <sys/ioctl.h>
76 #endif /* LINUX_ARCHITECTURE */
79 #include <sys/types.h>
82 #endif /* USE_STREAMS */
84 #if defined (USE_CSWIDTH)
85 #include <sys/ioctl.h>
86 #include <sys/eucioctl.h>
87 #endif /* (USE_CSWIDTH) */
95 #define XTTYMODE_intr 0
96 #define XTTYMODE_quit 1
97 #define XTTYMODE_erase 2
98 #define XTTYMODE_kill 3
99 #define XTTYMODE_eof 4
100 #define XTTYMODE_eol 5
101 #define XTTYMODE_swtch 6
102 #define XTTYMODE_start 7
103 #define XTTYMODE_stop 8
104 #define XTTYMODE_brk 9
105 #define XTTYMODE_susp 10
106 #define XTTYMODE_dsusp 11
107 #define XTTYMODE_rprnt 12
108 #define XTTYMODE_flush 13
109 #define XTTYMODE_weras 14
110 #define XTTYMODE_lnext 15
111 #define NXTTYMODES 16
113 #if defined(CSRG_BASED)
120 #define TAB3 0x00000000
121 #define NLDLY 0x00000000
122 #define CRDLY 0x00000000
123 #define TABDLY 0x00000000
124 #define BSDLY 0x00000000
125 #define VTDLY 0x00000000
126 #define FFDLY 0x00000000
127 #define CBAUD 0x00000000
129 typedef struct _ttyMode
138 ttyMode _DtTermPrimTtyModeList[] =
140 { "intr" , 4, 0, '\0' }, /* tchars.t_intrc ; VINTR */
141 { "quit" , 4, 0, '\0' }, /* tchars.t_quitc ; VQUIT */
142 { "erase", 5, 0, '\0' }, /* sgttyb.sg_erase ; VERASE */
143 { "kill" , 4, 0, '\0' }, /* sgttyb.sg_kill ; VKILL */
144 { "eof" , 3, 0, '\0' }, /* tchars.t_eofc ; VEOF */
145 { "eol" , 3, 0, '\0' }, /* VEOL */
146 { "swtch", 5, 0, '\0' }, /* VSWTCH */
147 { "start", 5, 0, '\0' }, /* tchars.t_startc */
148 { "stop" , 4, 0, '\0' }, /* tchars.t_stopc */
149 { "brk" , 3, 0, '\0' }, /* tchars.t_brkc */
150 { "susp" , 4, 0, '\0' }, /* ltchars.t_suspc */
151 { "dsusp", 5, 0, '\0' }, /* ltchars.t_dsuspc */
152 { "rprnt", 5, 0, '\0' }, /* ltchars.t_rprntc */
153 { "flush", 5, 0, '\0' }, /* ltchars.t_flushc */
154 { "weras", 5, 0, '\0' }, /* ltchars.t_werasc */
155 { "lnext", 5, 0, '\0' }, /* ltchars.t_lnextc */
156 { NULL, 0, 0, '\0' }, /* NULL terminate the array */
171 ** Search to the end of the.
176 ** Skip white space, if this is the end of the list,
179 while (*modeString && isascii(*modeString) && isspace(*modeString))
186 DebugF('p', 2, fprintf(stderr,
187 ">>parseTtyModes() hit end of mode string, return=%d\n",
193 ** Otherwise, see if 'modeString' is in the list of mode names.
195 for (pMode = modeList; pMode->name; pMode++)
197 DebugF('p', 2, fprintf(stderr,
198 ">>parseTtyModes() comparing %.*s to %s\n",
199 pMode->len, modeString, pMode->name));
200 if (strncmp(modeString, pMode->name, pMode->len) == 0)
202 DebugF('p', 2, fprintf(stderr, ">>parseTtyModes() match!\n"));
208 DebugF('p', 2, fprintf(stderr, ">>parseTtyModes() no match\n"));
213 ** Now look for a value for the setting.
214 ** (Skip white space, return an error if no value.)
216 modeString += pMode->len;
217 while (*modeString && isascii(*modeString) && isspace(*modeString))
223 DebugF('p', 2, fprintf(stderr,
224 ">>parseTtyModes() missing value\n"));
228 ** Make sure we handle control characters correctly.
230 if (*modeString == '^')
236 c = ((*modeString == '?') ? 0177 : *modeString & 31);
243 ** Set the values, and get go back for more.
250 /* return(modeCount); */
253 #if defined (USE_CSWIDTH)
254 #define FIND_NUMBER(x, cp) \
257 while (*cp && isdigit(*cp)) \
266 ** parse the cswidth string
267 ** it should be in the form: X1[[:Y1][,X2[:Y2][,X3[:Y3]]]]
280 ** set all cs widths to 0
282 wp->eucw[1] = wp->eucw[2] = wp->eucw[3] = 0;
283 wp->scrw[1] = wp->scrw[2] = wp->scrw[3] = 0;
289 DebugF('p', 4, fprintf(stderr,
290 ">>parseCSWidth(): csWidthString %s\n", cp));
292 for (i = 1; i <= 3; i++)
301 wp->scrw[i] = wp->eucw[i];
320 wp->scrw[i] = wp->eucw[i];
324 DebugF('p', 4, fprintf(stderr,"parseCSWidth():"));
325 DebugF('p', 4, fprintf(stderr,
326 " eucw[1] : %d, scrw[1] : %d\n", wp->eucw[1], wp->scrw[1]));
327 DebugF('p', 4, fprintf(stderr,
328 " eucw[2] : %d, scrw[2] : %d\n", wp->eucw[2], wp->scrw[2]));
329 DebugF('p', 4, fprintf(stderr,
330 " eucw[3] : %d, scrw[3] : %d\n", wp->eucw[3], wp->scrw[3]));
332 #endif /* (USE_CSWIDTH) */
334 void _DtTermPrimPtySendBreak(int pty, int msec)
336 #if defined(USE_TIOCBREAK)
337 (void) ioctl(pty, TIOCBREAK, 0);
338 #elif defined(USE_TCSBRK)
339 (void) ioctl(pty, TCSBRK, 0);
340 #elif defined(USE_TCSENDBREAK)
341 (void) tcsendbreak(pty, 0);
342 #else /* none specified... */
343 There is no RS232 break code specified for this architecture. See
344 TermPrimOSDepI.h for a list of #defines...
345 #endif /* rs232 break definition... */
348 void _DtTermPrimPtySetWindowSize(int pty, short pixelWidth, short pixelHeight,
349 short characterRows, short characterColumns)
353 ws.ws_row = characterRows;
354 ws.ws_col = characterColumns;
355 ws.ws_xpixel = pixelWidth;
356 ws.ws_ypixel = pixelHeight;
357 (void) ioctl(pty, TIOCSWINSZ, &ws);
360 static struct termios refTio;
361 static int refValid = 0;
363 #if defined (USE_CSWIDTH)
365 ** default width settings for ldterm
367 static eucioc_t refWp;
368 #endif /* (USE_CSWIDTH) */
371 _DtTermPrimPtyGetDefaultModes()
376 #if defined (USE_CSWIDTH)
377 struct strioctl i_str;
378 #endif /* (USE_CSWIDTH) */
380 _DtTermProcessLock();
382 /* see if we can get a reference tty to get our base reference from...
384 if ((tty = open("/dev/tty", O_RDONLY, 0)) >= 0) {
385 if (!tcgetattr(tty, &refTio)) {
386 /* we got a valid reference tty... */
387 DebugF('p', 3, fprintf(stderr,
388 ">>_DtTermPrimPtyGetDefaultModes() valid reference \"/dev/tty\"\n"));
394 for (refTty = 0; refTty < 3; refTty++) {
395 if (!tcgetattr(refTty, &refTio)) {
396 DebugF('p', 3, fprintf(stderr,
397 ">>_DtTermPrimPtyGetDefaultModes() valid reference \fd %d\n", refTty));
404 #if defined (USE_CSWIDTH)
405 if (refValid && (MB_CUR_MAX > 1))
408 ** we are in a wide character locale, get the current
411 i_str.ic_cmd = EUC_WGET;
413 i_str.ic_len = sizeof(struct eucioc);
414 i_str.ic_dp = (char *)&refWp;
415 (void)ioctl(refTty, I_STR, &i_str);
417 #endif /* (USE_CSWIDTH) */
421 /* close off the "/dev/tty" fd... */
426 _DtTermProcessUnlock();
439 #if defined (USE_CSWIDTH)
440 struct strioctl i_str;
442 #endif /* (USE_CSWIDTH) */
444 #if defined (USE_SETCSMAP)
446 ** set thing up so we can use setcsmap()
447 ** for the time being, this is IBM specific
449 char path[MAXPATHLEN];
451 #endif /* (USE_SETCSMAP) */
455 if (ioctl(pty, I_PUSH, "ptem") < 0) {
456 (void) perror("I_PUSH ptem");
459 if (ioctl(pty, I_PUSH, "ldterm") < 0) {
460 (void) perror("I_PUSH ldterm");
463 if (ioctl(pty, I_PUSH, "ttcompat") < 0) {
464 (void) perror("I_PUSH ttcompat");
466 #endif /* USE_STREAMS */
470 /* we will start from the reference tty...
472 /* we already got the termios structure. No need to get again... */
473 DebugF('p', 3, fprintf(stderr,
474 ">>_DtTermPrimPtyInit() using refTio\n"));
477 #if defined (USE_CSWIDTH)
479 ** use the cs width information from the reference...
482 #endif /* (USE_CSWIDTH) */
484 /* DKS: are there any other terminal states we need to get?... */
486 /* let's set a reasonable default... */
487 DebugF('p', 3, fprintf(stderr,
488 ">>_DtTermPrimPtyInit() generating default termio\n"));
489 (void) memset(&tio, '\0', sizeof(tio));
491 tio.c_iflag = ICRNL | IXON | IXOFF;
492 tio.c_oflag = OPOST | ONLCR | TAB3;
493 tio.c_cflag = B9600 | CS8 | CREAD | PARENB | HUPCL;
494 tio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE;
495 /* DKS: this is termio specific. Do we need it?...
498 tio.c_cc[VINTR] = 0x7f; /* DEL */
499 tio.c_cc[VQUIT] = '\\' & 0x3f; /* '^\' */
500 tio.c_cc[VERASE] = '#'; /* '#' */
501 tio.c_cc[VKILL] = '@'; /* '@' */
502 tio.c_cc[VEOF] = 'D' & 0x3f; /* '^D' */
503 tio.c_cc[VEOL] = '@' & 0x3f; /* '^@' */
505 tio.c_cc[VSWITCH] = '@' & 0x3f; /* '^@' */
508 #if defined (USE_CSWIDTH)
510 ** get the cs width information from the resource
512 parseCSWidth(csWidthString, &wp);
513 #endif /* (USE_CSWIDTH) */
517 /* now, let's clean up certain flags... */
518 /* input: nl->nl, don't ignore cr, cr->nl
519 * turn on IXOFF pacing so that we can do paste without
520 * overflowing the buffer...
522 tio.c_iflag &= ~(INLCR | IGNCR);
523 tio.c_iflag |= ICRNL | IXOFF;
525 /* output: cr->cr, nl is not return, no delays, nl->cr/nl
527 tio.c_oflag &= ~(OCRNL | ONLRET | NLDLY | CRDLY | TABDLY |
528 BSDLY | VTDLY | FFDLY);
529 tio.c_oflag |= ONLCR;
531 /* baud rate is 9600 (nice default), turn off clocal and turn on
532 * hupcl so that the last close will SIGHUP processes running on
535 tio.c_cflag &= ~(CBAUD | CLOCAL);
536 tio.c_cflag |= B9600 | HUPCL;
538 /* enable signals, canonical processing (erase, kill, etc), echo...
540 tio.c_lflag |= ISIG | ICANON | ECHO | IEXTEN | ECHOCTL | ECHOKE;
542 /* reset EOL to the default value (ksh mucks this up sometimes)...
544 tio.c_cc[VEOL] = '@' & 0x3f; /* '^@' */
546 /* reset EOF to the default value (ksh and csh muck with this)... */
547 tio.c_cc[VEOF] = 'D' & 0x3f; /* '^D' */
550 ** Now its time to handle the ttyModes
551 ** Decide if the user supplied a ttyModes resource, if so then
552 ** parse it and if it was a legal mode string, pass the parse result
554 #define TMODE(ind,var) if (_DtTermPrimTtyModeList[ind].set) var = _DtTermPrimTtyModeList[ind].value;
556 _DtTermProcessLock();
559 if (parseTtyModes(modeString, _DtTermPrimTtyModeList) < 0)
562 ** NOTE: should we prepend the program name to this string?
564 fprintf(stderr, "Bad tty modes \"%s\"\n", modeString);
568 TMODE (XTTYMODE_intr, tio.c_cc[VINTR]);
569 TMODE (XTTYMODE_quit, tio.c_cc[VQUIT]);
570 TMODE (XTTYMODE_erase, tio.c_cc[VERASE]);
571 TMODE (XTTYMODE_kill, tio.c_cc[VKILL]);
572 TMODE (XTTYMODE_eof, tio.c_cc[VEOF]);
573 TMODE (XTTYMODE_eol, tio.c_cc[VEOL]);
575 #if defined(HP_ARCHITECTURE)
576 TMODE (XTTYMODE_swtch, tio.c_cc[VSWTCH]);
577 TMODE (XTTYMODE_susp, tio.c_cc[VSUSP]);
578 #if OSMAJORVERSION > 9
579 /* HP-UX 10.0 supports the new, extended c_cc[] array...
581 TMODE (XTTYMODE_start, tio.c_cc[VSTART]);
582 TMODE (XTTYMODE_stop, tio.c_cc[VSTOP]);
583 TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]);
585 /* the following two parameters are not supported by
588 TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]);
589 TMODE (XTTYMODE_flush, tio.c_cc[VDISCARD]);
591 TMODE (XTTYMODE_weras, tio.c_cc[VWERASE]);
592 TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]);
593 #else /* OSMAJORVERSION > 9 */
595 /* With HP-UX 9.0 (and earlier) we need to set dsuspc
596 * via the ltchars array. In addition, we have no support
597 * for rprnt, flush, weras, and lnext...
601 if (!ioctl(pty, TIOCGLTC, <c)) {
602 TMODE (XTTYMODE_dsusp, ltc.t_dsuspc);
603 (void) ioctl(pty, TIOCSLTC, <c);
606 #endif /* OSMAJORVERSION > 9 */
608 #elif defined(IBM_ARCHITECTURE)
609 TMODE (XTTYMODE_start, tio.c_cc[VSTRT]);
610 TMODE (XTTYMODE_stop, tio.c_cc[VSTOP]);
611 TMODE (XTTYMODE_susp, tio.c_cc[VSUSP]);
612 TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]);
613 TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]);
614 TMODE (XTTYMODE_flush, tio.c_cc[VDISCRD]);
615 TMODE (XTTYMODE_weras, tio.c_cc[VWERSE]);
616 TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]);
618 #elif defined(SUN_ARCHITECTURE)
619 TMODE (XTTYMODE_swtch, tio.c_cc[VSWTCH]);
620 TMODE (XTTYMODE_start, tio.c_cc[VSTART]);
621 TMODE (XTTYMODE_stop, tio.c_cc[VSTOP]);
622 TMODE (XTTYMODE_susp, tio.c_cc[VSUSP]);
623 TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]);
624 TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]);
625 TMODE (XTTYMODE_flush, tio.c_cc[VDISCARD]);
626 TMODE (XTTYMODE_weras, tio.c_cc[VWERASE]);
627 TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]);
629 #elif defined(ALPHA_ARCHITECTURE)
630 TMODE (XTTYMODE_start, tio.c_cc[VSTART]);
631 TMODE (XTTYMODE_stop, tio.c_cc[VSTOP]);
632 TMODE (XTTYMODE_susp, tio.c_cc[VSUSP]);
633 TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]);
634 TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]);
635 TMODE (XTTYMODE_flush, tio.c_cc[VDISCARD]);
636 TMODE (XTTYMODE_weras, tio.c_cc[VWERASE]);
637 TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]);
642 _DtTermProcessUnlock();
644 (void) tcsetattr(pty, TCSADRAIN, &tio);
646 #if defined (USE_CSWIDTH)
650 ** we are in a wide character locale, set the cs
653 i_str.ic_cmd = EUC_WSET;
655 i_str.ic_len = sizeof(struct eucioc);
656 i_str.ic_dp = (char *)℘
657 (void)ioctl(pty, I_STR, &i_str);
659 #endif /* (USE_CSWIDTH) */
661 #if defined (USE_SETCSMAP)
664 ** Setcsmap() only operates on STDIN, so we have to do some
665 ** munging around to map the pty to STDIN in order to get
666 ** the desired result. This may seem wasteful, but it
667 ** makes it easier to encapsulate the OS dependencies in
672 oldStdin = fcntl(0, F_DUPFD, 1);
677 sprintf(path, "%s%s", CSMAP_DIR, nl_langinfo(CODESET));
678 if(access(path, E_ACC|R_ACC) == 0)
688 (void) dup(oldStdin);
689 (void) close(oldStdin);
692 #endif /* (USE_SETCSMAP) */
696 #if defined(USE_TIOCCONS)
697 #ifndef CONSOLE_DEVICE
698 #define CONSOLE_DEVICE "/dev/console"
699 #endif /* CONSOLE_DEVICE */
700 void _DtTermPrimPtyConsoleModeEnable(int pty)
705 /* check to see if we are the owner of the device... */
706 if (!stat(CONSOLE_DEVICE, &st)) {
707 /* stat succeeded... */
708 if (st.st_uid == getuid()) {
709 /* we are the owner, check the access... */
710 if (!access(CONSOLE_DEVICE, R_OK | W_OK)) {
711 /* and we can read/write it... */
712 /* we need to be setuid root... */
713 (void) _DtTermPrimToggleSuidRoot(True);
715 if (ioctl(pty, TIOCCONS, &one)) {
716 /* failure, errno was set... */
717 (void) perror(CONSOLE_DEVICE);
718 (void) fprintf(stderr,
719 "attempt to make tty the console failed\n");
721 /* we no longer need to be suid root... */
722 (void) _DtTermPrimToggleSuidRoot(False);
724 /* we can't read/write it... */
725 (void) perror(CONSOLE_DEVICE);
726 (void) fprintf(stderr, "-C console access denied\n");
729 /* we are not the owner -- return an access owner... */
731 (void) perror(CONSOLE_DEVICE);
732 (void) fprintf(stderr, "-C console access denied\n");
735 /* we were unable to stat the file, errno is already set,
738 (void) perror(CONSOLE_DEVICE);
739 (void) fprintf(stderr, "-C console access denied\n");
744 #elif defined(USE_SRIOCSREDIR)
745 #ifndef CONSOLE_DEVICE
746 #define CONSOLE_DEVICE "/dev/console"
747 #endif /* CONSOLE_DEVICE */
748 void _DtTermPrimPtyConsoleModeEnable(int pty)
753 /* check to see if we are the owner of the device... */
754 if (!stat(CONSOLE_DEVICE, &st)) {
755 /* stat succeeded... */
756 if (st.st_uid == getuid()) {
757 /* we are the owner, open the file... */
758 if ((consoleFd = open("/dev/console", O_RDWR | O_NOCTTY)) >= 0) {
759 if (ioctl(consoleFd, SRIOCSREDIR, pty) == -1) {
760 (void) perror(CONSOLE_DEVICE);
761 (void) fprintf(stderr,
762 "attempt to make tty the console failed\n");
764 (void) close(consoleFd);
766 /* we can't open it for reading and writing... */
767 (void) perror(CONSOLE_DEVICE);
768 (void) fprintf(stderr, "-C console access denied\n");
771 /* we are not the owner -- return an access owner... */
773 (void) perror(CONSOLE_DEVICE);
774 (void) fprintf(stderr, "-C console access denied\n");
777 /* we were unable to stat the file, errno is already set,
780 (void) perror(CONSOLE_DEVICE);
781 (void) fprintf(stderr, "-C console access denied\n");
787 void _DtTermPrimPtyConsoleModeEnable(int pty)
789 (void) fprintf(stderr,
790 "-C console access not supported on this architecture\n");