Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / lib / DtTerm / TermPrim / TermPrimSetPty.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23 /*                                                                      *
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.                                          *
31  */
32
33 #include "TermHeader.h"
34 #include "TermPrimOSDepI.h"
35 #include "TermPrimDebug.h"
36 #include <fcntl.h>
37 #ifdef  ALPHA_ARCHITECTURE
38 #include <sys/ioctl.h>
39 #include <sys/ttydev.h>
40 #endif /* ALPHA_ARCHITECTURE */
41 #include <termios.h>
42 #ifdef  USE_PTYS
43 #ifdef  HP_ARCHITECTURE
44 #include <sys/ptyio.h>
45 #endif  /* HP_ARCHITECTURE */
46 #endif  /* USE_PTYS */
47 #if     defined(HP_ARCHITECTURE) && !(OSMAJORVERSION > 9)
48 #include <bsdtty.h>
49 #endif  /* defined(HP_ARCHITECTURE) && !(OSMAJORVERSION > 9) */
50
51 #if defined (USE_SETCSMAP)
52 #include <langinfo.h>
53 #include <sys/param.h>
54 #endif   /* (USE_SETCSMAP) */
55
56 #ifdef  USE_SRIOCSREDIR
57 #include <sys/strredir.h>
58 #include <sys/stat.h>
59 #endif  /* USE_SRIOCSREDIR */
60
61 #ifdef  USE_TIOCCONS
62 #ifdef  IBM_ARCHITECTURE
63 #include <sys/ioctl.h>
64 #endif  /* IBM_ARCHITECTURE */
65 #include <sys/stat.h>
66 #endif  /* USE_TIOCCONS */
67
68 #if defined(LINUX_ARCHITECTURE) || defined(OPENBSD_ARCHITECTURE)
69 #include <sys/ioctl.h>
70 #endif /* LINUX_ARCHITECTURE */
71
72 #ifdef  USE_STREAMS
73 #include <sys/types.h>
74 #include <stropts.h>
75 #include <sys/conf.h>
76 #endif  /* USE_STREAMS */
77
78 #if defined (USE_CSWIDTH)
79 #include <sys/ioctl.h>
80 #include <sys/eucioctl.h>
81 #endif   /* (USE_CSWIDTH) */
82
83 #include <sys/wait.h>
84 #include <ctype.h>
85 #include <errno.h>
86 #include <signal.h>
87 #include <Xm/Xm.h>
88
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
106
107 #if defined(CSRG_BASED)
108 #ifdef TAB3
109 #undef TAB3
110 #endif
111 #ifdef TABDLY
112 #undef TABDLY
113 #endif
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
122 #endif
123 typedef struct _ttyMode
124 {
125     char    *name;
126     int      len;
127     int      set;
128     char     value;
129 }
130 ttyMode;
131
132 ttyMode _DtTermPrimTtyModeList[] = 
133 {
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 */
151 };
152
153 static int
154 parseTtyModes
155 (
156     char    *modeString,
157     ttyMode *modeList
158 )
159 {
160     ttyMode    *pMode;
161     int         c;
162     int         modeCount = 0;
163
164     /*
165     ** Search to the end of the.
166     */
167
168     while (1) {
169         /*
170         ** Skip white space,  if this is the end of the list,
171         ** return.
172         */
173         while (*modeString && isascii(*modeString) && isspace(*modeString))
174         {
175              modeString++;
176         }
177
178         if (!*modeString) 
179         {
180             DebugF('p', 2, fprintf(stderr,
181                     ">>parseTtyModes() hit end of mode string, return=%d\n",
182                     modeCount));
183             return(modeCount);
184         }
185
186         /*
187         ** Otherwise, see if 'modeString' is in the list of mode names.
188         */
189         for (pMode = modeList; pMode->name; pMode++)
190         {
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)
195             {
196                 DebugF('p', 2, fprintf(stderr, ">>parseTtyModes() match!\n"));
197                 break;
198             }
199         }
200         if (!pMode->name) 
201         {
202             DebugF('p', 2, fprintf(stderr, ">>parseTtyModes() no match\n"));
203             return(-1);
204         }
205
206         /*
207         ** Now look for a value for the setting.
208         ** (Skip white space, return an error if no value.)
209         */
210         modeString += pMode->len;
211         while (*modeString && isascii(*modeString) && isspace(*modeString))
212         {
213             modeString++;
214         }
215         if (!*modeString)
216         {
217             DebugF('p', 2, fprintf(stderr,
218                     ">>parseTtyModes() missing value\n"));
219             return(-1);
220         }
221         /*
222         ** Make sure we handle control characters correctly.
223         */
224         if (*modeString == '^')
225         {
226             modeString++;
227             /*
228             ** keep control bits
229             */
230             c = ((*modeString == '?') ? 0177 : *modeString & 31);
231         } 
232         else
233         {
234             c = *modeString;
235         }
236         /*
237         ** Set the values, and get go back for more.
238         */
239         pMode->value = c;
240         pMode->set   = 1;
241         modeCount++;
242         modeString++;
243     }
244     /* return(modeCount); */
245 }
246
247 #if defined (USE_CSWIDTH)
248 #define FIND_NUMBER(x, cp) \
249 { \
250     x = 0; \
251     while (*cp && isdigit(*cp)) \
252     { \
253         x *= 10; \
254         x += (*cp - '0'); \
255         cp++; \
256     } \
257 }
258
259 /*
260 ** parse the cswidth string
261 ** it should be in the form: X1[[:Y1][,X2[:Y2][,X3[:Y3]]]]
262 */
263 static void
264 parseCSWidth
265 (
266     char *cp,
267     eucioc_t *wp
268 )
269 {
270     int x;
271     int i;
272     
273     /*
274     ** set all cs widths to 0
275     */
276     wp->eucw[1] = wp->eucw[2] = wp->eucw[3] = 0;
277     wp->scrw[1] = wp->scrw[2] = wp->scrw[3] = 0;
278     if (!cp)
279     {
280         return;
281     }
282
283     DebugF('p', 4, fprintf(stderr,
284             ">>parseCSWidth(): csWidthString %s\n", cp));
285
286     for (i = 1; i <= 3; i++)
287     {
288         /*
289         ** read Xn
290         */
291         FIND_NUMBER(x, cp);
292         wp->eucw[i] = x;
293         if (!*cp)
294         {
295             wp->scrw[i] = wp->eucw[i];
296             return;
297         }
298
299         /*
300         ** Yn might exist
301         */
302         if (*cp == ':')
303         {
304             cp++;
305             FIND_NUMBER(x, cp);
306             wp->scrw[i] = x;
307             if (!*cp)
308             {
309                 return;
310             }
311         }
312         else
313         {
314             wp->scrw[i] = wp->eucw[i];
315         }
316         cp++;
317     }
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]));
325 }
326 #endif   /* (USE_CSWIDTH) */
327
328 void _DtTermPrimPtySendBreak(int pty, int msec)
329 {
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... */
339 }
340
341 void _DtTermPrimPtySetWindowSize(int pty, short pixelWidth, short pixelHeight,
342         short characterRows, short characterColumns)
343 {
344     struct winsize ws;
345
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);
351 }
352
353 static struct termios refTio;
354 static int refValid = 0;
355
356 #if defined (USE_CSWIDTH)
357 /*
358 ** default width settings for ldterm
359 */
360 static eucioc_t refWp;
361 #endif   /* (USE_CSWIDTH) */
362
363 void
364 _DtTermPrimPtyGetDefaultModes(void)
365 {
366     int tty = -1;
367     int refTty = -1;
368
369 #if defined (USE_CSWIDTH)
370     struct strioctl i_str;
371 #endif   /* (USE_CSWIDTH) */
372
373     _DtTermProcessLock();
374     if (!refValid) {
375         /* see if we can get a reference tty to get our base reference from...
376          */
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"));
382                 refValid = 1;
383             }
384         }
385
386         if (!refValid) {
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));
391                     refValid = 1;
392                     break;
393                 }
394             }
395         }
396
397 #if defined (USE_CSWIDTH)
398         if (refValid && (MB_CUR_MAX > 1))
399         {
400             /*
401             ** we are in a wide character locale, get the current
402             ** width settings...
403             */
404             i_str.ic_cmd    = EUC_WGET;
405             i_str.ic_timout = 0;
406             i_str.ic_len    = sizeof(struct eucioc);
407             i_str.ic_dp     = (char *)&refWp;
408             (void)ioctl(refTty, I_STR, &i_str);
409         }
410 #endif   /* (USE_CSWIDTH) */
411
412         /* all done...
413          */
414         /* close off the "/dev/tty" fd... */
415         if (tty >= 0) {
416             (void) close(tty);
417         }
418     }
419     _DtTermProcessUnlock();
420 }
421
422 void
423 _DtTermPrimPtyInit
424 (
425     int   pty,
426     char *modeString,
427     char *csWidthString
428 )
429 {
430     struct termios tio;
431
432 #if defined (USE_CSWIDTH)
433     struct strioctl i_str;
434     eucioc_t        wp;
435 #endif   /* (USE_CSWIDTH) */
436
437 #if defined (USE_SETCSMAP)
438     /*
439     ** set thing up so we can use setcsmap()
440     ** for the time being, this is IBM specific
441     */
442     char path[MAXPATHLEN];
443     int  oldStdin = -1;
444 #endif   /* (USE_SETCSMAP) */
445
446 #ifdef  NOTDEF
447 #ifdef  USE_STREAMS
448     if (ioctl(pty, I_PUSH, "ptem") < 0) {
449         (void) perror("I_PUSH ptem");
450     }
451
452     if (ioctl(pty, I_PUSH, "ldterm") < 0) {
453         (void) perror("I_PUSH ldterm");
454     }
455
456     if (ioctl(pty, I_PUSH, "ttcompat") < 0) {
457         (void) perror("I_PUSH ttcompat");
458     }
459 #endif  /* USE_STREAMS */
460 #endif  /* NOTDEF */
461
462     if (refValid) {
463         /* we will start from the reference tty...
464          */
465         /* we already got the termios structure.  No need to get again... */
466         DebugF('p', 3, fprintf(stderr,
467                 ">>_DtTermPrimPtyInit() using refTio\n"));
468         tio = refTio;
469
470 #if defined (USE_CSWIDTH)
471         /*
472         ** use the cs width information from the reference...
473         */
474         wp  = refWp;
475 #endif   /* (USE_CSWIDTH) */
476         
477         /* DKS: are there any other terminal states we need to get?... */
478     } else {
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));
483
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?...
489         tio.c_line        = 0;
490         */
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;   /* '^@'         */
497 #ifdef VSWITCH
498         tio.c_cc[VSWITCH] = '@' & 0x3f;   /* '^@'         */
499 #endif  /* VSWITCH */
500
501 #if defined (USE_CSWIDTH)
502         /*
503         ** get the cs width information from the resource
504         */
505         parseCSWidth(csWidthString, &wp);
506 #endif   /* (USE_CSWIDTH) */
507
508     }
509
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...
514      */
515     tio.c_iflag &= ~(INLCR | IGNCR);
516     tio.c_iflag |=   ICRNL | IXOFF;
517
518     /* output: cr->cr, nl is not return, no delays, nl->cr/nl
519      */
520     tio.c_oflag &= ~(OCRNL | ONLRET | NLDLY | CRDLY | TABDLY |
521                      BSDLY | VTDLY  | FFDLY);
522     tio.c_oflag |=   ONLCR;
523
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
526      * the tty...
527      */
528     tio.c_cflag &= ~(CBAUD | CLOCAL);
529     tio.c_cflag |= B9600 | HUPCL;
530
531     /* enable signals, canonical processing (erase, kill, etc), echo...
532      */
533     tio.c_lflag |= ISIG | ICANON | ECHO | IEXTEN | ECHOCTL | ECHOKE;
534
535     /* reset EOL to the default value (ksh mucks this up sometimes)...
536      */
537     tio.c_cc[VEOL] = '@' & 0x3f;                        /* '^@' */
538
539     /* reset EOF to the default value (ksh and csh muck with this)... */
540     tio.c_cc[VEOF] = 'D' & 0x3f;                        /* '^D' */
541
542     /* 
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
546     */
547 #define TMODE(ind,var) if (_DtTermPrimTtyModeList[ind].set) var = _DtTermPrimTtyModeList[ind].value;
548
549     _DtTermProcessLock();
550     if (modeString)
551     {
552         if (parseTtyModes(modeString, _DtTermPrimTtyModeList) < 0)
553         {
554             /*
555             ** NOTE: should we prepend the program name to this string?
556             */
557             fprintf(stderr, "Bad tty modes \"%s\"\n", modeString);
558         }
559         else
560         {
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]);
567
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...
573              */
574             TMODE (XTTYMODE_start, tio.c_cc[VSTART]);
575             TMODE (XTTYMODE_stop,  tio.c_cc[VSTOP]);
576             TMODE (XTTYMODE_dsusp, tio.c_cc[VDSUSP]);
577 #ifdef  NOTDEF
578             /* the following two parameters are not supported by
579              * HP-UX 10.0.
580              */
581             TMODE (XTTYMODE_rprnt, tio.c_cc[VREPRINT]);
582             TMODE (XTTYMODE_flush, tio.c_cc[VDISCARD]);
583 #endif  /* NOTDEF */
584             TMODE (XTTYMODE_weras, tio.c_cc[VWERASE]);
585             TMODE (XTTYMODE_lnext, tio.c_cc[VLNEXT]);
586 #else   /* OSMAJORVERSION > 9 */
587             {
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...
591                  */
592                 struct ltchars ltc;
593
594                 if (!ioctl(pty, TIOCGLTC, &ltc)) {
595                     TMODE (XTTYMODE_dsusp, ltc.t_dsuspc);
596                     (void) ioctl(pty, TIOCSLTC, &ltc);
597                 }
598             }
599 #endif  /* OSMAJORVERSION > 9 */
600
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]);
610
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]);
621
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]);
631 #endif
632         }
633 #undef TMODE
634     }
635     _DtTermProcessUnlock();
636     
637     (void) tcsetattr(pty, TCSADRAIN, &tio);
638
639 #if defined (USE_CSWIDTH)
640     if (MB_CUR_MAX > 1)
641     {
642         /*
643         ** we are in a wide character locale, set the cs
644         ** width settings...
645         */
646         i_str.ic_cmd    = EUC_WSET;
647         i_str.ic_timout = 0;
648         i_str.ic_len    = sizeof(struct eucioc);
649         i_str.ic_dp     = (char *)&wp;
650         (void)ioctl(pty, I_STR, &i_str);
651     }
652 #endif   /* (USE_CSWIDTH) */
653
654 #if defined (USE_SETCSMAP)
655     /*
656     ** NOTE:
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
661     **     this function.
662     */
663     if (pty != 0)
664     {
665         oldStdin = fcntl(0, F_DUPFD, 1);
666         (void) close(0);
667         (void) dup(pty);
668     }
669
670     sprintf(path, "%s%s", CSMAP_DIR, nl_langinfo(CODESET));
671     if(access(path, E_ACC|R_ACC) == 0)
672     {
673         setcsmap(path);
674     }
675         
676     if (pty != 0)
677     {
678         (void) close(0);
679         if (oldStdin >= 0)
680         {
681             (void) dup(oldStdin);
682             (void) close(oldStdin);
683         }
684     }
685 #endif   /* (USE_SETCSMAP) */
686 }
687
688
689 #if     defined(USE_TIOCCONS)
690 #ifndef CONSOLE_DEVICE
691 #define CONSOLE_DEVICE  "/dev/console"
692 #endif  /* CONSOLE_DEVICE */
693 void _DtTermPrimPtyConsoleModeEnable(int pty)
694 {
695     struct stat           st;
696     int                   one = 1;
697
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);
707
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");
713                 }
714                 /* we no longer need to be suid root... */
715                 (void) _DtTermPrimToggleSuidRoot(False);
716             } else {
717                 /* we can't read/write it... */
718                 (void) perror(CONSOLE_DEVICE);
719                 (void) fprintf(stderr, "-C console access denied\n");
720             }
721         } else {
722             /* we are not the owner -- return an access owner... */
723             errno = EACCES;
724             (void) perror(CONSOLE_DEVICE);
725             (void) fprintf(stderr, "-C console access denied\n");
726         }
727     } else {
728         /* we were unable to stat the file, errno is already set,
729          * failure...
730          */
731         (void) perror(CONSOLE_DEVICE);
732         (void) fprintf(stderr, "-C console access denied\n");
733     }
734 }
735
736
737 #elif   defined(USE_SRIOCSREDIR)
738 #ifndef CONSOLE_DEVICE
739 #define CONSOLE_DEVICE  "/dev/console"
740 #endif  /* CONSOLE_DEVICE */
741 void _DtTermPrimPtyConsoleModeEnable(int pty)
742 {
743     struct stat           st;
744     int                   consoleFd;
745
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");
756                 }
757                 (void) close(consoleFd);
758             } else {
759                 /* we can't open it for reading and writing... */
760                 (void) perror(CONSOLE_DEVICE);
761                 (void) fprintf(stderr, "-C console access denied\n");
762             }
763         } else {
764             /* we are not the owner -- return an access owner... */
765             errno = EACCES;
766             (void) perror(CONSOLE_DEVICE);
767             (void) fprintf(stderr, "-C console access denied\n");
768         }
769     } else {
770         /* we were unable to stat the file, errno is already set,
771          * failure...
772          */
773         (void) perror(CONSOLE_DEVICE);
774         (void) fprintf(stderr, "-C console access denied\n");
775     }
776 }
777
778
779 #else
780 void _DtTermPrimPtyConsoleModeEnable(int pty)
781 {
782     (void) fprintf(stderr,
783             "-C console access not supported on this architecture\n");
784 }
785 #endif