root/foundation-apps/mxterm-maxx/os2main.c

Revision 8, 61.0 KB (checked in by emasson, 3 years ago)

initial import for the community edition

Line 
1/* $XTermId: os2main.c,v 1.255 2007/11/30 01:25:03 tom Exp $ */
2
3/* removed all foreign stuff to get the code more clear (hv)
4 * and did some rewrite for the obscure OS/2 environment
5 */
6
7/***********************************************************
8
9Copyright (c) 1987, 1988  X Consortium
10
11Permission is hereby granted, free of charge, to any person obtaining a copy
12of this software and associated documentation files (the "Software"), to deal
13in the Software without restriction, including without limitation the rights
14to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15copies of the Software, and to permit persons to whom the Software is
16furnished to do so, subject to the following conditions:
17
18The above copyright notice and this permission notice shall be included in
19all copies or substantial portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28Except as contained in this notice, the name of the X Consortium shall not be
29used in advertising or otherwise to promote the sale, use or other dealings
30in this Software without prior written authorization from the X Consortium.
31
32Copyright 1987, 1988 by Digital Equipment Corporation, Maynard.
33
34                        All Rights Reserved
35
36Permission to use, copy, modify, and distribute this software and its
37documentation for any purpose and without fee is hereby granted,
38provided that the above copyright notice appear in all copies and that
39both that copyright notice and this permission notice appear in
40supporting documentation, and that the name of Digital not be used in
41advertising or publicity pertaining to distribution of the software
42without specific, written prior permission.
43
44DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
45ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
46DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
47ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
48WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
49ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
50SOFTWARE.
51
52******************************************************************/
53
54/* os2main.c */
55#define INCL_DOSFILEMGR
56#define INCL_DOSDEVIOCTL
57#define INCL_DOSSEMAPHORES
58#ifdef __INNOTEK_LIBC__
59#define INCL_DOSDEVICES
60#endif
61#define I_NEED_OS2_H
62#include <os2.h>
63#define XTERM_MAIN
64
65#define RES_OFFSET(field)       XtOffsetOf(XTERM_RESOURCE, field)
66
67#include <xterm.h>
68
69#include <X11/cursorfont.h>
70#ifdef I18N
71#include <X11/Xlocale.h>
72#endif
73
74#if OPT_TOOLBAR
75
76#if defined(HAVE_LIB_XAW)
77#include <X11/Xaw/Form.h>
78#elif defined(HAVE_LIB_XAW3D)
79#include <X11/Xaw3d/Form.h>
80#elif defined(HAVE_LIB_NEXTAW)
81#include <X11/neXtaw/Form.h>
82#elif defined(HAVE_LIB_XAWPLUS)
83#include <X11/XawPlus/Form.h>
84#endif
85
86#endif /* OPT_TOOLBAR */
87
88#include <pwd.h>
89#include <ctype.h>
90
91#include <data.h>
92#include <error.h>
93#include <menu.h>
94#include <main.h>
95#include <xstrings.h>
96#include <xtermcap.h>
97#include <xterm_io.h>
98
99#if OPT_WIDE_CHARS
100#include <charclass.h>
101#endif
102
103int
104setpgrp(pid_t pid, gid_t pgid)
105{
106    return 0;
107}
108
109int
110chown(const char *fn, pid_t pid, gid_t gid)
111{
112    return 0;
113}
114
115char *
116ttyname(int fd)
117{
118    return "/dev/tty";
119}
120
121#include <sys/stat.h>
122#include <sys/param.h>          /* for NOFILE */
123#include <stdio.h>
124#include <signal.h>
125
126static SIGNAL_T reapchild(int n);
127static int spawnXTerm(XtermWidget /* xw */ );
128static void resize_termcap(XtermWidget xw, char *newtc);
129static void set_owner(char *device, uid_t uid, gid_t gid, mode_t mode);
130
131static Bool added_utmp_entry = False;
132
133static uid_t save_ruid;
134static gid_t save_rgid;
135
136/*
137** Ordinarily it should be okay to omit the assignment in the following
138** statement. Apparently the c89 compiler on AIX 4.1.3 has a bug, or does
139** it? Without the assignment though the compiler will init command_to_exec
140** to 0xffffffff instead of NULL; and subsequent usage, e.g. in spawnXTerm() to
141** SEGV.
142*/
143static char **command_to_exec = NULL;
144
145#if OPT_LUIT_PROG
146static char **command_to_exec_with_luit = NULL;
147#endif
148
149/* The following structures are initialized in main() in order
150** to eliminate any assumptions about the internal order of their
151** contents.
152*/
153static struct termio d_tio;
154
155/* allow use of system default characters if defined and reasonable */
156#ifndef CEOF
157#define CEOF CONTROL('D')
158#endif
159#ifndef CEOL
160#define CEOL 0
161#endif
162#ifndef CFLUSH
163#define CFLUSH CONTROL('O')
164#endif
165#ifndef CLNEXT
166#define CLNEXT CONTROL('V')
167#endif
168#ifndef CNUL
169#define CNUL 0
170#endif
171#ifndef CQUIT
172#define CQUIT CONTROL('\\')
173#endif
174#ifndef CRPRNT
175#define CRPRNT CONTROL('R')
176#endif
177#ifndef CSTART
178#define CSTART CONTROL('Q')
179#endif
180#ifndef CSTOP
181#define CSTOP CONTROL('S')
182#endif
183#ifndef CSUSP
184#define CSUSP CONTROL('Z')
185#endif
186#ifndef CSWTCH
187#define CSWTCH 0
188#endif
189#ifndef CWERASE
190#define CWERASE CONTROL('W')
191#endif
192
193#define TERMIO_STRUCT struct termio
194
195/*
196 * SYSV has the termio.c_cc[V] and ltchars; BSD has tchars and ltchars;
197 * SVR4 has only termio.c_cc, but it includes everything from ltchars.
198 * POSIX termios has termios.c_cc, which is similar to SVR4.
199 */
200#define TTYMODE(name) { name, sizeof(name)-1, 0, 0 }
201static int override_tty_modes = 0;
202/* *INDENT-OFF* */
203static struct _xttymodes {
204    char *name;
205    size_t len;
206    int set;
207    Char value;
208} ttymodelist[] = {
209    TTYMODE("intr"),            /* tchars.t_intrc ; VINTR */
210#define XTTYMODE_intr   0
211    TTYMODE("quit"),            /* tchars.t_quitc ; VQUIT */
212#define XTTYMODE_quit   1
213    TTYMODE("erase"),           /* sgttyb.sg_erase ; VERASE */
214#define XTTYMODE_erase  2
215    TTYMODE("kill"),            /* sgttyb.sg_kill ; VKILL */
216#define XTTYMODE_kill   3
217    TTYMODE("eof"),             /* tchars.t_eofc ; VEOF */
218#define XTTYMODE_eof    4
219    TTYMODE("eol"),             /* VEOL */
220#define XTTYMODE_eol    5
221    TTYMODE("swtch"),           /* VSWTCH */
222#define XTTYMODE_swtch  6
223    TTYMODE("start"),           /* tchars.t_startc ; VSTART */
224#define XTTYMODE_start  7
225    TTYMODE("stop"),            /* tchars.t_stopc ; VSTOP */
226#define XTTYMODE_stop   8
227    TTYMODE("brk"),             /* tchars.t_brkc */
228#define XTTYMODE_brk    9
229    TTYMODE("susp"),            /* ltchars.t_suspc ; VSUSP */
230#define XTTYMODE_susp   10
231    TTYMODE("dsusp"),           /* ltchars.t_dsuspc ; VDSUSP */
232#define XTTYMODE_dsusp  11
233    TTYMODE("rprnt"),           /* ltchars.t_rprntc ; VREPRINT */
234#define XTTYMODE_rprnt  12
235    TTYMODE("flush"),           /* ltchars.t_flushc ; VDISCARD */
236#define XTTYMODE_flush  13
237    TTYMODE("weras"),           /* ltchars.t_werasc ; VWERASE */
238#define XTTYMODE_weras  14
239    TTYMODE("lnext"),           /* ltchars.t_lnextc ; VLNEXT */
240#define XTTYMODE_lnext  15
241    { NULL,     0, 0, '\0' },   /* end of data */
242};
243/* *INDENT-ON* */
244
245#define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value
246
247static int parse_tty_modes(char *s, struct _xttymodes *modelist);
248
249static char passedPty[2];       /* name if pty if slave */
250
251static int Console;
252#include <X11/Xmu/SysUtil.h>    /* XmuGetHostname */
253#define MIT_CONSOLE_LEN 12
254#define MIT_CONSOLE "MIT_CONSOLE_"
255static char mit_console_name[255 + MIT_CONSOLE_LEN + 1] = MIT_CONSOLE;
256static Atom mit_console;
257
258static int tslot;
259static jmp_buf env;
260
261/* used by VT (charproc.c) */
262
263static XtResource application_resources[] =
264{
265    Sres("name", "Name", xterm_name, DFT_TERMTYPE),
266    Sres("iconGeometry", "IconGeometry", icon_geometry, NULL),
267    Sres(XtNtitle, XtCTitle, title, NULL),
268    Sres(XtNiconName, XtCIconName, icon_name, NULL),
269    Sres("termName", "TermName", term_name, NULL),
270    Sres("ttyModes", "TtyModes", tty_modes, NULL),
271    Bres("hold", "Hold", hold_screen, False),
272    Bres("utmpInhibit", "UtmpInhibit", utmpInhibit, False),
273    Bres("utmpDisplayId", "UtmpDisplayId", utmpDisplayId, True),
274    Bres("messages", "Messages", messages, True),
275    Ires("minBufSize", "MinBufSize", minBufSize, 4096),
276    Ires("maxBufSize", "MaxBufSize", maxBufSize, 32768),
277    Sres("menuLocale", "MenuLocale", menuLocale, ""),
278    Sres("keyboardType", "KeyboardType", keyboardType, "unknown"),
279#if OPT_SUNPC_KBD
280    Bres("sunKeyboard", "SunKeyboard", sunKeyboard, False),
281#endif
282#if OPT_HP_FUNC_KEYS
283    Bres("hpFunctionKeys", "HpFunctionKeys", hpFunctionKeys, False),
284#endif
285#if OPT_SCO_FUNC_KEYS
286    Bres("scoFunctionKeys", "ScoFunctionKeys", scoFunctionKeys, False),
287#endif
288#if OPT_SUN_FUNC_KEYS
289    Bres("sunFunctionKeys", "SunFunctionKeys", sunFunctionKeys, False),
290#endif
291#if OPT_TCAP_FKEYS
292    Bres("tcapFunctionKeys", "TcapFunctionKeys", termcapKeys, False),
293#endif
294#if OPT_INITIAL_ERASE
295    Bres("ptyInitialErase", "PtyInitialErase", ptyInitialErase, DEF_INITIAL_ERASE),
296    Bres("backarrowKeyIsErase", "BackarrowKeyIsErase", backarrow_is_erase, DEF_BACKARO_ERASE),
297#endif
298    Bres("useInsertMode", "UseInsertMode", useInsertMode, False),
299#if OPT_ZICONBEEP
300    Ires("zIconBeep", "ZIconBeep", zIconBeep, 0),
301#endif
302#if OPT_PTY_HANDSHAKE
303    Bres("waitForMap", "WaitForMap", wait_for_map, False),
304    Bres("ptyHandshake", "PtyHandshake", ptyHandshake, DEF_PTY_HANDSHAKE),
305#endif
306#if OPT_SAME_NAME
307    Bres("sameName", "SameName", sameName, True),
308#endif
309#if OPT_SESSION_MGT
310    Bres("sessionMgt", "SessionMgt", sessionMgt, True),
311#endif
312#if OPT_TOOLBAR
313    Bres(XtNtoolBar, XtCToolBar, toolBar, True),
314#endif
315};
316
317static char *fallback_resources[] =
318{
319    "*SimpleMenu*menuLabel.vertSpace: 100",
320    "*SimpleMenu*HorizontalMargins: 16",
321    "*SimpleMenu*Sme.height: 16",
322    "*SimpleMenu*Cursor: left_ptr",
323    "*mainMenu.Label:  Main Options (no app-defaults)",
324    "*vtMenu.Label:  VT Options (no app-defaults)",
325    "*fontMenu.Label:  VT Fonts (no app-defaults)",
326#if OPT_TEK4014
327    "*tekMenu.Label:  Tek Options (no app-defaults)",
328#endif
329    NULL
330};
331
332/* Command line options table.  Only resources are entered here...there is a
333   pass over the remaining options after XrmParseCommand is let loose. */
334/* *INDENT-OFF* */
335static XrmOptionDescRec optionDescList[] = {
336{"-geometry",   "*vt100.geometry",XrmoptionSepArg,      (caddr_t) NULL},
337{"-132",        "*c132",        XrmoptionNoArg,         (caddr_t) "on"},
338{"+132",        "*c132",        XrmoptionNoArg,         (caddr_t) "off"},
339{"-ah",         "*alwaysHighlight", XrmoptionNoArg,     (caddr_t) "on"},
340{"+ah",         "*alwaysHighlight", XrmoptionNoArg,     (caddr_t) "off"},
341{"-aw",         "*autoWrap",    XrmoptionNoArg,         (caddr_t) "on"},
342{"+aw",         "*autoWrap",    XrmoptionNoArg,         (caddr_t) "off"},
343#ifndef NO_ACTIVE_ICON
344{"-ai",         "*activeIcon",  XrmoptionNoArg,         (caddr_t) "off"},
345{"+ai",         "*activeIcon",  XrmoptionNoArg,         (caddr_t) "on"},
346#endif /* NO_ACTIVE_ICON */
347{"-b",          "*internalBorder",XrmoptionSepArg,      (caddr_t) NULL},
348{"-bc",         "*cursorBlink", XrmoptionNoArg,         (caddr_t) "on"},
349{"+bc",         "*cursorBlink", XrmoptionNoArg,         (caddr_t) "off"},
350{"-bcf",        "*cursorOffTime",XrmoptionSepArg,       (caddr_t) NULL},
351{"-bcn",        "*cursorOnTime",XrmoptionSepArg,        (caddr_t) NULL},
352{"-bdc",        "*colorBDMode", XrmoptionNoArg,         (caddr_t) "off"},
353{"+bdc",        "*colorBDMode", XrmoptionNoArg,         (caddr_t) "on"},
354{"-cb",         "*cutToBeginningOfLine", XrmoptionNoArg, (caddr_t) "off"},
355{"+cb",         "*cutToBeginningOfLine", XrmoptionNoArg, (caddr_t) "on"},
356{"-cc",         "*charClass",   XrmoptionSepArg,        (caddr_t) NULL},
357{"-cm",         "*colorMode",   XrmoptionNoArg,         (caddr_t) "off"},
358{"+cm",         "*colorMode",   XrmoptionNoArg,         (caddr_t) "on"},
359{"-cn",         "*cutNewline",  XrmoptionNoArg,         (caddr_t) "off"},
360{"+cn",         "*cutNewline",  XrmoptionNoArg,         (caddr_t) "on"},
361{"-cr",         "*cursorColor", XrmoptionSepArg,        (caddr_t) NULL},
362{"-cu",         "*curses",      XrmoptionNoArg,         (caddr_t) "on"},
363{"+cu",         "*curses",      XrmoptionNoArg,         (caddr_t) "off"},
364{"-dc",         "*dynamicColors",XrmoptionNoArg,        (caddr_t) "off"},
365{"+dc",         "*dynamicColors",XrmoptionNoArg,        (caddr_t) "on"},
366{"-fb",         "*boldFont",    XrmoptionSepArg,        (caddr_t) NULL},
367{"-fbb",        "*freeBoldBox", XrmoptionNoArg,         (caddr_t)"off"},
368{"+fbb",        "*freeBoldBox", XrmoptionNoArg,         (caddr_t)"on"},
369{"-fbx",        "*forceBoxChars", XrmoptionNoArg,       (caddr_t)"off"},
370{"+fbx",        "*forceBoxChars", XrmoptionNoArg,       (caddr_t)"on"},
371#ifndef NO_ACTIVE_ICON
372{"-fi",         "*iconFont",    XrmoptionSepArg,        (caddr_t) NULL},
373#endif /* NO_ACTIVE_ICON */
374#if OPT_RENDERFONT
375{"-fa",         "*faceName",    XrmoptionSepArg,        (caddr_t) NULL},
376{"-fd",         "*faceNameDoublesize", XrmoptionSepArg, (caddr_t) NULL},
377{"-fs",         "*faceSize",    XrmoptionSepArg,        (caddr_t) NULL},
378#endif
379#if OPT_WIDE_CHARS
380{"-fw",         "*wideFont",    XrmoptionSepArg,        (caddr_t) NULL},
381{"-fwb",        "*wideBoldFont", XrmoptionSepArg,       (caddr_t) NULL},
382#endif
383#if OPT_INPUT_METHOD
384{"-fx",         "*ximFont",     XrmoptionSepArg,        (caddr_t) NULL},
385#endif
386#if OPT_HIGHLIGHT_COLOR
387{"-hc",         "*highlightColor", XrmoptionSepArg,     (caddr_t) NULL},
388{"-hm",         "*highlightColorMode", XrmoptionNoArg,  (caddr_t) "on"},
389{"+hm",         "*highlightColorMode", XrmoptionNoArg,  (caddr_t) "off"},
390{"-selfg",      "*highlightTextColor", XrmoptionSepArg, (caddr_t) NULL},
391{"-selbg",      "*highlightColor", XrmoptionSepArg,     (caddr_t) NULL},
392#endif
393#if OPT_HP_FUNC_KEYS
394{"-hf",         "*hpFunctionKeys",XrmoptionNoArg,       (caddr_t) "on"},
395{"+hf",         "*hpFunctionKeys",XrmoptionNoArg,       (caddr_t) "off"},
396#endif
397{"-hold",       "*hold",        XrmoptionNoArg,         (caddr_t) "on"},
398{"+hold",       "*hold",        XrmoptionNoArg,         (caddr_t) "off"},
399#if OPT_INITIAL_ERASE
400{"-ie",         "*ptyInitialErase", XrmoptionNoArg,     (caddr_t) "on"},
401{"+ie",         "*ptyInitialErase", XrmoptionNoArg,     (caddr_t) "off"},
402#endif
403{"-j",          "*jumpScroll",  XrmoptionNoArg,         (caddr_t) "on"},
404{"+j",          "*jumpScroll",  XrmoptionNoArg,         (caddr_t) "off"},
405#if OPT_C1_PRINT
406{"-k8",         "*allowC1Printable", XrmoptionNoArg,    (caddr_t) "on"},
407{"+k8",         "*allowC1Printable", XrmoptionNoArg,    (caddr_t) "off"},
408#endif
409{"-kt",         "*keyboardType", XrmoptionSepArg,       (caddr_t) NULL},
410{"+kt",         "*keyboardType", XrmoptionSepArg,       (caddr_t) NULL},
411/* parse logging options anyway for compatibility */
412{"-l",          "*logging",     XrmoptionNoArg,         (caddr_t) "on"},
413{"+l",          "*logging",     XrmoptionNoArg,         (caddr_t) "off"},
414{"-lf",         "*logFile",     XrmoptionSepArg,        (caddr_t) NULL},
415{"-ls",         "*loginShell",  XrmoptionNoArg,         (caddr_t) "on"},
416{"+ls",         "*loginShell",  XrmoptionNoArg,         (caddr_t) "off"},
417{"-mb",         "*marginBell",  XrmoptionNoArg,         (caddr_t) "on"},
418{"+mb",         "*marginBell",  XrmoptionNoArg,         (caddr_t) "off"},
419{"-mc",         "*multiClickTime", XrmoptionSepArg,     (caddr_t) NULL},
420{"-mesg",       "*messages",    XrmoptionNoArg,         (caddr_t) "off"},
421{"+mesg",       "*messages",    XrmoptionNoArg,         (caddr_t) "on"},
422{"-ms",         "*pointerColor",XrmoptionSepArg,        (caddr_t) NULL},
423{"-nb",         "*nMarginBell", XrmoptionSepArg,        (caddr_t) NULL},
424{"-nul",        "*underLine",   XrmoptionNoArg,         (caddr_t) "off"},
425{"+nul",        "*underLine",   XrmoptionNoArg,         (caddr_t) "on"},
426{"-pc",         "*boldColors",  XrmoptionNoArg,         (caddr_t) "on"},
427{"+pc",         "*boldColors",  XrmoptionNoArg,         (caddr_t) "off"},
428{"-rw",         "*reverseWrap", XrmoptionNoArg,         (caddr_t) "on"},
429{"+rw",         "*reverseWrap", XrmoptionNoArg,         (caddr_t) "off"},
430{"-s",          "*multiScroll", XrmoptionNoArg,         (caddr_t) "on"},
431{"+s",          "*multiScroll", XrmoptionNoArg,         (caddr_t) "off"},
432{"-sb",         "*scrollBar",   XrmoptionNoArg,         (caddr_t) "on"},
433{"+sb",         "*scrollBar",   XrmoptionNoArg,         (caddr_t) "off"},
434#ifdef SCROLLBAR_RIGHT
435{"-leftbar",    "*rightScrollBar", XrmoptionNoArg,      (caddr_t) "off"},
436{"-rightbar",   "*rightScrollBar", XrmoptionNoArg,      (caddr_t) "on"},
437#endif
438{"-rvc",        "*colorRVMode", XrmoptionNoArg,         (caddr_t) "off"},
439{"+rvc",        "*colorRVMode", XrmoptionNoArg,         (caddr_t) "on"},
440{"-sf",         "*sunFunctionKeys", XrmoptionNoArg,     (caddr_t) "on"},
441{"+sf",         "*sunFunctionKeys", XrmoptionNoArg,     (caddr_t) "off"},
442{"-si",         "*scrollTtyOutput", XrmoptionNoArg,     (caddr_t) "off"},
443{"+si",         "*scrollTtyOutput", XrmoptionNoArg,     (caddr_t) "on"},
444{"-sk",         "*scrollKey",   XrmoptionNoArg,         (caddr_t) "on"},
445{"+sk",         "*scrollKey",   XrmoptionNoArg,         (caddr_t) "off"},
446{"-sl",         "*saveLines",   XrmoptionSepArg,        (caddr_t) NULL},
447#if OPT_SUNPC_KBD
448{"-sp",         "*sunKeyboard", XrmoptionNoArg,         (caddr_t) "on"},
449{"+sp",         "*sunKeyboard", XrmoptionNoArg,         (caddr_t) "off"},
450#endif
451#if OPT_TEK4014
452{"-t",          "*tekStartup",  XrmoptionNoArg,         (caddr_t) "on"},
453{"+t",          "*tekStartup",  XrmoptionNoArg,         (caddr_t) "off"},
454#endif
455{"-ti",         "*decTerminalID",XrmoptionSepArg,       (caddr_t) NULL},
456{"-tm",         "*ttyModes",    XrmoptionSepArg,        (caddr_t) NULL},
457{"-tn",         "*termName",    XrmoptionSepArg,        (caddr_t) NULL},
458#if OPT_WIDE_CHARS
459{"-u8",         "*utf8",        XrmoptionNoArg,         (caddr_t) "2"},
460{"+u8",         "*utf8",        XrmoptionNoArg,         (caddr_t) "0"},
461#endif
462#if OPT_LUIT_PROG
463{"-lc",         "*locale",      XrmoptionNoArg,         (caddr_t) "on"},
464{"+lc",         "*locale",      XrmoptionNoArg,         (caddr_t) "off"},
465{"-lcc",        "*localeFilter",XrmoptionSepArg,        (caddr_t) NULL},
466{"-en",         "*locale",      XrmoptionSepArg,        (caddr_t) NULL},
467#endif
468{"-ulc",        "*colorULMode", XrmoptionNoArg,         (caddr_t) "off"},
469{"+ulc",        "*colorULMode", XrmoptionNoArg,         (caddr_t) "on"},
470{"-ulit",       "*italicULMode", XrmoptionNoArg,        (caddr_t) "off"},
471{"+ulit",       "*italicULMode", XrmoptionNoArg,        (caddr_t) "on"},
472{"-ut",         "*utmpInhibit", XrmoptionNoArg,         (caddr_t) "on"},
473{"+ut",         "*utmpInhibit", XrmoptionNoArg,         (caddr_t) "off"},
474{"-im",         "*useInsertMode", XrmoptionNoArg,       (caddr_t) "on"},
475{"+im",         "*useInsertMode", XrmoptionNoArg,       (caddr_t) "off"},
476{"-vb",         "*visualBell",  XrmoptionNoArg,         (caddr_t) "on"},
477{"+vb",         "*visualBell",  XrmoptionNoArg,         (caddr_t) "off"},
478{"-pob",        "*popOnBell",   XrmoptionNoArg,         (caddr_t) "on"},
479{"+pob",        "*popOnBell",   XrmoptionNoArg,         (caddr_t) "off"},
480#if OPT_WIDE_CHARS
481{"-wc",         "*wideChars",   XrmoptionNoArg,         (caddr_t) "on"},
482{"+wc",         "*wideChars",   XrmoptionNoArg,         (caddr_t) "off"},
483{"-mk_width",   "*mkWidth",     XrmoptionNoArg,         (caddr_t) "on"},
484{"+mk_width",   "*mkWidth",     XrmoptionNoArg,         (caddr_t) "off"},
485{"-cjk_width""*cjkWidth",    XrmoptionNoArg,         (caddr_t) "on"},
486{"+cjk_width""*cjkWidth",    XrmoptionNoArg,         (caddr_t) "off"},
487#endif
488{"-wf",         "*waitForMap",  XrmoptionNoArg,         (caddr_t) "on"},
489{"+wf",         "*waitForMap",  XrmoptionNoArg,         (caddr_t) "off"},
490#if OPT_ZICONBEEP
491{"-ziconbeep""*zIconBeep",   XrmoptionSepArg,        (caddr_t) NULL},
492#endif
493#if OPT_SAME_NAME
494{"-samename",   "*sameName",    XrmoptionNoArg,         (caddr_t) "on"},
495{"+samename",   "*sameName",    XrmoptionNoArg,         (caddr_t) "off"},
496#endif
497#if OPT_SESSION_MGT
498{"-sm",         "*sessionMgt",  XrmoptionNoArg,         (caddr_t) "on"},
499{"+sm",         "*sessionMgt",  XrmoptionNoArg,         (caddr_t) "off"},
500#endif
501#if OPT_TOOLBAR
502{"-tb",         "*"XtNtoolBar,  XrmoptionNoArg,         (caddr_t) "on"},
503{"+tb",         "*"XtNtoolBar,  XrmoptionNoArg,         (caddr_t) "off"},
504#endif
505/* options that we process ourselves */
506{"-help",       NULL,           XrmoptionSkipNArgs,     (caddr_t) NULL},
507{"-version",    NULL,           XrmoptionSkipNArgs,     (caddr_t) NULL},
508{"-class",      NULL,           XrmoptionSkipArg,       (caddr_t) NULL},
509{"-e",          NULL,           XrmoptionSkipLine,      (caddr_t) NULL},
510{"-into",       NULL,           XrmoptionSkipArg,       (caddr_t) NULL},
511/* bogus old compatibility stuff for which there are
512   standard XtOpenApplication options now */
513{"%",           "*tekGeometry", XrmoptionStickyArg,     (caddr_t) NULL},
514{"#",           ".iconGeometry",XrmoptionStickyArg,     (caddr_t) NULL},
515{"-T",          ".title",       XrmoptionSepArg,        (caddr_t) NULL},
516{"-n",          "*iconName",    XrmoptionSepArg,        (caddr_t) NULL},
517{"-r",          "*reverseVideo",XrmoptionNoArg,         (caddr_t) "on"},
518{"+r",          "*reverseVideo",XrmoptionNoArg,         (caddr_t) "off"},
519{"-rv",         "*reverseVideo",XrmoptionNoArg,         (caddr_t) "on"},
520{"+rv",         "*reverseVideo",XrmoptionNoArg,         (caddr_t) "off"},
521{"-w",          ".borderWidth", XrmoptionSepArg,        (caddr_t) NULL},
522};
523
524static OptionHelp xtermOptions[] = {
525{ "-version",              "print the version number" },
526{ "-help",                 "print out this message" },
527{ "-display displayname""X server to contact" },
528{ "-geometry geom",        "size (in characters) and position" },
529{ "-/+rv",                 "turn on/off reverse video" },
530{ "-bg color",             "background color" },
531{ "-fg color",             "foreground color" },
532{ "-bd color",             "border color" },
533{ "-bw number",            "border width in pixels" },
534{ "-fn fontname",          "normal text font" },
535{ "-fb fontname",          "bold text font" },
536{ "-/+fbb",                "turn on/off normal/bold font comparison inhibit"},
537{ "-/+fbx",                "turn off/on linedrawing characters"},
538#if OPT_RENDERFONT
539{ "-fa pattern",           "FreeType font-selection pattern" },
540{ "-fd pattern",           "FreeType Doublesize font-selection pattern" },
541{ "-fs size",              "FreeType font-size" },
542#endif
543#if OPT_WIDE_CHARS
544{ "-fw fontname",          "doublewidth text font" },
545{ "-fwb fontname",         "doublewidth bold text font" },
546#endif
547#if OPT_INPUT_METHOD
548{ "-fx fontname",          "XIM fontset" },
549#endif
550{ "-iconic",               "start iconic" },
551{ "-name string",          "client instance, icon, and title strings" },
552{ "-class string",         "class string (XTerm)" },
553{ "-title string",         "title string" },
554{ "-xrm resourcestring",   "additional resource specifications" },
555{ "-/+132",                "turn on/off 80/132 column switching" },
556{ "-/+ah",                 "turn on/off always highlight" },
557#ifndef NO_ACTIVE_ICON
558{ "-/+ai",                 "turn off/on active icon" },
559{ "-fi fontname",          "icon font for active icon" },
560#endif /* NO_ACTIVE_ICON */
561{ "-b number",             "internal border in pixels" },
562{ "-/+bc",                 "turn on/off text cursor blinking" },
563{ "-bcf milliseconds",     "time text cursor is off when blinking"},
564{ "-bcn milliseconds",     "time text cursor is on when blinking"},
565{ "-/+bdc",                "turn off/on display of bold as color"},
566{ "-/+cb",                 "turn on/off cut-to-beginning-of-line inhibit" },
567{ "-cc classrange",        "specify additional character classes" },
568{ "-/+cm",                 "turn off/on ANSI color mode" },
569{ "-/+cn",                 "turn on/off cut newline inhibit" },
570{ "-cr color",             "text cursor color" },
571{ "-/+cu",                 "turn on/off curses emulation" },
572{ "-/+dc",                 "turn off/on dynamic color selection" },
573#if OPT_HIGHLIGHT_COLOR
574{ "-/+hm",                 "turn on/off selection-color override" },
575{ "-selbg color",          "selection background color" },
576{ "-selfg color",          "selection foreground color" },
577#endif
578#if OPT_HP_FUNC_KEYS
579{ "-/+hf",                 "turn on/off HP Function Key escape codes" },
580#endif
581{ "-/+hold",               "turn on/off logic that retains window after exit" },
582#if OPT_INITIAL_ERASE
583{ "-/+ie",                 "turn on/off initialization of 'erase' from pty" },
584#endif
585{ "-/+im",                 "use insert mode for TERMCAP" },
586{ "-/+j",                  "turn on/off jump scroll" },
587#if OPT_C1_PRINT
588{ "-/+k8",                 "turn on/off C1-printable classification"},
589#endif
590{ "-kt keyboardtype",      "set keyboard type:" KEYBOARD_TYPES },
591#ifdef ALLOWLOGGING
592{ "-/+l",                  "turn on/off logging" },
593{ "-lf filename",          "logging filename" },
594#else
595{ "-/+l",                  "turn on/off logging (not supported)" },
596{ "-lf filename",          "logging filename (not supported)" },
597#endif
598{ "-/+ls",                 "turn on/off login shell" },
599{ "-/+mb",                 "turn on/off margin bell" },
600{ "-mc milliseconds",      "multiclick time in milliseconds" },
601{ "-/+mesg",               "forbid/allow messages" },
602{ "-ms color",             "pointer color" },
603{ "-nb number",            "margin bell in characters from right end" },
604{ "-/+nul",                "turn off/on display of underlining" },
605{ "-/+aw",                 "turn on/off auto wraparound" },
606{ "-/+pc",                 "turn on/off PC-style bold colors" },
607{ "-/+rw",                 "turn on/off reverse wraparound" },
608{ "-/+s",                  "turn on/off multiscroll" },
609{ "-/+sb",                 "turn on/off scrollbar" },
610#ifdef SCROLLBAR_RIGHT
611{ "-rightbar",             "force scrollbar right (default left)" },
612{ "-leftbar",              "force scrollbar left" },
613#endif
614{ "-/+rvc",                "turn off/on display of reverse as color" },
615{ "-/+sf",                 "turn on/off Sun Function Key escape codes" },
616{ "-/+si",                 "turn on/off scroll-on-tty-output inhibit" },
617{ "-/+sk",                 "turn on/off scroll-on-keypress" },
618{ "-sl number",            "number of scrolled lines to save" },
619#if OPT_SUNPC_KBD
620{ "-/+sp",                 "turn on/off Sun/PC Function/Keypad mapping" },
621#endif
622#if OPT_TEK4014
623{ "-/+t",                  "turn on/off Tek emulation window" },
624#endif
625#if OPT_TOOLBAR
626{ "-/+tb",                 "turn on/off toolbar" },
627#endif
628{ "-ti termid",            "terminal identifier" },
629{ "-tm string",            "terminal mode keywords and characters" },
630{ "-tn name",              "TERM environment variable name" },
631#if OPT_WIDE_CHARS
632{ "-/+u8",                 "turn on/off UTF-8 mode (implies wide-characters)" },
633#endif
634#if OPT_LUIT_PROG
635{ "-/+lc",                 "turn on/off locale mode using luit" },
636{ "-lcc path",             "filename of locale converter (" DEFLOCALEFILTER ")" },
637#endif
638{ "-/+ulc",                "turn off/on display of underline as color" },
639{ "-/+ut",                 "turn on/off utmp inhibit (not supported)" },
640{ "-/+ulit",               "turn off/on display of underline as italics" },
641{ "-/+vb",                 "turn on/off visual bell" },
642{ "-/+pob",                "turn on/off pop on bell" },
643#if OPT_WIDE_CHARS
644{ "-/+wc",                 "turn on/off wide-character mode" },
645{ "-/+mk_width",           "turn on/off simple width convention" },
646{ "-/+cjk_width",          "turn on/off legacy CJK width convention" },
647#endif
648{ "-/+wf",                 "turn on/off wait for map before command exec" },
649{ "-e command args ...",   "command to execute" },
650#if OPT_TEK4014
651{ "%geom",                 "Tek window geometry" },
652#endif
653{ "#geom",                 "icon window geometry" },
654{ "-T string",             "title name for window" },
655{ "-n string",             "icon name for window" },
656{ "-C",                    "intercept console messages" },
657{ "-Sccn",                 "slave mode on \"ttycc\", file descriptor \"n\"" },
658{ "-into windowId",        "use the window id given to -into as the parent window rather than the default root window" },
659#if OPT_ZICONBEEP
660{ "-ziconbeep percent",    "beep and flag icon of window having hidden output" },
661#endif
662#if OPT_SAME_NAME
663{ "-/+samename",           "turn on/off the no-flicker option for title and icon name" },
664#endif
665#if OPT_SESSION_MGT
666{ "-/+sm",                 "turn on/off the session-management support" },
667#endif
668{ NULL, NULL }};
669/* *INDENT-ON* */
670
671/*debug FILE *confd;*/
672/*static void opencons()
673{
674        if ((confd=fopen("/dev/console$","w")) < 0) {
675                fputs("!!! Cannot open console device.\n",
676                        stderr);
677                exit(1);
678        }
679}
680
681static void closecons(void)
682{
683        fclose(confd);
684}
685*/
686static char *message[] =
687{
688    "Fonts should be fixed width and, if both normal and bold are specified, should",
689    "have the same size.  If only a normal font is specified, it will be used for",
690    "both normal and bold text (by doing overstriking).  The -e option, if given,",
691    "must appear at the end of the command line, otherwise the user's default shell",
692    "will be started.  Options that start with a plus sign (+) restore the default.",
693    NULL};
694
695/*
696 * Decode a key-definition.  This combines the termcap and ttyModes, for
697 * comparison.  Note that octal escapes in ttyModes are done by the normal
698 * resource translation.  Also, ttyModes allows '^-' as a synonym for disabled.
699 */
700static int
701decode_keyvalue(char **ptr, int termcap)
702{
703    char *string = *ptr;
704    int value = -1;
705
706    TRACE(("...decode '%s'\n", string));
707    if (*string == '^') {
708        switch (*++string) {
709        case '?':
710            value = A2E(ANSI_DEL);
711            break;
712        case '-':
713            if (!termcap) {
714                errno = 0;
715#if defined(_POSIX_VDISABLE) && defined(HAVE_UNISTD_H)
716                value = _POSIX_VDISABLE;
717#endif
718#if defined(_PC_VDISABLE)
719                if (value == -1) {
720                    value = fpathconf(0, _PC_VDISABLE);
721                    if (value == -1) {
722                        if (errno != 0)
723                            break;      /* skip this (error) */
724                        value = 0377;
725                    }
726                }
727#elif defined(VDISABLE)
728                if (value == -1)
729                    value = VDISABLE;
730#endif
731                break;
732            }
733            /* FALLTHRU */
734        default:
735            value = CONTROL(*string);
736            break;
737        }
738        ++string;
739    } else if (termcap && (*string == '\\')) {
740        char *d;
741        int temp = strtol(string + 1, &d, 8);
742        if (temp > 0 && d != string) {
743            value = temp;
744            string = d;
745        }
746    } else {
747        value = CharOf(*string);
748        ++string;
749    }
750    *ptr = string;
751    return value;
752}
753
754static int
755abbrev(char *tst, char *cmp, size_t need)
756{
757    size_t len = strlen(tst);
758    return ((len >= need) && (!strncmp(tst, cmp, len)));
759}
760
761static void
762Syntax(char *badOption)
763{
764    OptionHelp *opt;
765    OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList));
766    int col;
767
768    fprintf(stderr, "%s:  bad command line option \"%s\"\r\n\n",
769            ProgramName, badOption);
770
771    fprintf(stderr, "usage:  %s", ProgramName);
772    col = 8 + strlen(ProgramName);
773    for (opt = list; opt->opt; opt++) {
774        int len = 3 + strlen(opt->opt);         /* space [ string ] */
775        if (col + len > 79) {
776            fprintf(stderr, "\r\n   ");         /* 3 spaces */
777            col = 3;
778        }
779        fprintf(stderr, " [%s]", opt->opt);
780        col += len;
781    }
782
783    fprintf(stderr, "\r\n\nType %s -help for a full description.\r\n\n",
784            ProgramName);
785    exit(1);
786}
787
788static void
789Version(void)
790{
791    printf("%s\n", xtermVersion());
792    fflush(stdout);
793}
794
795static void
796Help(void)
797{
798    OptionHelp *opt;
799    OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList));
800    char **cpp;
801
802    printf("%s usage:\n    %s [-options ...] [-e command args]\n\n",
803           xtermVersion(), ProgramName);
804    printf("where options include:\n");
805    for (opt = list; opt->opt; opt++) {
806        printf("    %-28s %s\n", opt->opt, opt->desc);
807    }
808
809    putchar('\n');
810    for (cpp = message; *cpp; cpp++)
811        puts(*cpp);
812    putchar('\n');
813    fflush(stdout);
814}
815
816/* ARGSUSED */
817static Boolean
818ConvertConsoleSelection(Widget w GCC_UNUSED,
819                        Atom * selection GCC_UNUSED,
820                        Atom * target GCC_UNUSED,
821                        Atom * type GCC_UNUSED,
822                        XtPointer *value GCC_UNUSED,
823                        unsigned long *length GCC_UNUSED,
824                        int *format GCC_UNUSED)
825{
826    /* we don't save console output, so can't offer it */
827    return False;
828}
829
830#if OPT_SESSION_MGT
831static void
832die_callback(Widget w GCC_UNUSED,
833             XtPointer client_data GCC_UNUSED,
834             XtPointer call_data GCC_UNUSED)
835{
836    Cleanup(0);
837}
838
839static void
840save_callback(Widget w GCC_UNUSED,
841              XtPointer client_data GCC_UNUSED,
842              XtPointer call_data)
843{
844    XtCheckpointToken token = (XtCheckpointToken) call_data;
845    /* we have nothing to save */
846    token->save_success = True;
847}
848#endif /* OPT_SESSION_MGT */
849
850/*
851 * DeleteWindow(): Action proc to implement ICCCM delete_window.
852 */
853/* ARGSUSED */
854static void
855DeleteWindow(Widget w,
856             XEvent * event GCC_UNUSED,
857             String * params GCC_UNUSED,
858             Cardinal *num_params GCC_UNUSED)
859{
860#if OPT_TEK4014
861    if (w == toplevel) {
862        if (TEK4014_SHOWN(term))
863            hide_vt_window();
864        else
865            do_hangup(w, (XtPointer) 0, (XtPointer) 0);
866    } else if (term->screen.Vshow)
867        hide_tek_window();
868    else
869#endif
870        do_hangup(w, (XtPointer) 0, (XtPointer) 0);
871}
872
873/* ARGSUSED */
874static void
875KeyboardMapping(Widget w GCC_UNUSED,
876                XEvent * event,
877                String * params GCC_UNUSED,
878                Cardinal *num_params GCC_UNUSED)
879{
880    switch (event->type) {
881    case MappingNotify:
882        XRefreshKeyboardMapping(&event->xmapping);
883        break;
884    }
885}
886
887static XtActionsRec actionProcs[] =
888{
889    {"DeleteWindow", DeleteWindow},
890    {"KeyboardMapping", KeyboardMapping},
891};
892
893char **gblenvp;
894
895int
896main(int argc, char **argv ENVP_ARG)
897{
898    Widget form_top, menu_top;
899    Dimension menu_high;
900    TScreen *screen;
901    int mode;
902    char *my_class = DEFCLASS;
903    Window winToEmbedInto = None;
904#if OPT_COLOR_RES
905    Bool reversed = False;
906#endif
907
908    ProgramName = argv[0];
909
910    save_ruid = getuid();
911    save_rgid = getgid();
912
913    /* Do these first, since we may not be able to open the display */
914    TRACE_OPTS(xtermOptions, optionDescList, XtNumber(optionDescList));
915    TRACE_ARGV("Before XtOpenApplication", argv);
916    if (argc > 1) {
917        int n;
918        unsigned unique = 2;
919        Bool quit = True;
920
921        for (n = 1; n < argc; n++) {
922            TRACE(("parsing %s\n", argv[n]));
923            if (abbrev(argv[n], "-version", unique)) {
924                Version();
925            } else if (abbrev(argv[n], "-help", unique)) {
926                Help();
927            } else if (abbrev(argv[n], "-class", 3)) {
928                if ((my_class = argv[++n]) == 0) {
929                    Help();
930                } else {
931                    quit = False;
932                }
933                unique = 3;
934            } else {
935#if OPT_COLOR_RES
936                if (abbrev(argv[n], "-reverse", 2)
937                    || !strcmp("-rv", argv[n])) {
938                    reversed = True;
939                } else if (!strcmp("+rv", argv[n])) {
940                    reversed = False;
941                }
942#endif
943                quit = False;
944                unique = 3;
945            }
946        }
947        if (quit)
948            exit(0);
949    }
950
951    /* XXX: for some obscure reason EMX seems to lose the value of
952     * the environ variable, don't understand why, so save it recently
953     */
954    gblenvp = envp;
955
956#ifdef I18N
957    setlocale(LC_ALL, NULL);
958#endif
959
960/*debug opencons();*/
961
962    ttydev = TypeMallocN(char, PTMS_BUFSZ);
963    ptydev = TypeMallocN(char, PTMS_BUFSZ);
964    if (!ttydev || !ptydev) {
965        fprintf(stderr,
966                "%s:  unable to allocate memory for ttydev or ptydev\n",
967                ProgramName);
968        exit(1);
969    }
970    strcpy(ttydev, TTYDEV);
971    strcpy(ptydev, PTYDEV);
972
973    /* Initialization is done here rather than above in order
974     * to prevent any assumptions about the order of the contents
975     * of the various terminal structures (which may change from
976     * implementation to implementation).
977     */
978    d_tio.c_iflag = ICRNL | IXON;
979    d_tio.c_oflag = OPOST | ONLCR | TAB3;
980    d_tio.c_cflag = B38400 | CS8 | CREAD | PARENB | HUPCL;
981    d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
982    d_tio.c_line = 0;
983    d_tio.c_cc[VINTR] = CONTROL('C');   /* '^C' */
984    d_tio.c_cc[VERASE] = ANSI_DEL;      /* DEL  */
985    d_tio.c_cc[VKILL] = CONTROL('U');   /* '^U' */
986    d_tio.c_cc[VQUIT] = CQUIT;  /* '^\' */
987    d_tio.c_cc[VEOF] = CEOF;    /* '^D' */
988    d_tio.c_cc[VEOL] = CEOL;    /* '^@' */
989
990    XtSetErrorHandler(xt_error);
991#if OPT_SESSION_MGT
992    toplevel = XtOpenApplication(&app_con, my_class,
993                                 optionDescList,
994                                 XtNumber(optionDescList),
995                                 &argc, argv, fallback_resources,
996                                 sessionShellWidgetClass,
997                                 NULL, 0);
998#else
999    toplevel = XtAppInitialize(&app_con, my_class,
1000                               optionDescList,
1001                               XtNumber(optionDescList),
1002                               &argc, argv, fallback_resources,
1003                               NULL, 0);
1004#endif /* OPT_SESSION_MGT */
1005    XtSetErrorHandler((XtErrorHandler) 0);
1006
1007    XtGetApplicationResources(toplevel, (XtPointer) &resource,
1008                              application_resources,
1009                              XtNumber(application_resources), NULL, 0);
1010    TRACE_XRES();
1011
1012    /*
1013     * ICCCM delete_window.
1014     */
1015    XtAppAddActions(app_con, actionProcs, XtNumber(actionProcs));
1016
1017    /*
1018     * fill in terminal modes
1019     */
1020    if (resource.tty_modes) {
1021        int n = parse_tty_modes(resource.tty_modes, ttymodelist);
1022        if (n < 0) {
1023            fprintf(stderr, "%s:  bad tty modes \"%s\"\n",
1024                    ProgramName, resource.tty_modes);
1025        } else if (n > 0) {
1026            override_tty_modes = 1;
1027        }
1028    }
1029#if OPT_ZICONBEEP
1030    if (resource.zIconBeep > 100 || resource.zIconBeep < -100) {
1031        resource.zIconBeep = 0; /* was 100, but I prefer to defaulting off. */
1032        fprintf(stderr,
1033                "a number between -100 and 100 is required for zIconBeep.  0 used by default\n");
1034    }
1035#endif /* OPT_ZICONBEEP */
1036    hold_screen = resource.hold_screen ? 1 : 0;
1037    xterm_name = resource.xterm_name;
1038    if (strcmp(xterm_name, "-") == 0)
1039        xterm_name = DFT_TERMTYPE;
1040    if (resource.icon_geometry != NULL) {
1041        int scr, junk;
1042        int ix, iy;
1043        Arg args[2];
1044
1045        for (scr = 0;           /* yyuucchh */
1046             XtScreen(toplevel) != ScreenOfDisplay(XtDisplay(toplevel), scr);
1047             scr++) ;
1048
1049        args[0].name = XtNiconX;
1050        args[1].name = XtNiconY;
1051        XGeometry(XtDisplay(toplevel), scr, resource.icon_geometry, "",
1052                  0, 0, 0, 0, 0, &ix, &iy, &junk, &junk);
1053        args[0].value = (XtArgVal) ix;
1054        args[1].value = (XtArgVal) iy;
1055        XtSetValues(toplevel, args, 2);
1056    }
1057
1058    XtSetValues(toplevel, ourTopLevelShellArgs,
1059                number_ourTopLevelShellArgs);
1060
1061#if OPT_WIDE_CHARS
1062    /* seems as good a place as any */
1063    init_classtab();
1064#endif
1065
1066    /* Parse the rest of the command line */
1067    TRACE_ARGV("After XtOpenApplication", argv);
1068    for (argc--, argv++; argc > 0; argc--, argv++) {
1069        if (**argv != '-')
1070            Syntax(*argv);
1071
1072        TRACE(("parsing %s\n", argv[0]));
1073        switch (argv[0][1]) {
1074        case 'h':               /* -help */
1075            Help();
1076            continue;
1077        case 'v':               /* -version */
1078            Version();
1079            continue;
1080        case 'C':
1081            {
1082                struct stat sbuf;
1083
1084                /* Must be owner and have read/write permission.
1085                   xdm cooperates to give the console the right user. */
1086                if (!stat("/dev/console", &sbuf) &&
1087                    (sbuf.st_uid == save_ruid) &&
1088                    !access("/dev/console", R_OK | W_OK)) {
1089                    Console = True;
1090                } else
1091                    Console = False;
1092            }
1093            continue;
1094        case 'S':
1095            if (sscanf(*argv + 2, "%c%c%d", passedPty, passedPty + 1,
1096                       &am_slave) != 3)
1097                Syntax(*argv);
1098            continue;
1099#ifdef DEBUG
1100        case 'D':
1101            debug = True;
1102            continue;
1103#endif /* DEBUG */
1104        case 'c':               /* -class param */
1105            if (strcmp(argv[0] + 1, "class") == 0)
1106                argc--, argv++;
1107            else
1108                Syntax(*argv);
1109            continue;
1110        case 'e':
1111            if (argc <= 1)
1112                Syntax(*argv);
1113            command_to_exec = ++argv;
1114            break;
1115        case 'i':
1116            if (argc <= 1) {
1117                Syntax(*argv);
1118            } else {
1119                char *endPtr;
1120                --argc;
1121                ++argv;
1122                winToEmbedInto = (Window) strtol(argv[0], &endPtr, 10);
1123            }
1124            continue;
1125
1126        default:
1127            Syntax(*argv);
1128        }
1129        break;
1130    }
1131
1132    SetupMenus(toplevel, &form_top, &menu_top, &menu_high);
1133
1134    term = (XtermWidget) XtVaCreateManagedWidget("vt100", xtermWidgetClass,
1135                                                 form_top,
1136#if OPT_TOOLBAR
1137                                                 XtNmenuBar, menu_top,
1138                                                 XtNresizable, True,
1139                                                 XtNfromVert, menu_top,
1140                                                 XtNleft, XawChainLeft,
1141                                                 XtNright, XawChainRight,
1142                                                 XtNtop, XawChainTop,
1143                                                 XtNbottom, XawChainBottom,
1144                                                 XtNmenuHeight, menu_high,
1145#endif
1146                                                 (XtPointer) 0);
1147    decode_keyboard_type(term, &resource);
1148
1149    screen = TScreenOf(term);
1150    screen->inhibit = 0;
1151#ifdef ALLOWLOGGING
1152    if (term->misc.logInhibit)
1153        screen->inhibit |= I_LOG;
1154#endif
1155    if (term->misc.signalInhibit)
1156        screen->inhibit |= I_SIGNAL;
1157#if OPT_TEK4014
1158    if (term->misc.tekInhibit)
1159        screen->inhibit |= I_TEK;
1160#endif
1161
1162    /*
1163     * We might start by showing the tek4014 window.
1164     */
1165#if OPT_TEK4014
1166    if (screen->inhibit & I_TEK)
1167        TEK4014_ACTIVE(term) = False;
1168
1169    if (TEK4014_ACTIVE(term) && !TekInit())
1170        exit(ERROR_INIT);
1171#endif
1172
1173    /*
1174     * Start the toolbar at this point, after the first window has been setup.
1175     */
1176#if OPT_TOOLBAR
1177    ShowToolbar(resource.toolBar);
1178#endif
1179
1180#if OPT_SESSION_MGT
1181    if (resource.sessionMgt) {
1182        TRACE(("Enabling session-management callbacks\n"));
1183        XtAddCallback(toplevel, XtNdieCallback, die_callback, NULL);
1184        XtAddCallback(toplevel, XtNsaveCallback, save_callback, NULL);
1185    }
1186#endif
1187
1188    /*
1189     * Set title and icon name if not specified
1190     */
1191    if (command_to_exec) {
1192        Arg args[2];
1193
1194        if (!resource.title) {
1195            if (command_to_exec) {
1196                resource.title = x_basename(command_to_exec[0]);
1197            }                   /* else not reached */
1198        }
1199
1200        if (!resource.icon_name)
1201            resource.icon_name = resource.title;
1202        XtSetArg(args[0], XtNtitle, resource.title);
1203        XtSetArg(args[1], XtNiconName, resource.icon_name);
1204
1205        TRACE(("setting:\n\ttitle \"%s\"\n\ticon \"%s\"\n\tbased on command \"%s\"\n",
1206               resource.title,
1207               resource.icon_name,
1208               *command_to_exec));
1209
1210        XtSetValues(toplevel, args, 2);
1211    }
1212#if OPT_LUIT_PROG
1213    if (term->misc.callfilter) {
1214        int u = (term->misc.use_encoding ? 2 : 0);
1215        if (command_to_exec) {
1216            int n;
1217            char **c;
1218            for (n = 0, c = command_to_exec; *c; n++, c++) ;
1219            c = TypeMallocN(char *, n + 3 + u);
1220            if (c == NULL)
1221                SysError(ERROR_LUMALLOC);
1222            memcpy(c + 2 + u, command_to_exec, (n + 1) * sizeof(char *));
1223            c[0] = term->misc.localefilter;
1224            if (u) {
1225                c[1] = "-encoding";
1226                c[2] = term->misc.locale_str;
1227            }
1228            c[1 + u] = "--";
1229            command_to_exec_with_luit = c;
1230        } else {
1231            static char *luit[4];
1232            luit[0] = term->misc.localefilter;
1233            if (u) {
1234                luit[1] = "-encoding";
1235                luit[2] = term->misc.locale_str;
1236                luit[3] = NULL;
1237            } else
1238                luit[1] = NULL;
1239            command_to_exec_with_luit = luit;
1240        }
1241    }
1242#endif
1243
1244#ifdef DEBUG
1245    {
1246        /* Set up stderr properly.  Opening this log file cannot be
1247           done securely by a privileged xterm process (although we try),
1248           so the debug feature is disabled by default. */
1249        char dbglogfile[45];
1250        int i = -1;
1251        if (debug) {
1252            timestamp_filename(dbglogfile, "xterm.debug.log.");
1253            if (creat_as(save_ruid, save_rgid, False, dbglogfile, 0666) > 0) {
1254                i = open(dbglogfile, O_WRONLY | O_TRUNC);
1255            }
1256        }
1257        if (i >= 0) {
1258            dup2(i, 2);
1259
1260            /* mark this file as close on exec */
1261            (void) fcntl(i, F_SETFD, 1);
1262        }
1263    }
1264#endif /* DEBUG */
1265
1266    spawnXTerm(term);
1267
1268    /* Child process is out there, let's catch its termination */
1269    (void) signal(SIGCHLD, reapchild);
1270
1271    /* Realize procs have now been executed */
1272
1273    if (am_slave >= 0) {        /* Write window id so master end can read and use */
1274        char buf[80];
1275
1276        buf[0] = '\0';
1277        sprintf(buf, "%lx\n", XtWindow(SHELL_OF(CURRENT_EMU())));
1278        write(screen->respond, buf, strlen(buf));
1279    }
1280
1281    if (0 > (mode = fcntl(screen->respond, F_GETFL, 0)))
1282        SysError(ERROR_F_GETFL);
1283    mode |= O_NDELAY;
1284
1285    if (fcntl(screen->respond, F_SETFL, mode))
1286        SysError(ERROR_F_SETFL);
1287
1288    FD_ZERO(&pty_mask);
1289    FD_ZERO(&X_mask);
1290    FD_ZERO(&Select_mask);
1291    FD_SET(screen->respond, &pty_mask);
1292    FD_SET(ConnectionNumber(screen->display), &X_mask);
1293    FD_SET(screen->respond, &Select_mask);
1294    FD_SET(ConnectionNumber(screen->display), &Select_mask);
1295    max_plus1 = ((screen->respond < ConnectionNumber(screen->display))
1296                 ? (1 + ConnectionNumber(screen->display))
1297                 : (1 + screen->respond));
1298
1299#ifdef DEBUG
1300    if (debug)
1301        printf("debugging on\n");
1302#endif /* DEBUG */
1303    XSetErrorHandler(xerror);
1304    XSetIOErrorHandler(xioerror);
1305
1306    initPtyData(&VTbuffer);
1307#ifdef ALLOWLOGGING
1308    if (term->misc.log_on) {
1309        StartLog(screen);
1310    }
1311#endif
1312
1313    if (winToEmbedInto != None) {
1314        XtRealizeWidget(toplevel);
1315        /*
1316         * This should probably query the tree or check the attributes of
1317         * winToEmbedInto in order to verify that it exists, but I'm still not
1318         * certain what is the best way to do it -GPS
1319         */
1320        XReparentWindow(XtDisplay(toplevel),
1321                        XtWindow(toplevel),
1322                        winToEmbedInto, 0, 0);
1323    }
1324#if OPT_COLOR_RES
1325    TRACE(("checking resource values rv %s fg %s, bg %s\n",
1326           BtoS(term->misc.re_verse0),
1327           NonNull(term->screen.Tcolors[TEXT_FG].resource),
1328           NonNull(term->screen.Tcolors[TEXT_BG].resource)));
1329
1330    if ((reversed && term->misc.re_verse0)
1331        && ((term->screen.Tcolors[TEXT_FG].resource
1332             && !isDefaultForeground(term->screen.Tcolors[TEXT_FG].resource))
1333            || (term->screen.Tcolors[TEXT_BG].resource
1334                && !isDefaultBackground(term->screen.Tcolors[TEXT_BG].resource))
1335        ))
1336        ReverseVideo(term);
1337#endif /* OPT_COLOR_RES */
1338
1339    for (;;) {
1340#if OPT_TEK4014
1341        if (TEK4014_ACTIVE(term))
1342            TekRun();
1343        else
1344#endif
1345            VTRun();
1346    }
1347    return 0;
1348}
1349
1350/*
1351 * Called from get_pty to iterate over likely pseudo terminals
1352 * we might allocate.  Used on those systems that do not have
1353 * a functional interface for allocating a pty.
1354 * Returns 0 if found a pty, 1 if fails.
1355 */
1356static int
1357pty_search(int *pty)
1358{
1359    char namebuf[PTMS_BUFSZ];
1360
1361    /* ask the PTY manager */
1362    int fd = open("/dev/ptms$", 0);
1363    if (fd && ptioctl(fd, PTMS_GETPTY, namebuf) == 0) {
1364        strcpy(ttydev, namebuf);
1365        strcpy(ptydev, namebuf);
1366        *x_basename(ttydev) = 't';
1367        close(fd);
1368        if ((*pty = open(ptydev, O_RDWR)) >= 0) {
1369#ifdef PTYDEBUG
1370            ptioctl(*pty, XTY_TRACE, 0);
1371#endif
1372            return 0;
1373        } else {
1374            fprintf(stderr, "Unable to open %s, errno=%d\n", ptydev, errno);
1375        }
1376    }
1377    return 1;
1378}
1379
1380/*
1381 * This function opens up a pty master and stuffs its value into pty.
1382 *
1383 * If it finds one, it returns a value of 0.  If it does not find one,
1384 * it returns a value of !0.  This routine is designed to be re-entrant,
1385 * so that if a pty master is found and later, we find that the slave
1386 * has problems, we can re-enter this function and get another one.
1387 */
1388static int
1389get_pty(int *pty)
1390{
1391    return pty_search(pty);
1392}
1393
1394/*
1395 * The only difference in /etc/termcap between 4014 and 4015 is that
1396 * the latter has support for switching character sets.  We support the
1397 * 4015 protocol, but ignore the character switches.  Therefore, we
1398 * choose 4014 over 4015.
1399 *
1400 * Features of the 4014 over the 4012: larger (19") screen, 12-bit
1401 * graphics addressing (compatible with 4012 10-bit addressing),
1402 * special point plot mode, incremental plot mode (not implemented in
1403 * later Tektronix terminals), and 4 character sizes.
1404 * All of these are supported by xterm.
1405 */
1406
1407#if OPT_TEK4014
1408static char *tekterm[] =
1409{
1410    "tek4014",
1411    "tek4015",                  /* 4014 with APL character set support */
1412    "tek4012",                  /* 4010 with lower case */
1413    "tek4013",                  /* 4012 with APL character set support */
1414    "tek4010",                  /* small screen, upper-case only */
1415    "dumb",
1416    0
1417};
1418#endif
1419
1420/* The VT102 is a VT100 with the Advanced Video Option included standard.
1421 * It also adds Escape sequences for insert/delete character/line.
1422 * The VT220 adds 8-bit character sets, selective erase.
1423 * The VT320 adds a 25th status line, terminal state interrogation.
1424 * The VT420 has up to 48 lines on the screen.
1425 */
1426
1427static char *vtterm[] =
1428{
1429#ifdef USE_X11TERM
1430    "x11term",                  /* for people who want special term name */
1431#endif
1432    DFT_TERMTYPE,               /* for people who want special term name */
1433    "xterm",                    /* the prefered name, should be fastest */
1434    "vt102",
1435    "vt100",
1436    "ansi",
1437    "dumb",
1438    0
1439};
1440
1441/* ARGSUSED */
1442static SIGNAL_T
1443hungtty(int i GCC_UNUSED)
1444{
1445    longjmp(env, 1);
1446    SIGNAL_RETURN;
1447}
1448
1449#if OPT_PTY_HANDSHAKE
1450struct {
1451    int rows;
1452    int cols;
1453} handshake = {
1454
1455    -1, -1
1456};
1457
1458void
1459first_map_occurred(void)
1460{
1461    if (resource.wait_for_map) {
1462        TScreen *screen = TScreenOf(term);
1463        handshake.rows = screen->max_row;
1464        handshake.cols = screen->max_col;
1465        resource.wait_for_map = False;
1466    }
1467}
1468#endif /* OPT_PTY_HANDSHAKE else !OPT_PTY_HANDSHAKE */
1469
1470static void
1471set_owner(char *device, uid_t uid, gid_t gid, mode_t mode)
1472{
1473    int why;
1474
1475    if (chown(device, uid, gid) < 0) {
1476        why = errno;
1477        if (why != ENOENT
1478            && save_ruid == 0) {
1479            fprintf(stderr, "Cannot chown %s to %ld,%ld: %s\n",
1480                    device, (long) uid, (long) gid,
1481                    strerror(why));
1482        }
1483    }
1484}
1485
1486#define THE_PARENT 1
1487#define THE_CHILD  2
1488int whoami = -1;
1489
1490SIGNAL_T
1491killit(int sig)
1492{
1493    switch (whoami) {
1494    case -1:
1495        signal(sig, killit);
1496        kill(-getpid(), sig);
1497        break;
1498    case THE_PARENT:
1499        wait(NULL);
1500        signal(SIGTERM, SIG_DFL);
1501        kill(-getpid(), SIGTERM);
1502        Exit(0);
1503        break;
1504    case THE_CHILD:
1505        signal(SIGTERM, SIG_DFL);
1506        kill(-getppid(), SIGTERM);
1507        Exit(0);
1508        break;
1509    }
1510
1511    SIGNAL_RETURN;
1512}
1513
1514#define close_fd(fd) close(fd), fd = -1
1515
1516static int
1517spawnXTerm(XtermWidget xw)
1518/*
1519 *  Inits pty and tty and forks a login process.
1520 *  Does not close fd Xsocket.
1521 *  If slave, the pty named in passedPty is already open for use
1522 */
1523{
1524    TScreen *screen = TScreenOf(xw);
1525    int Xsocket = ConnectionNumber(screen->display);
1526
1527    int ttyfd = -1;
1528    TERMIO_STRUCT tio;
1529    int status;
1530    Bool ok_termcap;
1531    char *newtc;
1532
1533    char *TermName = NULL;
1534    char *ptr, *shname, buf[64];
1535    int i, no_dev_tty = False;
1536    char *dev_tty_name = (char *) 0;
1537    TTYSIZE_STRUCT ts;
1538    int pgrp = getpid();
1539    char numbuf[12], **envnew;
1540
1541    screen->uid = save_ruid;
1542    screen->gid = save_rgid;
1543
1544    if (am_slave >= 0) {
1545        screen->respond = am_slave;
1546        ptydev[strlen(ptydev) - 2] =
1547            ttydev[strlen(ttydev) - 2] = passedPty[0];
1548        ptydev[strlen(ptydev) - 1] =
1549            ttydev[strlen(ttydev) - 1] = passedPty[1];
1550
1551        (void) xtermResetIds(screen);
1552    } else {
1553        Bool tty_got_hung;
1554
1555        /*
1556         * Sometimes /dev/tty hangs on open (as in the case of a pty
1557         * that has gone away).  Simply make up some reasonable
1558         * defaults.
1559         */
1560
1561        signal(SIGALRM, hungtty);
1562        alarm(2);               /* alarm(1) might return too soon */
1563        if (!setjmp(env)) {
1564            ttyfd = open("/dev/tty", O_RDWR);
1565            alarm(0);
1566            tty_got_hung = False;
1567        } else {
1568            tty_got_hung = True;
1569            ttyfd = -1;
1570            errno = ENXIO;
1571        }
1572        signal(SIGALRM, SIG_DFL);
1573
1574        /*
1575         * Check results and ignore current control terminal if
1576         * necessary.  ENXIO is what is normally returned if there is
1577         * no controlling terminal, but some systems (e.g. SunOS 4.0)
1578         * seem to return EIO.  Solaris 2.3 is said to return EINVAL.
1579         */
1580        if (ttyfd < 0) {
1581            if (tty_got_hung || errno == ENXIO || errno == EIO ||
1582                errno == EINVAL || errno == ENOTTY) {
1583                no_dev_tty = True;
1584                tio = d_tio;
1585            } else {
1586                SysError(ERROR_OPDEVTTY);
1587            }
1588        } else {
1589
1590            /* Get a copy of the current terminal's state,
1591             * if we can.  Some systems (e.g., SVR4 and MacII)
1592             * may not have a controlling terminal at this point
1593             * if started directly from xdm or xinit,
1594             * in which case we just use the defaults as above.
1595             */
1596            if (ioctl(ttyfd, TCGETA, &tio) == -1)
1597                tio = d_tio;
1598
1599            close_fd(ttyfd);
1600        }
1601
1602        if (get_pty(&screen->respond)) {
1603            /*  no ptys! */
1604            exit(ERROR_PTYS);
1605        }
1606    }
1607
1608    /* avoid double MapWindow requests */
1609    XtSetMappedWhenManaged(SHELL_OF(CURRENT_EMU()), False);
1610
1611    wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW",
1612                                   False);
1613
1614    if (!TEK4014_ACTIVE(xw))
1615        VTInit();               /* realize now so know window size for tty driver */
1616
1617    if (Console) {
1618        /*
1619         * Inform any running xconsole program
1620         * that we are going to steal the console.
1621         */
1622        XmuGetHostname(mit_console_name + MIT_CONSOLE_LEN, 255);
1623        mit_console = XInternAtom(screen->display, mit_console_name, False);
1624        /* the user told us to be the console, so we can use CurrentTime */
1625        XtOwnSelection(SHELL_OF(CURRENT_EMU()),
1626                       mit_console, CurrentTime,
1627                       ConvertConsoleSelection, NULL, NULL);
1628    }
1629#if OPT_TEK4014
1630    if (TEK4014_ACTIVE(xw)) {
1631        envnew = tekterm;
1632        newtc = TekScreenOf(tekWidget)->tcapbuf;
1633    } else
1634#endif
1635    {
1636        envnew = vtterm;
1637        newtc = screen->tcapbuf;
1638    }
1639
1640    /*
1641     * This used to exit if no termcap entry was found for the specified
1642     * terminal name.  That's a little unfriendly, so instead we'll allow
1643     * the program to proceed (but not to set $TERMCAP) if the termcap
1644     * entry is not found.
1645     */
1646    ok_termcap = True;
1647    if (!get_termcap(TermName = resource.term_name, newtc)) {
1648        char *last = NULL;
1649        TermName = *envnew;
1650        ok_termcap = False;
1651        while (*envnew != NULL) {
1652            if ((last == NULL || strcmp(last, *envnew))
1653                && get_termcap(*envnew, newtc)) {
1654                TermName = *envnew;
1655                ok_termcap = True;
1656                break;
1657            }
1658            last = *envnew;
1659            envnew++;
1660        }
1661    }
1662    if (ok_termcap) {
1663        resize_termcap(xw, newtc);
1664    }
1665
1666    /* tell tty how big window is */
1667#if OPT_TEK4014
1668    if (TEK4014_ACTIVE(xw)) {
1669        TTYSIZE_ROWS(ts) = 38;
1670        TTYSIZE_COLS(ts) = 81;
1671        ts.ws_xpixel = TFullWidth(&(tekWidget->screen));
1672        ts.ws_ypixel = TFullHeight(&(tekWidget->screen));
1673    } else
1674#endif
1675    {
1676        TTYSIZE_ROWS(ts) = MaxRows(screen);
1677        TTYSIZE_COLS(ts) = MaxCols(screen);
1678        ts.ws_xpixel = FullWidth(screen);
1679        ts.ws_ypixel = FullHeight(screen);
1680    }
1681
1682    if (am_slave < 0) {
1683
1684        char sema[40];
1685        HEV sev;
1686        /* start a child process
1687         * use an event sema for sync
1688         */
1689        sprintf(sema, "\\SEM32\\xterm%s", &ptydev[8]);
1690        if (DosCreateEventSem(sema, &sev, DC_SEM_SHARED, False))
1691            SysError(ERROR_FORK);
1692
1693        switch ((screen->pid = fork())) {
1694        case -1:                /* error */
1695            SysError(ERROR_FORK);
1696        default:                /* parent */
1697            whoami = THE_PARENT;
1698            DosWaitEventSem(sev, 1000L);
1699            DosCloseEventSem(sev);
1700            break;
1701        case 0:         /* child */
1702            whoami = THE_CHILD;
1703
1704/*debug fclose(confd);
1705opencons();*/
1706            /* we don't need the socket, or the pty master anymore */
1707            close(ConnectionNumber(screen->display));
1708            close(screen->respond);
1709
1710            /* Now is the time to set up our process group and
1711             * open up the pty slave.
1712             */
1713            if ((ttyfd = open(ttydev, O_RDWR)) < 0) {
1714                /* dumm gelaufen */
1715                fprintf(stderr, "Cannot open slave side of PTY\n");
1716                exit(1);
1717            }
1718
1719            /* use the same tty name that everyone else will use
1720             * (from ttyname)
1721             */
1722#ifdef EMXNOTBOGUS
1723            if ((ptr = ttyname(ttyfd)) != 0) {
1724                /* it may be bigger */
1725                ttydev = TypeRealloc(char, strlen(ptr) + 1, ttydev);
1726                if (ttydev == NULL) {
1727                    SysError(ERROR_SPREALLOC);
1728                }
1729                (void) strcpy(ttydev, ptr);
1730            }
1731#else
1732            ptr = ttydev;
1733#endif
1734            /* for safety: enable DUPs */
1735            ptioctl(ttyfd, XTY_ENADUP, 0);
1736
1737            /* change ownership of tty to real group and user id */
1738            set_owner(ttydev, screen->uid, screen->gid,
1739                      (resource.messages ? 0622U : 0600U));
1740
1741            /* for the xf86sup-pty, we set the pty to bypass: OS/2 does
1742             * not have a line discipline structure
1743             */
1744            {
1745                TERMIO_STRUCT t, t1;
1746                if (ptioctl(ttyfd, TCGETA, (char *) &t) < 0)
1747                    t = d_tio;
1748
1749                t.c_iflag = ICRNL;
1750                t.c_oflag = OPOST | ONLCR;
1751                t.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
1752
1753                /* ignore error code, user will see it :-) */
1754                ptioctl(ttyfd, TCSETA, (char *) &t);
1755
1756                /* set the console mode */
1757                if (Console) {
1758                    int on = 1;
1759                    if (ioctl(ttyfd, TIOCCONS, (char *) &on) == -1)
1760                        fprintf(stderr, "%s: cannot open console: %s\n",
1761                                xterm_name, strerror(errno));
1762                }
1763            }
1764
1765            signal(SIGCHLD, SIG_DFL);
1766            signal(SIGHUP, SIG_IGN);
1767
1768            /* restore various signals to their defaults */
1769            signal(SIGINT, SIG_DFL);
1770            signal(SIGQUIT, SIG_DFL);
1771            signal(SIGTERM, SIG_DFL);
1772
1773            xtermCopyEnv(gblenvp);
1774
1775            xtermSetenv("TERM", TermName);
1776            if (!TermName)
1777                *newtc = 0;
1778
1779            sprintf(buf, "%lu",
1780                    ((unsigned long) XtWindow(SHELL_OF(CURRENT_EMU()))));
1781            xtermSetenv("WINDOWID", buf);
1782
1783            /* put the display into the environment of the shell */
1784            xtermSetenv("DISPLAY", XDisplayString(screen->display));
1785
1786            xtermSetenv("XTERM_VERSION", xtermVersion());
1787
1788            signal(SIGTERM, SIG_DFL);
1789
1790            /* this is the time to go and set up stdin, out, and err
1791             */
1792            /* dup the tty */
1793            for (i = 0; i <= 2; i++)
1794                if (i != ttyfd) {
1795                    (void) close(i);
1796                    (void) dup(ttyfd);
1797                }
1798
1799            /* and close the tty */
1800            if (ttyfd > 2)
1801                close_fd(ttyfd);
1802
1803            setpgrp(0, pgrp);
1804            (void) xtermResetIds(screen);
1805
1806            if (handshake.rows > 0 && handshake.cols > 0) {
1807                set_max_row(screen, handshake.rows);
1808                set_max_col(screen, handshake.cols);
1809                TTYSIZE_ROWS(ts) = MaxRows(screen);
1810                TTYSIZE_COLS(ts) = MaxCols(screen);
1811                ts.ws_xpixel = FullWidth(screen);
1812                ts.ws_ypixel = FullHeight(screen);
1813            }
1814
1815            sprintf(numbuf, "%d", MaxCols(screen));
1816            xtermSetenv("COLUMNS", numbuf);
1817            sprintf(numbuf, "%d", MaxRows(screen));
1818            xtermSetenv("LINES", numbuf);
1819
1820            gblenvp = environ;
1821
1822            /* need to reset after all the ioctl bashing we did above */
1823            ptioctl(0, TIOCSWINSZ, (char *) &ts);
1824
1825            signal(SIGHUP, SIG_DFL);
1826
1827            /* okay everything seems right, so tell the parent, we are going */
1828            {
1829                char sema[40];
1830                HEV sev;
1831                sprintf(sema, "\\SEM32\\xterm%s", &ttydev[8]);
1832                DosOpenEventSem(sema, &sev);
1833                DosPostEventSem(sev);
1834                DosCloseEventSem(sev);
1835            }
1836
1837#if OPT_LUIT_PROG
1838            /*
1839             * Use two copies of command_to_exec, in case luit is not actually
1840             * there, or refuses to run.  In that case we will fall-through to
1841             * to command that the user gave anyway.
1842             */
1843            if (command_to_exec_with_luit) {
1844                xtermSetenv("XTERM_SHELL",
1845                            xtermFindShell(*command_to_exec_with_luit, False));
1846                TRACE(("spawning command \"%s\"\n", *command_to_exec_with_luit));
1847                execvp(*command_to_exec_with_luit, command_to_exec_with_luit);
1848                /* print error message on screen */
1849                fprintf(stderr, "%s: Can't execvp %s: %s\n",
1850                        xterm_name, *command_to_exec_with_luit, strerror(errno));
1851                fprintf(stderr, "%s: cannot support your locale.\n",
1852                        xterm_name);
1853            }
1854#endif
1855            if (command_to_exec) {
1856                xtermSetenv("XTERM_SHELL",
1857                            xtermFindShell(*command_to_exec, False));
1858                TRACE(("spawning command \"%s\"\n", *command_to_exec));
1859                execvpe(*command_to_exec, command_to_exec, gblenvp);
1860
1861                /* print error message on screen */
1862                fprintf(stderr, "%s: Can't execvp %s\n",
1863                        xterm_name, *command_to_exec);
1864            }
1865
1866            /* use a layered mechanism to find a shell */
1867            ptr = x_getenv("X11SHELL");
1868            if (!ptr)
1869                ptr = x_getenv("SHELL");
1870            if (!ptr)
1871                ptr = x_getenv("OS2_SHELL");
1872            if (!ptr)
1873                ptr = "SORRY_NO_SHELL_FOUND";
1874            xtermSetenv("XTERM_SHELL", ptr);
1875
1876            shname = x_basename(ptr);
1877            if (command_to_exec) {
1878                char *exargv[10];       /*XXX */
1879
1880                exargv[0] = ptr;
1881                exargv[1] = "/C";
1882                exargv[2] = command_to_exec[0];
1883                exargv[3] = command_to_exec[1];
1884                exargv[4] = command_to_exec[2];
1885                exargv[5] = command_to_exec[3];
1886                exargv[6] = command_to_exec[4];
1887                exargv[7] = command_to_exec[5];
1888                exargv[8] = command_to_exec[6];
1889                exargv[9] = 0;
1890                execvpe(exargv[0], exargv, gblenvp);
1891
1892                /* print error message on screen */
1893                fprintf(stderr, "%s: Can't execvp %s\n",
1894                        xterm_name, *command_to_exec);
1895            } else {
1896                execlpe(ptr, shname, 0, gblenvp);
1897
1898                /* Exec failed. */
1899                fprintf(stderr, "%s: Could not exec %s!\n",
1900                        xterm_name, ptr);
1901            }
1902            sleep(5);
1903
1904            /* preventively shoot the parent */
1905            kill(-getppid(), SIGTERM);
1906
1907            exit(ERROR_EXEC);
1908        }                       /* endcase */
1909    }
1910    /* !am_slave */
1911    signal(SIGHUP, SIG_IGN);
1912/*
1913 * Unfortunately, System V seems to have trouble divorcing the child process
1914 * from the process group of xterm.  This is a problem because hitting the
1915 * INTR or QUIT characters on the keyboard will cause xterm to go away if we
1916 * don't ignore the signals.  This is annoying.
1917 */
1918
1919/*  signal (SIGINT, SIG_IGN);*/
1920    signal(SIGINT, killit);
1921    signal(SIGTERM, killit);
1922
1923    /* hung shell problem */
1924    signal(SIGQUIT, SIG_IGN);
1925/*  signal (SIGTERM, SIG_IGN);*/
1926    return 0;
1927}                               /* end spawnXTerm */
1928
1929SIGNAL_T
1930Exit(int n)
1931{
1932    TScreen *screen = TScreenOf(term);
1933    int pty = term->screen.respond;     /* file descriptor of pty */
1934    close(pty);                 /* close explicitly to avoid race with slave side */
1935#ifdef ALLOWLOGGING
1936    if (screen->logging)
1937        CloseLog(screen);
1938#endif
1939    if (am_slave < 0) {
1940        /* restore ownership of tty and pty */
1941        set_owner(ttydev, 0, 0, 0666U);
1942        set_owner(ptydev, 0, 0, 0666U);
1943    }
1944    exit(n);
1945    SIGNAL_RETURN;
1946}
1947
1948/* ARGSUSED */
1949static void
1950resize_termcap(XtermWidget xw, char *newtc)
1951{
1952}
1953
1954/*
1955 * Does a non-blocking wait for a child process.  If the system
1956 * doesn't support non-blocking wait, do nothing.
1957 * Returns the pid of the child, or 0 or -1 if none or error.
1958 */
1959int
1960nonblocking_wait(void)
1961{
1962    pid_t pid;
1963
1964    pid = waitpid(-1, NULL, WNOHANG);
1965    return pid;
1966}
1967
1968/* ARGSUSED */
1969static SIGNAL_T
1970reapchild(int n GCC_UNUSED)
1971{
1972    int olderrno = errno;
1973    int pid;
1974
1975    pid = wait(NULL);
1976
1977    /* cannot re-enable signal before waiting for child
1978     * because then SVR4 loops.  Sigh.  HP-UX 9.01 too.
1979     */
1980    (void) signal(SIGCHLD, reapchild);
1981
1982    do {
1983        if (pid == term->screen.pid) {
1984#ifdef DEBUG
1985            if (debug)
1986                fputs("Exiting\n", stderr);
1987#endif
1988            if (!hold_screen)
1989                need_cleanup = True;
1990        }
1991    } while ((pid = nonblocking_wait()) > 0);
1992
1993    errno = olderrno;
1994    SIGNAL_RETURN;
1995}
1996
1997/*
1998 * parse_tty_modes accepts lines of the following form:
1999 *
2000 *         [SETTING] ...
2001 *
2002 * where setting consists of the words in the modelist followed by a character
2003 * or ^char.
2004 */
2005static int
2006parse_tty_modes(char *s, struct _xttymodes *modelist)
2007{
2008    struct _xttymodes *mp;
2009    int c;
2010    int count = 0;
2011
2012    TRACE(("parse_tty_modes\n"));
2013    while (1) {
2014        size_t len;
2015
2016        while (*s && isascii(CharOf(*s)) && isspace(CharOf(*s)))
2017            s++;
2018        if (!*s)
2019            return count;
2020
2021        for (len = 0; isalnum(CharOf(s[len])); ++len) ;
2022        for (mp = modelist; mp->name; mp++) {
2023            if (len == mp->len
2024                && strncmp(s, mp->name, mp->len) == 0)
2025                break;
2026        }
2027        if (!mp->name)
2028            return -1;
2029
2030        s += mp->len;
2031        while (*s && isascii(CharOf(*s)) && isspace(CharOf(*s)))
2032            s++;
2033        if (!*s)
2034            return -1;
2035
2036        if ((c = decode_keyvalue(&s, False)) != -1) {
2037            mp->value = c;
2038            mp->set = 1;
2039            count++;
2040            TRACE(("...parsed #%d: %s=%#x\n", count, mp->name, c));
2041        }
2042    }
2043}
2044
2045int
2046GetBytesAvailable(int fd)
2047{
2048    long arg;
2049    ioctl(fd, FIONREAD, (char *) &arg);
2050    return (int) arg;
2051}
2052
2053/* Utility function to try to hide system differences from
2054   everybody who used to call killpg() */
2055
2056int
2057kill_process_group(int pid, int sig)
2058{
2059    return kill(-pid, sig);
2060}
2061
2062int
2063ptioctl(int fd, int func, void *data)
2064{
2065    APIRET rc;
2066    ULONG len;
2067    struct pt_termios pt;
2068    TERMIO_STRUCT *t;
2069    int i;
2070
2071    switch (func) {
2072    case TCGETA:
2073        rc = DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCGETA,
2074                         NULL, 0, NULL,
2075                         (ULONG *) & pt, sizeof(struct pt_termios), &len);
2076        if (rc)
2077            return -1;
2078        t = (TERMIO_STRUCT *) data;
2079        t->c_iflag = pt.c_iflag;
2080        t->c_oflag = pt.c_oflag;
2081        t->c_cflag = pt.c_cflag;
2082        t->c_lflag = pt.c_lflag;
2083        for (i = 0; i < NCC; i++)
2084            t->c_cc[i] = pt.c_cc[i];
2085        return 0;
2086    case TCSETA:
2087    case TCSETAW:
2088    case TCSETAF:
2089        t = (TERMIO_STRUCT *) data;
2090        pt.c_iflag = t->c_iflag;
2091        pt.c_oflag = t->c_oflag;
2092        pt.c_cflag = t->c_cflag;
2093        pt.c_lflag = t->c_lflag;
2094
2095        for (i = 0; i < NCC; i++)
2096            pt.c_cc[i] = t->c_cc[i];
2097        if (func == TCSETA)
2098            i = XTY_TIOCSETA;
2099        else if (func == TCSETAW)
2100            i = XTY_TIOCSETAW;
2101        else
2102            i = XTY_TIOCSETAF;
2103        rc = DosDevIOCtl(fd, XFREE86_PTY, i,
2104                         (ULONG *) & pt, sizeof(struct pt_termios), &len,
2105                         NULL, 0, NULL);
2106        return (rc) ? -1 : 0;
2107    case TIOCCONS:
2108        return DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCCONS,
2109                           (ULONG *) data, sizeof(ULONG), &len,
2110                           NULL, 0, NULL);
2111    case TIOCSWINSZ:
2112        return DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCSWINSZ,
2113                           (ULONG *) data, sizeof(TTYSIZE_STRUCT), &len,
2114                           NULL, 0, NULL);
2115    case TIOCGWINSZ:
2116        return DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCGWINSZ,
2117                           NULL, 0, NULL,
2118                           (ULONG *) data, sizeof(TTYSIZE_STRUCT), &len);
2119    case XTY_ENADUP:
2120        i = 1;
2121        return DosDevIOCtl(fd, XFREE86_PTY, XTY_ENADUP,
2122                           (ULONG *) & i, sizeof(ULONG), &len,
2123                           NULL, 0, NULL);
2124    case XTY_TRACE:
2125        i = 2;
2126        return DosDevIOCtl(fd, XFREE86_PTY, XTY_TRACE,
2127                           (ULONG *) & i, sizeof(ULONG), &len,
2128                           NULL, 0, NULL);
2129    case PTMS_GETPTY:
2130        i = 1;
2131        return DosDevIOCtl(fd, XFREE86_PTY, PTMS_GETPTY,
2132                           (ULONG *) & i, sizeof(ULONG), &len,
2133                           (UCHAR *) data, 14, &len);
2134    default:
2135        return -1;
2136    }
2137}
Note: See TracBrowser for help on using the browser.