1 /* $XTermId: os2main.c,v 1.265 2010/06/20 21:27:07 tom Exp $ */
3 /* removed all foreign stuff to get the code more clear (hv)
4 * and did some rewrite for the obscure OS/2 environment
7 /***********************************************************
9 Copyright (c) 1987, 1988 X Consortium
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
18 The above copyright notice and this permission notice shall be included in
19 all copies or substantial portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 Except as contained in this notice, the name of the X Consortium shall not be
29 used in advertising or otherwise to promote the sale, use or other dealings
30 in this Software without prior written authorization from the X Consortium.
32 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard.
36 Permission to use, copy, modify, and distribute this software and its
37 documentation for any purpose and without fee is hereby granted,
38 provided that the above copyright notice appear in all copies and that
39 both that copyright notice and this permission notice appear in
40 supporting documentation, and that the name of Digital not be used in
41 advertising or publicity pertaining to distribution of the software
42 without specific, written prior permission.
44 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
45 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
46 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
47 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
48 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
49 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
52 ******************************************************************/
55 #define INCL_DOSFILEMGR
56 #define INCL_DOSDEVIOCTL
57 #define INCL_DOSSEMAPHORES
58 #ifdef __INNOTEK_LIBC__
59 #define INCL_DOSDEVICES
65 #define RES_OFFSET(field) XtOffsetOf(XTERM_RESOURCE, field)
69 #include <X11/cursorfont.h>
71 #include <X11/Xlocale.h>
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>
86 #endif /* OPT_TOOLBAR */
100 #include <charclass.h>
104 setpgrp(pid_t pid, gid_t pgid)
110 chown(const char *fn, pid_t pid, gid_t gid)
121 #include <sys/stat.h>
122 #include <sys/param.h> /* for NOFILE */
126 static SIGNAL_T reapchild(int n);
127 static int spawnXTerm(XtermWidget /* xw */ );
128 static void resize_termcap(XtermWidget xw);
129 static void set_owner(char *device, uid_t uid, gid_t gid, mode_t mode);
131 static Bool added_utmp_entry = False;
133 static uid_t save_ruid;
134 static gid_t save_rgid;
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
143 static char **command_to_exec = NULL;
146 static char **command_to_exec_with_luit = NULL;
149 /* The following structures are initialized in main() in order
150 ** to eliminate any assumptions about the internal order of their
153 static struct termio d_tio;
155 /* allow use of system default characters if defined and reasonable */
157 #define CEOF CONTROL('D')
163 #define CFLUSH CONTROL('O')
166 #define CLNEXT CONTROL('V')
172 #define CQUIT CONTROL('\\')
175 #define CRPRNT CONTROL('R')
178 #define CSTART CONTROL('Q')
181 #define CSTOP CONTROL('S')
184 #define CSUSP CONTROL('Z')
190 #define CWERASE CONTROL('W')
193 #define TERMIO_STRUCT struct termio
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.
200 #define TTYMODE(name) { name, sizeof(name)-1, 0, 0 }
201 static Boolean override_tty_modes = False;
203 static struct _xttymodes {
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 */
245 #define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value
247 static int parse_tty_modes(char *s, struct _xttymodes *modelist);
249 static char passedPty[2]; /* name if pty if slave */
252 #include <X11/Xmu/SysUtil.h> /* XmuGetHostname */
253 #define MIT_CONSOLE_LEN 12
254 #define MIT_CONSOLE "MIT_CONSOLE_"
255 static char mit_console_name[255 + MIT_CONSOLE_LEN + 1] = MIT_CONSOLE;
256 static Atom mit_console;
261 /* used by VT (charproc.c) */
263 static XtResource application_resources[] =
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"),
280 Bres("sunKeyboard", "SunKeyboard", sunKeyboard, False),
283 Bres("hpFunctionKeys", "HpFunctionKeys", hpFunctionKeys, False),
285 #if OPT_SCO_FUNC_KEYS
286 Bres("scoFunctionKeys", "ScoFunctionKeys", scoFunctionKeys, False),
288 #if OPT_SUN_FUNC_KEYS
289 Bres("sunFunctionKeys", "SunFunctionKeys", sunFunctionKeys, False),
292 Bres("tcapFunctionKeys", "TcapFunctionKeys", termcapKeys, False),
294 #if OPT_INITIAL_ERASE
295 Bres("ptyInitialErase", "PtyInitialErase", ptyInitialErase, DEF_INITIAL_ERASE),
296 Bres("backarrowKeyIsErase", "BackarrowKeyIsErase", backarrow_is_erase, DEF_BACKARO_ERASE),
298 Bres("useInsertMode", "UseInsertMode", useInsertMode, False),
300 Ires("zIconBeep", "ZIconBeep", zIconBeep, 0),
302 #if OPT_PTY_HANDSHAKE
303 Bres("waitForMap", "WaitForMap", wait_for_map, False),
304 Bres("ptyHandshake", "PtyHandshake", ptyHandshake, True),
305 Bres("ptySttySize", "PtySttySize", ptySttySize, DEF_PTY_STTY_SIZE),
308 Bres("sameName", "SameName", sameName, True),
311 Bres("sessionMgt", "SessionMgt", sessionMgt, True),
314 Bres(XtNtoolBar, XtCToolBar, toolBar, True),
317 Bres(XtNmaximized, XtCMaximized, maximized, False),
321 static String fallback_resources[] =
323 "*SimpleMenu*menuLabel.vertSpace: 100",
324 "*SimpleMenu*HorizontalMargins: 16",
325 "*SimpleMenu*Sme.height: 16",
326 "*SimpleMenu*Cursor: left_ptr",
327 "*mainMenu.Label: Main Options (no app-defaults)",
328 "*vtMenu.Label: VT Options (no app-defaults)",
329 "*fontMenu.Label: VT Fonts (no app-defaults)",
331 "*tekMenu.Label: Tek Options (no app-defaults)",
336 /* Command line options table. Only resources are entered here...there is a
337 pass over the remaining options after XrmParseCommand is let loose. */
339 static XrmOptionDescRec optionDescList[] = {
340 {"-geometry", "*vt100.geometry",XrmoptionSepArg, (XPointer) NULL},
341 {"-132", "*c132", XrmoptionNoArg, (XPointer) "on"},
342 {"+132", "*c132", XrmoptionNoArg, (XPointer) "off"},
343 {"-ah", "*alwaysHighlight", XrmoptionNoArg, (XPointer) "on"},
344 {"+ah", "*alwaysHighlight", XrmoptionNoArg, (XPointer) "off"},
345 {"-aw", "*autoWrap", XrmoptionNoArg, (XPointer) "on"},
346 {"+aw", "*autoWrap", XrmoptionNoArg, (XPointer) "off"},
347 #ifndef NO_ACTIVE_ICON
348 {"-ai", "*activeIcon", XrmoptionNoArg, (XPointer) "off"},
349 {"+ai", "*activeIcon", XrmoptionNoArg, (XPointer) "on"},
350 #endif /* NO_ACTIVE_ICON */
351 {"-b", "*internalBorder",XrmoptionSepArg, (XPointer) NULL},
352 {"-bc", "*cursorBlink", XrmoptionNoArg, (XPointer) "on"},
353 {"+bc", "*cursorBlink", XrmoptionNoArg, (XPointer) "off"},
354 {"-bcf", "*cursorOffTime",XrmoptionSepArg, (XPointer) NULL},
355 {"-bcn", "*cursorOnTime",XrmoptionSepArg, (XPointer) NULL},
356 {"-bdc", "*colorBDMode", XrmoptionNoArg, (XPointer) "off"},
357 {"+bdc", "*colorBDMode", XrmoptionNoArg, (XPointer) "on"},
358 {"-cb", "*cutToBeginningOfLine", XrmoptionNoArg, (XPointer) "off"},
359 {"+cb", "*cutToBeginningOfLine", XrmoptionNoArg, (XPointer) "on"},
360 {"-cc", "*charClass", XrmoptionSepArg, (XPointer) NULL},
361 {"-cm", "*colorMode", XrmoptionNoArg, (XPointer) "off"},
362 {"+cm", "*colorMode", XrmoptionNoArg, (XPointer) "on"},
363 {"-cn", "*cutNewline", XrmoptionNoArg, (XPointer) "off"},
364 {"+cn", "*cutNewline", XrmoptionNoArg, (XPointer) "on"},
365 {"-cr", "*cursorColor", XrmoptionSepArg, (XPointer) NULL},
366 {"-cu", "*curses", XrmoptionNoArg, (XPointer) "on"},
367 {"+cu", "*curses", XrmoptionNoArg, (XPointer) "off"},
368 {"-dc", "*dynamicColors",XrmoptionNoArg, (XPointer) "off"},
369 {"+dc", "*dynamicColors",XrmoptionNoArg, (XPointer) "on"},
370 {"-fb", "*boldFont", XrmoptionSepArg, (XPointer) NULL},
371 {"-fbb", "*freeBoldBox", XrmoptionNoArg, (XPointer)"off"},
372 {"+fbb", "*freeBoldBox", XrmoptionNoArg, (XPointer)"on"},
373 {"-fbx", "*forceBoxChars", XrmoptionNoArg, (XPointer)"off"},
374 {"+fbx", "*forceBoxChars", XrmoptionNoArg, (XPointer)"on"},
375 #ifndef NO_ACTIVE_ICON
376 {"-fi", "*iconFont", XrmoptionSepArg, (XPointer) NULL},
377 #endif /* NO_ACTIVE_ICON */
379 {"-fa", "*faceName", XrmoptionSepArg, (XPointer) NULL},
380 {"-fd", "*faceNameDoublesize", XrmoptionSepArg, (XPointer) NULL},
381 {"-fs", "*faceSize", XrmoptionSepArg, (XPointer) NULL},
384 {"-fw", "*wideFont", XrmoptionSepArg, (XPointer) NULL},
385 {"-fwb", "*wideBoldFont", XrmoptionSepArg, (XPointer) NULL},
388 {"-fx", "*ximFont", XrmoptionSepArg, (XPointer) NULL},
390 #if OPT_HIGHLIGHT_COLOR
391 {"-hc", "*highlightColor", XrmoptionSepArg, (XPointer) NULL},
392 {"-hm", "*highlightColorMode", XrmoptionNoArg, (XPointer) "on"},
393 {"+hm", "*highlightColorMode", XrmoptionNoArg, (XPointer) "off"},
394 {"-selfg", "*highlightTextColor", XrmoptionSepArg, (XPointer) NULL},
395 {"-selbg", "*highlightColor", XrmoptionSepArg, (XPointer) NULL},
398 {"-hf", "*hpFunctionKeys",XrmoptionNoArg, (XPointer) "on"},
399 {"+hf", "*hpFunctionKeys",XrmoptionNoArg, (XPointer) "off"},
401 {"-hold", "*hold", XrmoptionNoArg, (XPointer) "on"},
402 {"+hold", "*hold", XrmoptionNoArg, (XPointer) "off"},
403 #if OPT_INITIAL_ERASE
404 {"-ie", "*ptyInitialErase", XrmoptionNoArg, (XPointer) "on"},
405 {"+ie", "*ptyInitialErase", XrmoptionNoArg, (XPointer) "off"},
407 {"-j", "*jumpScroll", XrmoptionNoArg, (XPointer) "on"},
408 {"+j", "*jumpScroll", XrmoptionNoArg, (XPointer) "off"},
410 {"-k8", "*allowC1Printable", XrmoptionNoArg, (XPointer) "on"},
411 {"+k8", "*allowC1Printable", XrmoptionNoArg, (XPointer) "off"},
413 {"-kt", "*keyboardType", XrmoptionSepArg, (XPointer) NULL},
414 {"+kt", "*keyboardType", XrmoptionSepArg, (XPointer) NULL},
415 /* parse logging options anyway for compatibility */
416 {"-l", "*logging", XrmoptionNoArg, (XPointer) "on"},
417 {"+l", "*logging", XrmoptionNoArg, (XPointer) "off"},
418 {"-lf", "*logFile", XrmoptionSepArg, (XPointer) NULL},
419 {"-ls", "*loginShell", XrmoptionNoArg, (XPointer) "on"},
420 {"+ls", "*loginShell", XrmoptionNoArg, (XPointer) "off"},
421 {"-mb", "*marginBell", XrmoptionNoArg, (XPointer) "on"},
422 {"+mb", "*marginBell", XrmoptionNoArg, (XPointer) "off"},
423 {"-mc", "*multiClickTime", XrmoptionSepArg, (XPointer) NULL},
424 {"-mesg", "*messages", XrmoptionNoArg, (XPointer) "off"},
425 {"+mesg", "*messages", XrmoptionNoArg, (XPointer) "on"},
426 {"-ms", "*pointerColor",XrmoptionSepArg, (XPointer) NULL},
427 {"-nb", "*nMarginBell", XrmoptionSepArg, (XPointer) NULL},
428 {"-nul", "*underLine", XrmoptionNoArg, (XPointer) "off"},
429 {"+nul", "*underLine", XrmoptionNoArg, (XPointer) "on"},
430 {"-pc", "*boldColors", XrmoptionNoArg, (XPointer) "on"},
431 {"+pc", "*boldColors", XrmoptionNoArg, (XPointer) "off"},
432 {"-rw", "*reverseWrap", XrmoptionNoArg, (XPointer) "on"},
433 {"+rw", "*reverseWrap", XrmoptionNoArg, (XPointer) "off"},
434 {"-s", "*multiScroll", XrmoptionNoArg, (XPointer) "on"},
435 {"+s", "*multiScroll", XrmoptionNoArg, (XPointer) "off"},
436 {"-sb", "*scrollBar", XrmoptionNoArg, (XPointer) "on"},
437 {"+sb", "*scrollBar", XrmoptionNoArg, (XPointer) "off"},
438 #ifdef SCROLLBAR_RIGHT
439 {"-leftbar", "*rightScrollBar", XrmoptionNoArg, (XPointer) "off"},
440 {"-rightbar", "*rightScrollBar", XrmoptionNoArg, (XPointer) "on"},
442 {"-rvc", "*colorRVMode", XrmoptionNoArg, (XPointer) "off"},
443 {"+rvc", "*colorRVMode", XrmoptionNoArg, (XPointer) "on"},
444 {"-sf", "*sunFunctionKeys", XrmoptionNoArg, (XPointer) "on"},
445 {"+sf", "*sunFunctionKeys", XrmoptionNoArg, (XPointer) "off"},
446 {"-si", "*scrollTtyOutput", XrmoptionNoArg, (XPointer) "off"},
447 {"+si", "*scrollTtyOutput", XrmoptionNoArg, (XPointer) "on"},
448 {"-sk", "*scrollKey", XrmoptionNoArg, (XPointer) "on"},
449 {"+sk", "*scrollKey", XrmoptionNoArg, (XPointer) "off"},
450 {"-sl", "*saveLines", XrmoptionSepArg, (XPointer) NULL},
452 {"-sp", "*sunKeyboard", XrmoptionNoArg, (XPointer) "on"},
453 {"+sp", "*sunKeyboard", XrmoptionNoArg, (XPointer) "off"},
456 {"-t", "*tekStartup", XrmoptionNoArg, (XPointer) "on"},
457 {"+t", "*tekStartup", XrmoptionNoArg, (XPointer) "off"},
459 {"-ti", "*decTerminalID",XrmoptionSepArg, (XPointer) NULL},
460 {"-tm", "*ttyModes", XrmoptionSepArg, (XPointer) NULL},
461 {"-tn", "*termName", XrmoptionSepArg, (XPointer) NULL},
463 {"-u8", "*utf8", XrmoptionNoArg, (XPointer) "2"},
464 {"+u8", "*utf8", XrmoptionNoArg, (XPointer) "0"},
467 {"-lc", "*locale", XrmoptionNoArg, (XPointer) "on"},
468 {"+lc", "*locale", XrmoptionNoArg, (XPointer) "off"},
469 {"-lcc", "*localeFilter",XrmoptionSepArg, (XPointer) NULL},
470 {"-en", "*locale", XrmoptionSepArg, (XPointer) NULL},
472 {"-uc", "*cursorUnderLine", XrmoptionNoArg, (XPointer) "on"},
473 {"+uc", "*cursorUnderLine", XrmoptionNoArg, (XPointer) "off"},
474 {"-ulc", "*colorULMode", XrmoptionNoArg, (XPointer) "off"},
475 {"+ulc", "*colorULMode", XrmoptionNoArg, (XPointer) "on"},
476 {"-ulit", "*italicULMode", XrmoptionNoArg, (XPointer) "off"},
477 {"+ulit", "*italicULMode", XrmoptionNoArg, (XPointer) "on"},
478 {"-ut", "*utmpInhibit", XrmoptionNoArg, (XPointer) "on"},
479 {"+ut", "*utmpInhibit", XrmoptionNoArg, (XPointer) "off"},
480 {"-im", "*useInsertMode", XrmoptionNoArg, (XPointer) "on"},
481 {"+im", "*useInsertMode", XrmoptionNoArg, (XPointer) "off"},
482 {"-vb", "*visualBell", XrmoptionNoArg, (XPointer) "on"},
483 {"+vb", "*visualBell", XrmoptionNoArg, (XPointer) "off"},
484 {"-pob", "*popOnBell", XrmoptionNoArg, (XPointer) "on"},
485 {"+pob", "*popOnBell", XrmoptionNoArg, (XPointer) "off"},
487 {"-wc", "*wideChars", XrmoptionNoArg, (XPointer) "on"},
488 {"+wc", "*wideChars", XrmoptionNoArg, (XPointer) "off"},
489 {"-mk_width", "*mkWidth", XrmoptionNoArg, (XPointer) "on"},
490 {"+mk_width", "*mkWidth", XrmoptionNoArg, (XPointer) "off"},
491 {"-cjk_width", "*cjkWidth", XrmoptionNoArg, (XPointer) "on"},
492 {"+cjk_width", "*cjkWidth", XrmoptionNoArg, (XPointer) "off"},
494 {"-wf", "*waitForMap", XrmoptionNoArg, (XPointer) "on"},
495 {"+wf", "*waitForMap", XrmoptionNoArg, (XPointer) "off"},
497 {"-ziconbeep", "*zIconBeep", XrmoptionSepArg, (XPointer) NULL},
500 {"-samename", "*sameName", XrmoptionNoArg, (XPointer) "on"},
501 {"+samename", "*sameName", XrmoptionNoArg, (XPointer) "off"},
504 {"-sm", "*sessionMgt", XrmoptionNoArg, (XPointer) "on"},
505 {"+sm", "*sessionMgt", XrmoptionNoArg, (XPointer) "off"},
508 {"-tb", "*"XtNtoolBar, XrmoptionNoArg, (XPointer) "on"},
509 {"+tb", "*"XtNtoolBar, XrmoptionNoArg, (XPointer) "off"},
512 {"-maximized", "*maximized", XrmoptionNoArg, (XPointer) "on"},
513 {"+maximized", "*maximized", XrmoptionNoArg, (XPointer) "off"},
515 /* options that we process ourselves */
516 {"-help", NULL, XrmoptionSkipNArgs, (XPointer) NULL},
517 {"-version", NULL, XrmoptionSkipNArgs, (XPointer) NULL},
518 {"-class", NULL, XrmoptionSkipArg, (XPointer) NULL},
519 {"-e", NULL, XrmoptionSkipLine, (XPointer) NULL},
520 {"-into", NULL, XrmoptionSkipArg, (XPointer) NULL},
521 /* bogus old compatibility stuff for which there are
522 standard XtOpenApplication options now */
523 {"%", "*tekGeometry", XrmoptionStickyArg, (XPointer) NULL},
524 {"#", ".iconGeometry",XrmoptionStickyArg, (XPointer) NULL},
525 {"-T", ".title", XrmoptionSepArg, (XPointer) NULL},
526 {"-n", "*iconName", XrmoptionSepArg, (XPointer) NULL},
527 {"-r", "*reverseVideo",XrmoptionNoArg, (XPointer) "on"},
528 {"+r", "*reverseVideo",XrmoptionNoArg, (XPointer) "off"},
529 {"-rv", "*reverseVideo",XrmoptionNoArg, (XPointer) "on"},
530 {"+rv", "*reverseVideo",XrmoptionNoArg, (XPointer) "off"},
531 {"-w", ".borderWidth", XrmoptionSepArg, (XPointer) NULL},
534 static OptionHelp xtermOptions[] = {
535 { "-version", "print the version number" },
536 { "-help", "print out this message" },
537 { "-display displayname", "X server to contact" },
538 { "-geometry geom", "size (in characters) and position" },
539 { "-/+rv", "turn on/off reverse video" },
540 { "-bg color", "background color" },
541 { "-fg color", "foreground color" },
542 { "-bd color", "border color" },
543 { "-bw number", "border width in pixels" },
544 { "-fn fontname", "normal text font" },
545 { "-fb fontname", "bold text font" },
546 { "-/+fbb", "turn on/off normal/bold font comparison inhibit"},
547 { "-/+fbx", "turn off/on linedrawing characters"},
549 { "-fa pattern", "FreeType font-selection pattern" },
550 { "-fd pattern", "FreeType Doublesize font-selection pattern" },
551 { "-fs size", "FreeType font-size" },
554 { "-fw fontname", "doublewidth text font" },
555 { "-fwb fontname", "doublewidth bold text font" },
558 { "-fx fontname", "XIM fontset" },
560 { "-iconic", "start iconic" },
561 { "-name string", "client instance, icon, and title strings" },
562 { "-class string", "class string (XTerm)" },
563 { "-title string", "title string" },
564 { "-xrm resourcestring", "additional resource specifications" },
565 { "-/+132", "turn on/off 80/132 column switching" },
566 { "-/+ah", "turn on/off always highlight" },
567 #ifndef NO_ACTIVE_ICON
568 { "-/+ai", "turn off/on active icon" },
569 { "-fi fontname", "icon font for active icon" },
570 #endif /* NO_ACTIVE_ICON */
571 { "-b number", "internal border in pixels" },
572 { "-/+bc", "turn on/off text cursor blinking" },
573 { "-bcf milliseconds", "time text cursor is off when blinking"},
574 { "-bcn milliseconds", "time text cursor is on when blinking"},
575 { "-/+bdc", "turn off/on display of bold as color"},
576 { "-/+cb", "turn on/off cut-to-beginning-of-line inhibit" },
577 { "-cc classrange", "specify additional character classes" },
578 { "-/+cm", "turn off/on ANSI color mode" },
579 { "-/+cn", "turn on/off cut newline inhibit" },
580 { "-cr color", "text cursor color" },
581 { "-/+cu", "turn on/off curses emulation" },
582 { "-/+dc", "turn off/on dynamic color selection" },
583 #if OPT_HIGHLIGHT_COLOR
584 { "-/+hm", "turn on/off selection-color override" },
585 { "-selbg color", "selection background color" },
586 { "-selfg color", "selection foreground color" },
589 { "-/+hf", "turn on/off HP Function Key escape codes" },
591 { "-/+hold", "turn on/off logic that retains window after exit" },
592 #if OPT_INITIAL_ERASE
593 { "-/+ie", "turn on/off initialization of 'erase' from pty" },
595 { "-/+im", "use insert mode for TERMCAP" },
596 { "-/+j", "turn on/off jump scroll" },
598 { "-/+k8", "turn on/off C1-printable classification"},
600 { "-kt keyboardtype", "set keyboard type:" KEYBOARD_TYPES },
602 { "-/+l", "turn on/off logging" },
603 { "-lf filename", "logging filename" },
605 { "-/+l", "turn on/off logging (not supported)" },
606 { "-lf filename", "logging filename (not supported)" },
608 { "-/+ls", "turn on/off login shell" },
609 { "-/+mb", "turn on/off margin bell" },
610 { "-mc milliseconds", "multiclick time in milliseconds" },
611 { "-/+mesg", "forbid/allow messages" },
612 { "-ms color", "pointer color" },
613 { "-nb number", "margin bell in characters from right end" },
614 { "-/+nul", "turn off/on display of underlining" },
615 { "-/+aw", "turn on/off auto wraparound" },
616 { "-/+pc", "turn on/off PC-style bold colors" },
617 { "-/+rw", "turn on/off reverse wraparound" },
618 { "-/+s", "turn on/off multiscroll" },
619 { "-/+sb", "turn on/off scrollbar" },
620 #ifdef SCROLLBAR_RIGHT
621 { "-rightbar", "force scrollbar right (default left)" },
622 { "-leftbar", "force scrollbar left" },
624 { "-/+rvc", "turn off/on display of reverse as color" },
625 { "-/+sf", "turn on/off Sun Function Key escape codes" },
626 { "-/+si", "turn on/off scroll-on-tty-output inhibit" },
627 { "-/+sk", "turn on/off scroll-on-keypress" },
628 { "-sl number", "number of scrolled lines to save" },
630 { "-/+sp", "turn on/off Sun/PC Function/Keypad mapping" },
633 { "-/+t", "turn on/off Tek emulation window" },
636 { "-/+tb", "turn on/off toolbar" },
638 { "-ti termid", "terminal identifier" },
639 { "-tm string", "terminal mode keywords and characters" },
640 { "-tn name", "TERM environment variable name" },
642 { "-/+u8", "turn on/off UTF-8 mode (implies wide-characters)" },
645 { "-/+lc", "turn on/off locale mode using luit" },
646 { "-lcc path", "filename of locale converter (" DEFLOCALEFILTER ")" },
648 { "-/+uc", "turn on/off underline cursor" },
649 { "-/+ulc", "turn off/on display of underline as color" },
650 { "-/+ut", "turn on/off utmp inhibit (not supported)" },
651 { "-/+ulit", "turn off/on display of underline as italics" },
652 { "-/+vb", "turn on/off visual bell" },
653 { "-/+pob", "turn on/off pop on bell" },
655 { "-/+wc", "turn on/off wide-character mode" },
656 { "-/+mk_width", "turn on/off simple width convention" },
657 { "-/+cjk_width", "turn on/off legacy CJK width convention" },
659 { "-/+wf", "turn on/off wait for map before command exec" },
660 { "-e command args ...", "command to execute" },
662 { "%geom", "Tek window geometry" },
664 { "#geom", "icon window geometry" },
665 { "-T string", "title name for window" },
666 { "-n string", "icon name for window" },
667 { "-C", "intercept console messages" },
668 { "-Sccn", "slave mode on \"ttycc\", file descriptor \"n\"" },
669 { "-into windowId", "use the window id given to -into as the parent window rather than the default root window" },
671 { "-ziconbeep percent", "beep and flag icon of window having hidden output" },
674 { "-/+samename", "turn on/off the no-flicker option for title and icon name" },
677 { "-/+sm", "turn on/off the session-management support" },
680 {"-/+maximized", "turn on/off maxmize on startup" },
700 if ((confd = fopen("/dev/console$", "w")) < 0) {
701 fputs("!!! Cannot open console device.\n",
707 #define opencons() /* nothing */
708 #define closecons() /* nothing */
711 static const char *message[] =
713 "Fonts should be fixed width and, if both normal and bold are specified, should",
714 "have the same size. If only a normal font is specified, it will be used for",
715 "both normal and bold text (by doing overstriking). The -e option, if given,",
716 "must appear at the end of the command line, otherwise the user's default shell",
717 "will be started. Options that start with a plus sign (+) restore the default.",
721 * Decode a key-definition. This combines the termcap and ttyModes, for
722 * comparison. Note that octal escapes in ttyModes are done by the normal
723 * resource translation. Also, ttyModes allows '^-' as a synonym for disabled.
726 decode_keyvalue(char **ptr, int termcap)
731 TRACE(("...decode '%s'\n", string));
732 if (*string == '^') {
735 value = A2E(ANSI_DEL);
740 #if defined(_POSIX_VDISABLE) && defined(HAVE_UNISTD_H)
741 value = _POSIX_VDISABLE;
743 #if defined(_PC_VDISABLE)
745 value = fpathconf(0, _PC_VDISABLE);
748 break; /* skip this (error) */
752 #elif defined(VDISABLE)
760 value = CONTROL(*string);
764 } else if (termcap && (*string == '\\')) {
766 int temp = strtol(string + 1, &d, 8);
767 if (temp > 0 && d != string) {
772 value = CharOf(*string);
780 abbrev(const char *tst, const char *cmp, size_t need)
782 size_t len = strlen(tst);
783 return ((len >= need) && (!strncmp(tst, cmp, len)));
787 Syntax(char *badOption)
790 OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList));
793 fprintf(stderr, "%s: bad command line option \"%s\"\r\n\n",
794 ProgramName, badOption);
796 fprintf(stderr, "usage: %s", ProgramName);
797 col = 8 + (int) strlen(ProgramName);
798 for (opt = list; opt->opt; opt++) {
799 int len = 3 + (int) strlen(opt->opt); /* space [ string ] */
800 if (col + len > 79) {
801 fprintf(stderr, "\r\n "); /* 3 spaces */
804 fprintf(stderr, " [%s]", opt->opt);
808 fprintf(stderr, "\r\n\nType %s -help for a full description.\r\n\n",
816 printf("%s\n", xtermVersion());
824 OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList));
827 printf("%s usage:\n %s [-options ...] [-e command args]\n\n",
828 xtermVersion(), ProgramName);
829 printf("where options include:\n");
830 for (opt = list; opt->opt; opt++) {
831 printf(" %-28s %s\n", opt->opt, opt->desc);
835 for (cpp = message; *cpp; cpp++)
843 ConvertConsoleSelection(Widget w GCC_UNUSED,
844 Atom * selection GCC_UNUSED,
845 Atom * target GCC_UNUSED,
846 Atom * type GCC_UNUSED,
847 XtPointer *value GCC_UNUSED,
848 unsigned long *length GCC_UNUSED,
849 int *format GCC_UNUSED)
851 /* we don't save console output, so can't offer it */
857 die_callback(Widget w GCC_UNUSED,
858 XtPointer client_data GCC_UNUSED,
859 XtPointer call_data GCC_UNUSED)
865 save_callback(Widget w GCC_UNUSED,
866 XtPointer client_data GCC_UNUSED,
869 XtCheckpointToken token = (XtCheckpointToken) call_data;
870 /* we have nothing to save */
871 token->save_success = True;
875 icewatch(IceConn iceConn,
876 IcePointer clientData GCC_UNUSED,
878 IcePointer * watchData GCC_UNUSED)
881 ice_fd = IceConnectionNumber(iceConn);
882 TRACE(("got IceConnectionNumber %d\n", ice_fd));
885 TRACE(("reset IceConnectionNumber\n"));
889 #endif /* OPT_SESSION_MGT */
892 * DeleteWindow(): Action proc to implement ICCCM delete_window.
896 DeleteWindow(Widget w,
897 XEvent * event GCC_UNUSED,
898 String * params GCC_UNUSED,
899 Cardinal *num_params GCC_UNUSED)
903 if (TEK4014_SHOWN(term))
906 do_hangup(w, (XtPointer) 0, (XtPointer) 0);
907 } else if (TScreenOf(term)->Vshow)
911 do_hangup(w, (XtPointer) 0, (XtPointer) 0);
916 KeyboardMapping(Widget w GCC_UNUSED,
918 String * params GCC_UNUSED,
919 Cardinal *num_params GCC_UNUSED)
921 switch (event->type) {
923 XRefreshKeyboardMapping(&event->xmapping);
928 static XtActionsRec actionProcs[] =
930 {"DeleteWindow", DeleteWindow},
931 {"KeyboardMapping", KeyboardMapping},
937 main(int argc, char **argv ENVP_ARG)
939 Widget form_top, menu_top;
943 char *my_class = DEFCLASS;
944 Window winToEmbedInto = None;
946 Bool reversed = False;
949 ProgramName = argv[0];
951 save_ruid = getuid();
952 save_rgid = getgid();
954 /* Do these first, since we may not be able to open the display */
955 TRACE_OPTS(xtermOptions, optionDescList, XtNumber(optionDescList));
956 TRACE_ARGV("Before XtOpenApplication", argv);
962 for (n = 1; n < argc; n++) {
963 TRACE(("parsing %s\n", argv[n]));
964 if (abbrev(argv[n], "-version", unique)) {
966 } else if (abbrev(argv[n], "-help", unique)) {
968 } else if (abbrev(argv[n], "-class", 3)) {
969 if ((my_class = argv[++n]) == 0) {
977 if (abbrev(argv[n], "-reverse", 2)
978 || !strcmp("-rv", argv[n])) {
980 } else if (!strcmp("+rv", argv[n])) {
992 /* XXX: for some obscure reason EMX seems to lose the value of
993 * the environ variable, don't understand why, so save it recently
998 setlocale(LC_ALL, NULL);
1003 ttydev = TypeMallocN(char, PTMS_BUFSZ);
1004 ptydev = TypeMallocN(char, PTMS_BUFSZ);
1005 if (!ttydev || !ptydev) {
1007 "%s: unable to allocate memory for ttydev or ptydev\n",
1011 strcpy(ttydev, TTYDEV);
1012 strcpy(ptydev, PTYDEV);
1014 /* Initialization is done here rather than above in order
1015 * to prevent any assumptions about the order of the contents
1016 * of the various terminal structures (which may change from
1017 * implementation to implementation).
1019 d_tio.c_iflag = ICRNL | IXON;
1020 d_tio.c_oflag = OPOST | ONLCR | TAB3;
1021 d_tio.c_cflag = B38400 | CS8 | CREAD | PARENB | HUPCL;
1022 d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
1024 d_tio.c_cc[VINTR] = CONTROL('C'); /* '^C' */
1025 d_tio.c_cc[VERASE] = ANSI_DEL; /* DEL */
1026 d_tio.c_cc[VKILL] = CONTROL('U'); /* '^U' */
1027 d_tio.c_cc[VQUIT] = CQUIT; /* '^\' */
1028 d_tio.c_cc[VEOF] = CEOF; /* '^D' */
1029 d_tio.c_cc[VEOL] = CEOL; /* '^@' */
1031 XtSetErrorHandler(xt_error);
1033 toplevel = XtOpenApplication(&app_con, my_class,
1035 XtNumber(optionDescList),
1036 &argc, argv, fallback_resources,
1037 sessionShellWidgetClass,
1039 IceAddConnectionWatch(icewatch, NULL);
1041 toplevel = XtAppInitialize(&app_con, my_class,
1043 XtNumber(optionDescList),
1044 &argc, argv, fallback_resources,
1046 #endif /* OPT_SESSION_MGT */
1047 XtSetErrorHandler((XtErrorHandler) 0);
1049 XtGetApplicationResources(toplevel, (XtPointer) &resource,
1050 application_resources,
1051 XtNumber(application_resources), NULL, 0);
1055 * ICCCM delete_window.
1057 XtAppAddActions(app_con, actionProcs, XtNumber(actionProcs));
1060 * fill in terminal modes
1062 if (resource.tty_modes) {
1063 int n = parse_tty_modes(resource.tty_modes, ttymodelist);
1065 fprintf(stderr, "%s: bad tty modes \"%s\"\n",
1066 ProgramName, resource.tty_modes);
1068 override_tty_modes = True;
1072 if (resource.zIconBeep > 100 || resource.zIconBeep < -100) {
1073 resource.zIconBeep = 0; /* was 100, but I prefer to defaulting off. */
1075 "a number between -100 and 100 is required for zIconBeep. 0 used by default\n");
1077 #endif /* OPT_ZICONBEEP */
1078 hold_screen = resource.hold_screen ? 1 : 0;
1079 xterm_name = resource.xterm_name;
1080 if (strcmp(xterm_name, "-") == 0)
1081 xterm_name = DFT_TERMTYPE;
1082 if (resource.icon_geometry != NULL) {
1087 for (scr = 0; /* yyuucchh */
1088 XtScreen(toplevel) != ScreenOfDisplay(XtDisplay(toplevel), scr);
1091 args[0].name = XtNiconX;
1092 args[1].name = XtNiconY;
1093 XGeometry(XtDisplay(toplevel), scr, resource.icon_geometry, "",
1094 0, 0, 0, 0, 0, &ix, &iy, &junk, &junk);
1095 args[0].value = (XtArgVal) ix;
1096 args[1].value = (XtArgVal) iy;
1097 XtSetValues(toplevel, args, 2);
1100 XtSetValues(toplevel, ourTopLevelShellArgs,
1101 number_ourTopLevelShellArgs);
1104 /* seems as good a place as any */
1108 /* Parse the rest of the command line */
1109 TRACE_ARGV("After XtOpenApplication", argv);
1110 for (argc--, argv++; argc > 0; argc--, argv++) {
1114 TRACE(("parsing %s\n", argv[0]));
1115 switch (argv[0][1]) {
1116 case 'h': /* -help */
1119 case 'v': /* -version */
1126 /* Must be owner and have read/write permission.
1127 xdm cooperates to give the console the right user. */
1128 if (!stat("/dev/console", &sbuf) &&
1129 (sbuf.st_uid == save_ruid) &&
1130 !access("/dev/console", R_OK | W_OK)) {
1137 if (sscanf(*argv + 2, "%c%c%d", passedPty, passedPty + 1,
1146 case 'c': /* -class param */
1147 if (strcmp(argv[0] + 1, "class") == 0)
1155 command_to_exec = ++argv;
1164 winToEmbedInto = (Window) strtol(argv[0], &endPtr, 10);
1174 SetupMenus(toplevel, &form_top, &menu_top, &menu_high);
1176 term = (XtermWidget) XtVaCreateManagedWidget("vt100", xtermWidgetClass,
1179 XtNmenuBar, menu_top,
1181 XtNfromVert, menu_top,
1182 XtNleft, XawChainLeft,
1183 XtNright, XawChainRight,
1184 XtNtop, XawChainTop,
1185 XtNbottom, XawChainBottom,
1186 XtNmenuHeight, menu_high,
1189 decode_keyboard_type(term, &resource);
1191 screen = TScreenOf(term);
1192 screen->inhibit = 0;
1195 if (term->misc.logInhibit)
1196 screen->inhibit |= I_LOG;
1198 if (term->misc.signalInhibit)
1199 screen->inhibit |= I_SIGNAL;
1201 if (term->misc.tekInhibit)
1202 screen->inhibit |= I_TEK;
1206 * We might start by showing the tek4014 window.
1209 if (screen->inhibit & I_TEK)
1210 TEK4014_ACTIVE(term) = False;
1212 if (TEK4014_ACTIVE(term) && !TekInit())
1213 SysError(ERROR_INIT);
1217 * Start the toolbar at this point, after the first window has been setup.
1220 ShowToolbar(resource.toolBar);
1224 if (resource.sessionMgt) {
1225 TRACE(("Enabling session-management callbacks\n"));
1226 XtAddCallback(toplevel, XtNdieCallback, die_callback, NULL);
1227 XtAddCallback(toplevel, XtNsaveCallback, save_callback, NULL);
1232 * Set title and icon name if not specified
1234 if (command_to_exec) {
1237 if (!resource.title) {
1238 if (command_to_exec) {
1239 resource.title = x_basename(command_to_exec[0]);
1240 } /* else not reached */
1243 if (!resource.icon_name)
1244 resource.icon_name = resource.title;
1245 XtSetArg(args[0], XtNtitle, resource.title);
1246 XtSetArg(args[1], XtNiconName, resource.icon_name);
1248 TRACE(("setting:\n\ttitle \"%s\"\n\ticon \"%s\"\n\tbased on command \"%s\"\n",
1253 XtSetValues(toplevel, args, 2);
1256 if (term->misc.callfilter) {
1257 int u = (term->misc.use_encoding ? 2 : 0);
1258 if (command_to_exec) {
1261 for (n = 0, c = command_to_exec; *c; n++, c++) ;
1262 c = TypeMallocN(char *, n + 3 + u);
1264 SysError(ERROR_LUMALLOC);
1265 memcpy(c + 2 + u, command_to_exec, (n + 1) * sizeof(char *));
1266 c[0] = term->misc.localefilter;
1269 c[2] = term->misc.locale_str;
1272 command_to_exec_with_luit = c;
1274 static char *luit[6];
1275 luit[0] = term->misc.localefilter;
1277 luit[1] = "-encoding";
1278 luit[2] = term->misc.locale_str;
1282 command_to_exec_with_luit = luit;
1289 /* Set up stderr properly. Opening this log file cannot be
1290 done securely by a privileged xterm process (although we try),
1291 so the debug feature is disabled by default. */
1292 char dbglogfile[45];
1295 timestamp_filename(dbglogfile, "xterm.debug.log.");
1296 if (creat_as(save_ruid, save_rgid, False, dbglogfile, 0666) > 0) {
1297 i = open(dbglogfile, O_WRONLY | O_TRUNC);
1303 /* mark this file as close on exec */
1304 (void) fcntl(i, F_SETFD, 1);
1311 /* Child process is out there, let's catch its termination */
1312 (void) signal(SIGCHLD, reapchild);
1314 /* Realize procs have now been executed */
1316 if (am_slave >= 0) { /* Write window id so master end can read and use */
1320 sprintf(buf, "%lx\n", XtWindow(SHELL_OF(CURRENT_EMU())));
1321 IGNORE_RC(write(screen->respond, buf, strlen(buf)));
1324 if (0 > (mode = fcntl(screen->respond, F_GETFL, 0)))
1325 SysError(ERROR_F_GETFL);
1328 if (fcntl(screen->respond, F_SETFL, mode))
1329 SysError(ERROR_F_SETFL);
1333 FD_ZERO(&Select_mask);
1334 FD_SET(screen->respond, &pty_mask);
1335 FD_SET(ConnectionNumber(screen->display), &X_mask);
1336 FD_SET(screen->respond, &Select_mask);
1337 FD_SET(ConnectionNumber(screen->display), &Select_mask);
1338 max_plus1 = ((screen->respond < ConnectionNumber(screen->display))
1339 ? (1 + ConnectionNumber(screen->display))
1340 : (1 + screen->respond));
1344 printf("debugging on\n");
1346 XSetErrorHandler(xerror);
1347 XSetIOErrorHandler(xioerror);
1349 initPtyData(&VTbuffer);
1351 if (term->misc.log_on) {
1356 if (winToEmbedInto != None) {
1357 XtRealizeWidget(toplevel);
1359 * This should probably query the tree or check the attributes of
1360 * winToEmbedInto in order to verify that it exists, but I'm still not
1361 * certain what is the best way to do it -GPS
1363 XReparentWindow(XtDisplay(toplevel),
1365 winToEmbedInto, 0, 0);
1368 TRACE(("checking resource values rv %s fg %s, bg %s\n",
1369 BtoS(term->misc.re_verse0),
1370 NonNull(TScreenOf(term)->Tcolors[TEXT_FG].resource),
1371 NonNull(TScreenOf(term)->Tcolors[TEXT_BG].resource)));
1373 if ((reversed && term->misc.re_verse0)
1374 && ((TScreenOf(term)->Tcolors[TEXT_FG].resource
1375 && !isDefaultForeground(TScreenOf(term)->Tcolors[TEXT_FG].resource))
1376 || (TScreenOf(term)->Tcolors[TEXT_BG].resource
1377 && !isDefaultBackground(TScreenOf(term)->Tcolors[TEXT_BG].resource))
1380 #endif /* OPT_COLOR_RES */
1383 if (resource.maximized)
1384 RequestMaximize(term, True);
1388 if (TEK4014_ACTIVE(term))
1398 * Called from get_pty to iterate over likely pseudo terminals
1399 * we might allocate. Used on those systems that do not have
1400 * a functional interface for allocating a pty.
1401 * Returns 0 if found a pty, 1 if fails.
1404 pty_search(int *pty)
1406 char namebuf[PTMS_BUFSZ];
1408 /* ask the PTY manager */
1409 int fd = open("/dev/ptms$", 0);
1410 if (fd && ptioctl(fd, PTMS_GETPTY, namebuf) == 0) {
1411 strcpy(ttydev, namebuf);
1412 strcpy(ptydev, namebuf);
1413 *x_basename(ttydev) = 't';
1415 if ((*pty = open(ptydev, O_RDWR)) >= 0) {
1417 ptioctl(*pty, XTY_TRACE, 0);
1421 fprintf(stderr, "Unable to open %s, errno=%d\n", ptydev, errno);
1428 * This function opens up a pty master and stuffs its value into pty.
1430 * If it finds one, it returns a value of 0. If it does not find one,
1431 * it returns a value of !0. This routine is designed to be re-entrant,
1432 * so that if a pty master is found and later, we find that the slave
1433 * has problems, we can re-enter this function and get another one.
1438 return pty_search(pty);
1442 * The only difference in /etc/termcap between 4014 and 4015 is that
1443 * the latter has support for switching character sets. We support the
1444 * 4015 protocol, but ignore the character switches. Therefore, we
1445 * choose 4014 over 4015.
1447 * Features of the 4014 over the 4012: larger (19") screen, 12-bit
1448 * graphics addressing (compatible with 4012 10-bit addressing),
1449 * special point plot mode, incremental plot mode (not implemented in
1450 * later Tektronix terminals), and 4 character sizes.
1451 * All of these are supported by xterm.
1455 static char *tekterm[] =
1458 "tek4015", /* 4014 with APL character set support */
1459 "tek4012", /* 4010 with lower case */
1460 "tek4013", /* 4012 with APL character set support */
1461 "tek4010", /* small screen, upper-case only */
1467 /* The VT102 is a VT100 with the Advanced Video Option included standard.
1468 * It also adds Escape sequences for insert/delete character/line.
1469 * The VT220 adds 8-bit character sets, selective erase.
1470 * The VT320 adds a 25th status line, terminal state interrogation.
1471 * The VT420 has up to 48 lines on the screen.
1474 static char *vtterm[] =
1477 "x11term", /* for people who want special term name */
1479 DFT_TERMTYPE, /* for people who want special term name */
1480 "xterm", /* the prefered name, should be fastest */
1490 hungtty(int i GCC_UNUSED)
1496 #if OPT_PTY_HANDSHAKE
1506 first_map_occurred(void)
1508 if (resource.wait_for_map) {
1509 TScreen *screen = TScreenOf(term);
1510 handshake.rows = screen->max_row;
1511 handshake.cols = screen->max_col;
1512 resource.wait_for_map = False;
1515 #endif /* OPT_PTY_HANDSHAKE else !OPT_PTY_HANDSHAKE */
1518 set_owner(char *device, uid_t uid, gid_t gid, mode_t mode)
1522 if (chown(device, uid, gid) < 0) {
1525 && save_ruid == 0) {
1526 fprintf(stderr, "Cannot chown %s to %ld,%ld: %s\n",
1527 device, (long) uid, (long) gid,
1533 #define THE_PARENT 1
1542 signal(sig, killit);
1543 kill(-getpid(), sig);
1547 signal(SIGTERM, SIG_DFL);
1548 kill(-getpid(), SIGTERM);
1552 signal(SIGTERM, SIG_DFL);
1553 kill(-getppid(), SIGTERM);
1561 #define close_fd(fd) close(fd), fd = -1
1564 spawnXTerm(XtermWidget xw)
1566 * Inits pty and tty and forks a login process.
1567 * Does not close fd Xsocket.
1568 * If slave, the pty named in passedPty is already open for use
1571 TScreen *screen = TScreenOf(xw);
1572 int Xsocket = ConnectionNumber(screen->display);
1579 char *TermName = NULL;
1580 char *ptr, *shname, buf[64];
1581 int i, no_dev_tty = False;
1582 char *dev_tty_name = (char *) 0;
1584 int pgrp = getpid();
1585 char numbuf[12], **envnew;
1587 screen->uid = save_ruid;
1588 screen->gid = save_rgid;
1590 if (am_slave >= 0) {
1591 screen->respond = am_slave;
1592 ptydev[strlen(ptydev) - 2] =
1593 ttydev[strlen(ttydev) - 2] = passedPty[0];
1594 ptydev[strlen(ptydev) - 1] =
1595 ttydev[strlen(ttydev) - 1] = passedPty[1];
1597 (void) xtermResetIds(screen);
1602 * Sometimes /dev/tty hangs on open (as in the case of a pty
1603 * that has gone away). Simply make up some reasonable
1607 signal(SIGALRM, hungtty);
1608 alarm(2); /* alarm(1) might return too soon */
1610 ttyfd = open("/dev/tty", O_RDWR);
1612 tty_got_hung = False;
1614 tty_got_hung = True;
1618 signal(SIGALRM, SIG_DFL);
1621 * Check results and ignore current control terminal if
1622 * necessary. ENXIO is what is normally returned if there is
1623 * no controlling terminal, but some systems (e.g. SunOS 4.0)
1624 * seem to return EIO. Solaris 2.3 is said to return EINVAL.
1627 if (tty_got_hung || errno == ENXIO || errno == EIO ||
1628 errno == EINVAL || errno == ENOTTY) {
1632 SysError(ERROR_OPDEVTTY);
1636 /* Get a copy of the current terminal's state,
1637 * if we can. Some systems (e.g., SVR4 and MacII)
1638 * may not have a controlling terminal at this point
1639 * if started directly from xdm or xinit,
1640 * in which case we just use the defaults as above.
1642 if (ioctl(ttyfd, TCGETA, &tio) == -1)
1648 if (get_pty(&screen->respond)) {
1654 /* avoid double MapWindow requests */
1655 XtSetMappedWhenManaged(SHELL_OF(CURRENT_EMU()), False);
1657 wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW",
1660 if (!TEK4014_ACTIVE(xw))
1661 VTInit(xw); /* realize now so know window size for tty driver */
1665 * Inform any running xconsole program
1666 * that we are going to steal the console.
1668 XmuGetHostname(mit_console_name + MIT_CONSOLE_LEN, 255);
1669 mit_console = XInternAtom(screen->display, mit_console_name, False);
1670 /* the user told us to be the console, so we can use CurrentTime */
1671 XtOwnSelection(SHELL_OF(CURRENT_EMU()),
1672 mit_console, CurrentTime,
1673 ConvertConsoleSelection, NULL, NULL);
1676 if (TEK4014_ACTIVE(xw)) {
1685 * This used to exit if no termcap entry was found for the specified
1686 * terminal name. That's a little unfriendly, so instead we'll allow
1687 * the program to proceed (but not to set $TERMCAP) if the termcap
1688 * entry is not found.
1691 if (!get_termcap(TermName = resource.term_name)) {
1695 while (*envnew != NULL) {
1696 if ((last == NULL || strcmp(last, *envnew))
1697 && get_termcap(*envnew)) {
1710 /* tell tty how big window is */
1712 if (TEK4014_ACTIVE(xw)) {
1713 TTYSIZE_ROWS(ts) = 38;
1714 TTYSIZE_COLS(ts) = 81;
1715 ts.ws_xpixel = TFullWidth(TekScreenOf(tekWidget));
1716 ts.ws_ypixel = TFullHeight(TekScreenOf(tekWidget));
1720 TTYSIZE_ROWS(ts) = MaxRows(screen);
1721 TTYSIZE_COLS(ts) = MaxCols(screen);
1722 ts.ws_xpixel = FullWidth(screen);
1723 ts.ws_ypixel = FullHeight(screen);
1730 /* start a child process
1731 * use an event sema for sync
1733 sprintf(sema, "\\SEM32\\xterm%s", &ptydev[8]);
1734 if (DosCreateEventSem(sema, &sev, DC_SEM_SHARED, False))
1735 SysError(ERROR_FORK);
1737 switch ((screen->pid = fork())) {
1738 case -1: /* error */
1739 SysError(ERROR_FORK);
1740 default: /* parent */
1741 whoami = THE_PARENT;
1742 DosWaitEventSem(sev, 1000L);
1743 DosCloseEventSem(sev);
1749 /* we don't need the socket, or the pty master anymore */
1750 close(ConnectionNumber(screen->display));
1751 close(screen->respond);
1753 /* Now is the time to set up our process group and
1754 * open up the pty slave.
1756 if ((ttyfd = open(ttydev, O_RDWR)) < 0) {
1758 fprintf(stderr, "Cannot open slave side of PTY\n");
1762 /* use the same tty name that everyone else will use
1766 if ((ptr = ttyname(ttyfd)) != 0) {
1767 ttydev = x_strdup(ptr);
1772 /* for safety: enable DUPs */
1773 ptioctl(ttyfd, XTY_ENADUP, 0);
1775 /* change ownership of tty to real group and user id */
1776 set_owner(ttydev, screen->uid, screen->gid,
1777 (resource.messages ? 0622U : 0600U));
1779 /* for the xf86sup-pty, we set the pty to bypass: OS/2 does
1780 * not have a line discipline structure
1783 TERMIO_STRUCT t, t1;
1784 if (ptioctl(ttyfd, TCGETA, (char *) &t) < 0)
1788 t.c_oflag = OPOST | ONLCR;
1789 t.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
1791 /* ignore error code, user will see it :-) */
1792 ptioctl(ttyfd, TCSETA, (char *) &t);
1794 /* set the console mode */
1797 if (ioctl(ttyfd, TIOCCONS, (char *) &on) == -1)
1798 fprintf(stderr, "%s: cannot open console: %s\n",
1799 ProgramName, strerror(errno));
1803 signal(SIGCHLD, SIG_DFL);
1804 signal(SIGHUP, SIG_IGN);
1806 /* restore various signals to their defaults */
1807 signal(SIGINT, SIG_DFL);
1808 signal(SIGQUIT, SIG_DFL);
1809 signal(SIGTERM, SIG_DFL);
1811 xtermCopyEnv(gblenvp);
1813 xtermSetenv("TERM", TermName);
1815 *get_tcap_buffer(xw) = 0;
1818 ((unsigned long) XtWindow(SHELL_OF(CURRENT_EMU()))));
1819 xtermSetenv("WINDOWID", buf);
1821 /* put the display into the environment of the shell */
1822 xtermSetenv("DISPLAY", XDisplayString(screen->display));
1824 xtermSetenv("XTERM_VERSION", xtermVersion());
1825 xtermSetenv("XTERM_LOCALE", xtermEnvLocale());
1827 signal(SIGTERM, SIG_DFL);
1829 /* this is the time to go and set up stdin, out, and err
1832 for (i = 0; i <= 2; i++)
1835 IGNORE_RC(dup(ttyfd));
1838 /* and close the tty */
1843 (void) xtermResetIds(screen);
1845 if (handshake.rows > 0 && handshake.cols > 0) {
1846 TRACE(("handshake ttysize: %dx%d\n",
1847 handshake.rows, handshake.cols));
1848 set_max_row(screen, handshake.rows);
1849 set_max_col(screen, handshake.cols);
1850 TTYSIZE_ROWS(ts) = MaxRows(screen);
1851 TTYSIZE_COLS(ts) = MaxCols(screen);
1852 ts.ws_xpixel = FullWidth(screen);
1853 ts.ws_ypixel = FullHeight(screen);
1856 sprintf(numbuf, "%d", MaxCols(screen));
1857 xtermSetenv("COLUMNS", numbuf);
1858 sprintf(numbuf, "%d", MaxRows(screen));
1859 xtermSetenv("LINES", numbuf);
1863 /* need to reset after all the ioctl bashing we did above */
1864 ptioctl(0, TIOCSWINSZ, (char *) &ts);
1866 signal(SIGHUP, SIG_DFL);
1868 /* okay everything seems right, so tell the parent, we are going */
1872 sprintf(sema, "\\SEM32\\xterm%s", &ttydev[8]);
1873 DosOpenEventSem(sema, &sev);
1874 DosPostEventSem(sev);
1875 DosCloseEventSem(sev);
1880 * Use two copies of command_to_exec, in case luit is not actually
1881 * there, or refuses to run. In that case we will fall-through to
1882 * to command that the user gave anyway.
1884 if (command_to_exec_with_luit) {
1885 xtermSetenv("XTERM_SHELL",
1886 xtermFindShell(*command_to_exec_with_luit, False));
1887 TRACE(("spawning command \"%s\"\n", *command_to_exec_with_luit));
1888 execvp(*command_to_exec_with_luit, command_to_exec_with_luit);
1889 /* print error message on screen */
1890 fprintf(stderr, "%s: Can't execvp %s: %s\n",
1891 ProgramName, *command_to_exec_with_luit, strerror(errno));
1892 fprintf(stderr, "%s: cannot support your locale.\n",
1896 if (command_to_exec) {
1897 xtermSetenv("XTERM_SHELL",
1898 xtermFindShell(*command_to_exec, False));
1899 TRACE(("spawning command \"%s\"\n", *command_to_exec));
1900 execvpe(*command_to_exec, command_to_exec, gblenvp);
1902 /* print error message on screen */
1903 fprintf(stderr, "%s: Can't execvp %s\n",
1904 ProgramName, *command_to_exec);
1907 /* use a layered mechanism to find a shell */
1908 ptr = x_getenv("X11SHELL");
1910 ptr = x_getenv("SHELL");
1912 ptr = x_getenv("OS2_SHELL");
1914 ptr = "SORRY_NO_SHELL_FOUND";
1915 xtermSetenv("XTERM_SHELL", ptr);
1917 shname = x_basename(ptr);
1918 if (command_to_exec) {
1919 char *exargv[10]; /*XXX */
1923 exargv[2] = command_to_exec[0];
1924 exargv[3] = command_to_exec[1];
1925 exargv[4] = command_to_exec[2];
1926 exargv[5] = command_to_exec[3];
1927 exargv[6] = command_to_exec[4];
1928 exargv[7] = command_to_exec[5];
1929 exargv[8] = command_to_exec[6];
1931 execvpe(exargv[0], exargv, gblenvp);
1933 /* print error message on screen */
1934 fprintf(stderr, "%s: Can't execvp %s\n",
1935 ProgramName, *command_to_exec);
1937 execlpe(ptr, shname, 0, gblenvp);
1940 fprintf(stderr, "%s: Could not exec %s!\n",
1945 /* preventively shoot the parent */
1946 kill(-getppid(), SIGTERM);
1952 signal(SIGHUP, SIG_IGN);
1954 * Unfortunately, System V seems to have trouble divorcing the child process
1955 * from the process group of xterm. This is a problem because hitting the
1956 * INTR or QUIT characters on the keyboard will cause xterm to go away if we
1957 * don't ignore the signals. This is annoying.
1960 /* signal (SIGINT, SIG_IGN);*/
1961 signal(SIGINT, killit);
1962 signal(SIGTERM, killit);
1964 /* hung shell problem */
1965 signal(SIGQUIT, SIG_IGN);
1966 /* signal (SIGTERM, SIG_IGN);*/
1968 } /* end spawnXTerm */
1973 XtermWidget xw = term;
1974 TScreen *screen = TScreenOf(xw);
1975 int pty = TScreenOf(xw)->respond;
1976 close(pty); /* close explicitly to avoid race with slave side */
1978 if (screen->logging)
1982 /* restore ownership of tty and pty */
1983 set_owner(ttydev, 0, 0, 0666U);
1984 set_owner(ptydev, 0, 0, 0666U);
1988 * Close after releasing ownership to avoid race condition: other programs
1989 * grabbing it, and *then* having us release ownership....
1991 close(screen->respond); /* close explicitly to avoid race with slave side */
1993 if (screen->logging)
1999 TRACE(("Freeing memory leaks\n"));
2001 Display *dpy = TScreenOf(xw)->display;
2004 XtDestroyWidget(toplevel);
2005 TRACE(("destroyed top-level widget\n"));
2007 sortedOpts(0, 0, 0);
2011 noleaks_CharacterClass();
2013 /* XrmSetDatabase(dpy, 0); increases leaks ;-) */
2014 XtCloseDisplay(dpy);
2015 XtDestroyApplicationContext(app_con);
2017 IceRemoveConnectionWatch(icewatch, NULL);
2019 TRACE(("closed display\n"));
2031 resize_termcap(XtermWidget xw)
2036 * Does a non-blocking wait for a child process. If the system
2037 * doesn't support non-blocking wait, do nothing.
2038 * Returns the pid of the child, or 0 or -1 if none or error.
2041 nonblocking_wait(void)
2045 pid = waitpid(-1, NULL, WNOHANG);
2051 reapchild(int n GCC_UNUSED)
2053 int olderrno = errno;
2058 /* cannot re-enable signal before waiting for child
2059 * because then SVR4 loops. Sigh. HP-UX 9.01 too.
2061 (void) signal(SIGCHLD, reapchild);
2064 if (pid == TScreenOf(term)->pid) {
2067 fputs("Exiting\n", stderr);
2070 need_cleanup = True;
2072 } while ((pid = nonblocking_wait()) > 0);
2079 * parse_tty_modes accepts lines of the following form:
2083 * where setting consists of the words in the modelist followed by a character
2087 parse_tty_modes(char *s, struct _xttymodes *modelist)
2089 struct _xttymodes *mp;
2093 TRACE(("parse_tty_modes\n"));
2097 while (*s && isascii(CharOf(*s)) && isspace(CharOf(*s)))
2102 for (len = 0; isalnum(CharOf(s[len])); ++len) ;
2103 for (mp = modelist; mp->name; mp++) {
2105 && strncmp(s, mp->name, mp->len) == 0)
2112 while (*s && isascii(CharOf(*s)) && isspace(CharOf(*s)))
2117 if ((c = decode_keyvalue(&s, False)) != -1) {
2121 TRACE(("...parsed #%d: %s=%#x\n", count, mp->name, c));
2127 GetBytesAvailable(int fd)
2130 ioctl(fd, FIONREAD, (char *) &arg);
2134 /* Utility function to try to hide system differences from
2135 everybody who used to call killpg() */
2138 kill_process_group(int pid, int sig)
2140 return kill(-pid, sig);
2144 ptioctl(int fd, int func, void *data)
2148 struct pt_termios pt;
2154 rc = DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCGETA,
2156 (ULONG *) & pt, sizeof(struct pt_termios), &len);
2159 t = (TERMIO_STRUCT *) data;
2160 t->c_iflag = pt.c_iflag;
2161 t->c_oflag = pt.c_oflag;
2162 t->c_cflag = pt.c_cflag;
2163 t->c_lflag = pt.c_lflag;
2164 for (i = 0; i < NCC; i++)
2165 t->c_cc[i] = pt.c_cc[i];
2170 t = (TERMIO_STRUCT *) data;
2171 pt.c_iflag = t->c_iflag;
2172 pt.c_oflag = t->c_oflag;
2173 pt.c_cflag = t->c_cflag;
2174 pt.c_lflag = t->c_lflag;
2176 for (i = 0; i < NCC; i++)
2177 pt.c_cc[i] = t->c_cc[i];
2180 else if (func == TCSETAW)
2184 rc = DosDevIOCtl(fd, XFREE86_PTY, i,
2185 (ULONG *) & pt, sizeof(struct pt_termios), &len,
2187 return (rc) ? -1 : 0;
2189 return DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCCONS,
2190 (ULONG *) data, sizeof(ULONG), &len,
2193 return DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCSWINSZ,
2194 (ULONG *) data, sizeof(TTYSIZE_STRUCT), &len,
2197 return DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCGWINSZ,
2199 (ULONG *) data, sizeof(TTYSIZE_STRUCT), &len);
2202 return DosDevIOCtl(fd, XFREE86_PTY, XTY_ENADUP,
2203 (ULONG *) & i, sizeof(ULONG), &len,
2207 return DosDevIOCtl(fd, XFREE86_PTY, XTY_TRACE,
2208 (ULONG *) & i, sizeof(ULONG), &len,
2212 return DosDevIOCtl(fd, XFREE86_PTY, PTMS_GETPTY,
2213 (ULONG *) & i, sizeof(ULONG), &len,
2214 (UCHAR *) data, 14, &len);