#define INCL_DOSFILEMGR
#define INCL_DOSDEVIOCTL
#define INCL_DOSSEMAPHORES
#ifdef __INNOTEK_LIBC__
#define INCL_DOSDEVICES
#endif
#define I_NEED_OS2_H
#include <os2.h>
#define XTERM_MAIN
#define RES_OFFSET(field) XtOffsetOf(XTERM_RESOURCE, field)
#include <xterm.h>
#include <X11/cursorfont.h>
#ifdef I18N
#include <X11/Xlocale.h>
#endif
#if OPT_TOOLBAR
#if defined(HAVE_LIB_XAW)
#include <X11/Xaw/Form.h>
#elif defined(HAVE_LIB_XAW3D)
#include <X11/Xaw3d/Form.h>
#elif defined(HAVE_LIB_NEXTAW)
#include <X11/neXtaw/Form.h>
#elif defined(HAVE_LIB_XAWPLUS)
#include <X11/XawPlus/Form.h>
#endif
#endif
#include <pwd.h>
#include <ctype.h>
#include <data.h>
#include <error.h>
#include <menu.h>
#include <main.h>
#include <xstrings.h>
#include <xtermcap.h>
#include <xterm_io.h>
#if OPT_WIDE_CHARS
#include <charclass.h>
#endif
int
setpgrp(pid_t pid, gid_t pgid)
{
return 0;
}
int
chown(const char *fn, pid_t pid, gid_t gid)
{
return 0;
}
char *
ttyname(int fd)
{
return "/dev/tty";
}
#include <sys/stat.h>
#include <sys/param.h>
#include <stdio.h>
#include <signal.h>
static SIGNAL_T reapchild(int n);
static int spawnXTerm(XtermWidget );
static void resize_termcap(XtermWidget xw, char *newtc);
static void set_owner(char *device, uid_t uid, gid_t gid, mode_t mode);
static Bool added_utmp_entry = False;
static uid_t save_ruid;
static gid_t save_rgid;
static char **command_to_exec = NULL;
#if OPT_LUIT_PROG
static char **command_to_exec_with_luit = NULL;
#endif
static struct termio d_tio;
#ifndef CEOF
#define CEOF CONTROL('D')
#endif
#ifndef CEOL
#define CEOL 0
#endif
#ifndef CFLUSH
#define CFLUSH CONTROL('O')
#endif
#ifndef CLNEXT
#define CLNEXT CONTROL('V')
#endif
#ifndef CNUL
#define CNUL 0
#endif
#ifndef CQUIT
#define CQUIT CONTROL('\\')
#endif
#ifndef CRPRNT
#define CRPRNT CONTROL('R')
#endif
#ifndef CSTART
#define CSTART CONTROL('Q')
#endif
#ifndef CSTOP
#define CSTOP CONTROL('S')
#endif
#ifndef CSUSP
#define CSUSP CONTROL('Z')
#endif
#ifndef CSWTCH
#define CSWTCH 0
#endif
#ifndef CWERASE
#define CWERASE CONTROL('W')
#endif
#define TERMIO_STRUCT struct termio
#define TTYMODE(name) { name, sizeof(name)-1, 0, 0 }
static Boolean override_tty_modes = False;
static struct _xttymodes {
char *name;
size_t len;
int set;
int value;
} ttymodelist[] = {
TTYMODE("intr"),
#define XTTYMODE_intr 0
TTYMODE("quit"),
#define XTTYMODE_quit 1
TTYMODE("erase"),
#define XTTYMODE_erase 2
TTYMODE("kill"),
#define XTTYMODE_kill 3
TTYMODE("eof"),
#define XTTYMODE_eof 4
TTYMODE("eol"),
#define XTTYMODE_eol 5
TTYMODE("swtch"),
#define XTTYMODE_swtch 6
TTYMODE("start"),
#define XTTYMODE_start 7
TTYMODE("stop"),
#define XTTYMODE_stop 8
TTYMODE("brk"),
#define XTTYMODE_brk 9
TTYMODE("susp"),
#define XTTYMODE_susp 10
TTYMODE("dsusp"),
#define XTTYMODE_dsusp 11
TTYMODE("rprnt"),
#define XTTYMODE_rprnt 12
TTYMODE("flush"),
#define XTTYMODE_flush 13
TTYMODE("weras"),
#define XTTYMODE_weras 14
TTYMODE("lnext"),
#define XTTYMODE_lnext 15
{ NULL, 0, 0, '\0' },
};
#define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value
static int parse_tty_modes(char *s, struct _xttymodes *modelist);
static char passedPty[2];
static int Console;
#include <X11/Xmu/SysUtil.h>
#define MIT_CONSOLE_LEN 12
#define MIT_CONSOLE "MIT_CONSOLE_"
static char mit_console_name[255 + MIT_CONSOLE_LEN + 1] = MIT_CONSOLE;
static Atom mit_console;
static int tslot;
static jmp_buf env;
static XtResource application_resources[] =
{
Sres("name", "Name", xterm_name, DFT_TERMTYPE),
Sres("iconGeometry", "IconGeometry", icon_geometry, NULL),
Sres(XtNtitle, XtCTitle, title, NULL),
Sres(XtNiconName, XtCIconName, icon_name, NULL),
Sres("termName", "TermName", term_name, NULL),
Sres("ttyModes", "TtyModes", tty_modes, NULL),
Bres("hold", "Hold", hold_screen, False),
Bres("utmpInhibit", "UtmpInhibit", utmpInhibit, False),
Bres("utmpDisplayId", "UtmpDisplayId", utmpDisplayId, True),
Bres("messages", "Messages", messages, True),
Ires("minBufSize", "MinBufSize", minBufSize, 4096),
Ires("maxBufSize", "MaxBufSize", maxBufSize, 32768),
Sres("menuLocale", "MenuLocale", menuLocale, ""),
Sres("keyboardType", "KeyboardType", keyboardType, "unknown"),
#if OPT_SUNPC_KBD
Bres("sunKeyboard", "SunKeyboard", sunKeyboard, False),
#endif
#if OPT_HP_FUNC_KEYS
Bres("hpFunctionKeys", "HpFunctionKeys", hpFunctionKeys, False),
#endif
#if OPT_SCO_FUNC_KEYS
Bres("scoFunctionKeys", "ScoFunctionKeys", scoFunctionKeys, False),
#endif
#if OPT_SUN_FUNC_KEYS
Bres("sunFunctionKeys", "SunFunctionKeys", sunFunctionKeys, False),
#endif
#if OPT_TCAP_FKEYS
Bres("tcapFunctionKeys", "TcapFunctionKeys", termcapKeys, False),
#endif
#if OPT_INITIAL_ERASE
Bres("ptyInitialErase", "PtyInitialErase", ptyInitialErase, DEF_INITIAL_ERASE),
Bres("backarrowKeyIsErase", "BackarrowKeyIsErase", backarrow_is_erase, DEF_BACKARO_ERASE),
#endif
Bres("useInsertMode", "UseInsertMode", useInsertMode, False),
#if OPT_ZICONBEEP
Ires("zIconBeep", "ZIconBeep", zIconBeep, 0),
#endif
#if OPT_PTY_HANDSHAKE
Bres("waitForMap", "WaitForMap", wait_for_map, False),
Bres("ptyHandshake", "PtyHandshake", ptyHandshake, True),
Bres("ptySttySize", "PtySttySize", ptySttySize, DEF_PTY_STTY_SIZE),
#endif
#if OPT_SAME_NAME
Bres("sameName", "SameName", sameName, True),
#endif
#if OPT_SESSION_MGT
Bres("sessionMgt", "SessionMgt", sessionMgt, True),
#endif
#if OPT_TOOLBAR
Bres(XtNtoolBar, XtCToolBar, toolBar, True),
#endif
#if OPT_MAXIMIZE
Bres(XtNmaximized, XtCMaximized, maximized, False),
#endif
};
static char *fallback_resources[] =
{
"*SimpleMenu*menuLabel.vertSpace: 100",
"*SimpleMenu*HorizontalMargins: 16",
"*SimpleMenu*Sme.height: 16",
"*SimpleMenu*Cursor: left_ptr",
"*mainMenu.Label: Main Options (no app-defaults)",
"*vtMenu.Label: VT Options (no app-defaults)",
"*fontMenu.Label: VT Fonts (no app-defaults)",
#if OPT_TEK4014
"*tekMenu.Label: Tek Options (no app-defaults)",
#endif
NULL
};
static XrmOptionDescRec optionDescList[] = {
{"-geometry", "*vt100.geometry",XrmoptionSepArg, (caddr_t) NULL},
{"-132", "*c132", XrmoptionNoArg, (caddr_t) "on"},
{"+132", "*c132", XrmoptionNoArg, (caddr_t) "off"},
{"-ah", "*alwaysHighlight", XrmoptionNoArg, (caddr_t) "on"},
{"+ah", "*alwaysHighlight", XrmoptionNoArg, (caddr_t) "off"},
{"-aw", "*autoWrap", XrmoptionNoArg, (caddr_t) "on"},
{"+aw", "*autoWrap", XrmoptionNoArg, (caddr_t) "off"},
#ifndef NO_ACTIVE_ICON
{"-ai", "*activeIcon", XrmoptionNoArg, (caddr_t) "off"},
{"+ai", "*activeIcon", XrmoptionNoArg, (caddr_t) "on"},
#endif
{"-b", "*internalBorder",XrmoptionSepArg, (caddr_t) NULL},
{"-bc", "*cursorBlink", XrmoptionNoArg, (caddr_t) "on"},
{"+bc", "*cursorBlink", XrmoptionNoArg, (caddr_t) "off"},
{"-bcf", "*cursorOffTime",XrmoptionSepArg, (caddr_t) NULL},
{"-bcn", "*cursorOnTime",XrmoptionSepArg, (caddr_t) NULL},
{"-bdc", "*colorBDMode", XrmoptionNoArg, (caddr_t) "off"},
{"+bdc", "*colorBDMode", XrmoptionNoArg, (caddr_t) "on"},
{"-cb", "*cutToBeginningOfLine", XrmoptionNoArg, (caddr_t) "off"},
{"+cb", "*cutToBeginningOfLine", XrmoptionNoArg, (caddr_t) "on"},
{"-cc", "*charClass", XrmoptionSepArg, (caddr_t) NULL},
{"-cm", "*colorMode", XrmoptionNoArg, (caddr_t) "off"},
{"+cm", "*colorMode", XrmoptionNoArg, (caddr_t) "on"},
{"-cn", "*cutNewline", XrmoptionNoArg, (caddr_t) "off"},
{"+cn", "*cutNewline", XrmoptionNoArg, (caddr_t) "on"},
{"-cr", "*cursorColor", XrmoptionSepArg, (caddr_t) NULL},
{"-cu", "*curses", XrmoptionNoArg, (caddr_t) "on"},
{"+cu", "*curses", XrmoptionNoArg, (caddr_t) "off"},
{"-dc", "*dynamicColors",XrmoptionNoArg, (caddr_t) "off"},
{"+dc", "*dynamicColors",XrmoptionNoArg, (caddr_t) "on"},
{"-fb", "*boldFont", XrmoptionSepArg, (caddr_t) NULL},
{"-fbb", "*freeBoldBox", XrmoptionNoArg, (caddr_t)"off"},
{"+fbb", "*freeBoldBox", XrmoptionNoArg, (caddr_t)"on"},
{"-fbx", "*forceBoxChars", XrmoptionNoArg, (caddr_t)"off"},
{"+fbx", "*forceBoxChars", XrmoptionNoArg, (caddr_t)"on"},
#ifndef NO_ACTIVE_ICON
{"-fi", "*iconFont", XrmoptionSepArg, (caddr_t) NULL},
#endif
#if OPT_RENDERFONT
{"-fa", "*faceName", XrmoptionSepArg, (caddr_t) NULL},
{"-fd", "*faceNameDoublesize", XrmoptionSepArg, (caddr_t) NULL},
{"-fs", "*faceSize", XrmoptionSepArg, (caddr_t) NULL},
#endif
#if OPT_WIDE_CHARS
{"-fw", "*wideFont", XrmoptionSepArg, (caddr_t) NULL},
{"-fwb", "*wideBoldFont", XrmoptionSepArg, (caddr_t) NULL},
#endif
#if OPT_INPUT_METHOD
{"-fx", "*ximFont", XrmoptionSepArg, (caddr_t) NULL},
#endif
#if OPT_HIGHLIGHT_COLOR
{"-hc", "*highlightColor", XrmoptionSepArg, (caddr_t) NULL},
{"-hm", "*highlightColorMode", XrmoptionNoArg, (caddr_t) "on"},
{"+hm", "*highlightColorMode", XrmoptionNoArg, (caddr_t) "off"},
{"-selfg", "*highlightTextColor", XrmoptionSepArg, (caddr_t) NULL},
{"-selbg", "*highlightColor", XrmoptionSepArg, (caddr_t) NULL},
#endif
#if OPT_HP_FUNC_KEYS
{"-hf", "*hpFunctionKeys",XrmoptionNoArg, (caddr_t) "on"},
{"+hf", "*hpFunctionKeys",XrmoptionNoArg, (caddr_t) "off"},
#endif
{"-hold", "*hold", XrmoptionNoArg, (caddr_t) "on"},
{"+hold", "*hold", XrmoptionNoArg, (caddr_t) "off"},
#if OPT_INITIAL_ERASE
{"-ie", "*ptyInitialErase", XrmoptionNoArg, (caddr_t) "on"},
{"+ie", "*ptyInitialErase", XrmoptionNoArg, (caddr_t) "off"},
#endif
{"-j", "*jumpScroll", XrmoptionNoArg, (caddr_t) "on"},
{"+j", "*jumpScroll", XrmoptionNoArg, (caddr_t) "off"},
#if OPT_C1_PRINT
{"-k8", "*allowC1Printable", XrmoptionNoArg, (caddr_t) "on"},
{"+k8", "*allowC1Printable", XrmoptionNoArg, (caddr_t) "off"},
#endif
{"-kt", "*keyboardType", XrmoptionSepArg, (caddr_t) NULL},
{"+kt", "*keyboardType", XrmoptionSepArg, (caddr_t) NULL},
{"-l", "*logging", XrmoptionNoArg, (caddr_t) "on"},
{"+l", "*logging", XrmoptionNoArg, (caddr_t) "off"},
{"-lf", "*logFile", XrmoptionSepArg, (caddr_t) NULL},
{"-ls", "*loginShell", XrmoptionNoArg, (caddr_t) "on"},
{"+ls", "*loginShell", XrmoptionNoArg, (caddr_t) "off"},
{"-mb", "*marginBell", XrmoptionNoArg, (caddr_t) "on"},
{"+mb", "*marginBell", XrmoptionNoArg, (caddr_t) "off"},
{"-mc", "*multiClickTime", XrmoptionSepArg, (caddr_t) NULL},
{"-mesg", "*messages", XrmoptionNoArg, (caddr_t) "off"},
{"+mesg", "*messages", XrmoptionNoArg, (caddr_t) "on"},
{"-ms", "*pointerColor",XrmoptionSepArg, (caddr_t) NULL},
{"-nb", "*nMarginBell", XrmoptionSepArg, (caddr_t) NULL},
{"-nul", "*underLine", XrmoptionNoArg, (caddr_t) "off"},
{"+nul", "*underLine", XrmoptionNoArg, (caddr_t) "on"},
{"-pc", "*boldColors", XrmoptionNoArg, (caddr_t) "on"},
{"+pc", "*boldColors", XrmoptionNoArg, (caddr_t) "off"},
{"-rw", "*reverseWrap", XrmoptionNoArg, (caddr_t) "on"},
{"+rw", "*reverseWrap", XrmoptionNoArg, (caddr_t) "off"},
{"-s", "*multiScroll", XrmoptionNoArg, (caddr_t) "on"},
{"+s", "*multiScroll", XrmoptionNoArg, (caddr_t) "off"},
{"-sb", "*scrollBar", XrmoptionNoArg, (caddr_t) "on"},
{"+sb", "*scrollBar", XrmoptionNoArg, (caddr_t) "off"},
#ifdef SCROLLBAR_RIGHT
{"-leftbar", "*rightScrollBar", XrmoptionNoArg, (caddr_t) "off"},
{"-rightbar", "*rightScrollBar", XrmoptionNoArg, (caddr_t) "on"},
#endif
{"-rvc", "*colorRVMode", XrmoptionNoArg, (caddr_t) "off"},
{"+rvc", "*colorRVMode", XrmoptionNoArg, (caddr_t) "on"},
{"-sf", "*sunFunctionKeys", XrmoptionNoArg, (caddr_t) "on"},
{"+sf", "*sunFunctionKeys", XrmoptionNoArg, (caddr_t) "off"},
{"-si", "*scrollTtyOutput", XrmoptionNoArg, (caddr_t) "off"},
{"+si", "*scrollTtyOutput", XrmoptionNoArg, (caddr_t) "on"},
{"-sk", "*scrollKey", XrmoptionNoArg, (caddr_t) "on"},
{"+sk", "*scrollKey", XrmoptionNoArg, (caddr_t) "off"},
{"-sl", "*saveLines", XrmoptionSepArg, (caddr_t) NULL},
#if OPT_SUNPC_KBD
{"-sp", "*sunKeyboard", XrmoptionNoArg, (caddr_t) "on"},
{"+sp", "*sunKeyboard", XrmoptionNoArg, (caddr_t) "off"},
#endif
#if OPT_TEK4014
{"-t", "*tekStartup", XrmoptionNoArg, (caddr_t) "on"},
{"+t", "*tekStartup", XrmoptionNoArg, (caddr_t) "off"},
#endif
{"-ti", "*decTerminalID",XrmoptionSepArg, (caddr_t) NULL},
{"-tm", "*ttyModes", XrmoptionSepArg, (caddr_t) NULL},
{"-tn", "*termName", XrmoptionSepArg, (caddr_t) NULL},
#if OPT_WIDE_CHARS
{"-u8", "*utf8", XrmoptionNoArg, (caddr_t) "2"},
{"+u8", "*utf8", XrmoptionNoArg, (caddr_t) "0"},
#endif
#if OPT_LUIT_PROG
{"-lc", "*locale", XrmoptionNoArg, (caddr_t) "on"},
{"+lc", "*locale", XrmoptionNoArg, (caddr_t) "off"},
{"-lcc", "*localeFilter",XrmoptionSepArg, (caddr_t) NULL},
{"-en", "*locale", XrmoptionSepArg, (caddr_t) NULL},
#endif
{"-uc", "*cursorUnderLine", XrmoptionNoArg, (caddr_t) "on"},
{"+uc", "*cursorUnderLine", XrmoptionNoArg, (caddr_t) "off"},
{"-ulc", "*colorULMode", XrmoptionNoArg, (caddr_t) "off"},
{"+ulc", "*colorULMode", XrmoptionNoArg, (caddr_t) "on"},
{"-ulit", "*italicULMode", XrmoptionNoArg, (caddr_t) "off"},
{"+ulit", "*italicULMode", XrmoptionNoArg, (caddr_t) "on"},
{"-ut", "*utmpInhibit", XrmoptionNoArg, (caddr_t) "on"},
{"+ut", "*utmpInhibit", XrmoptionNoArg, (caddr_t) "off"},
{"-im", "*useInsertMode", XrmoptionNoArg, (caddr_t) "on"},
{"+im", "*useInsertMode", XrmoptionNoArg, (caddr_t) "off"},
{"-vb", "*visualBell", XrmoptionNoArg, (caddr_t) "on"},
{"+vb", "*visualBell", XrmoptionNoArg, (caddr_t) "off"},
{"-pob", "*popOnBell", XrmoptionNoArg, (caddr_t) "on"},
{"+pob", "*popOnBell", XrmoptionNoArg, (caddr_t) "off"},
#if OPT_WIDE_CHARS
{"-wc", "*wideChars", XrmoptionNoArg, (caddr_t) "on"},
{"+wc", "*wideChars", XrmoptionNoArg, (caddr_t) "off"},
{"-mk_width", "*mkWidth", XrmoptionNoArg, (caddr_t) "on"},
{"+mk_width", "*mkWidth", XrmoptionNoArg, (caddr_t) "off"},
{"-cjk_width", "*cjkWidth", XrmoptionNoArg, (caddr_t) "on"},
{"+cjk_width", "*cjkWidth", XrmoptionNoArg, (caddr_t) "off"},
#endif
{"-wf", "*waitForMap", XrmoptionNoArg, (caddr_t) "on"},
{"+wf", "*waitForMap", XrmoptionNoArg, (caddr_t) "off"},
#if OPT_ZICONBEEP
{"-ziconbeep", "*zIconBeep", XrmoptionSepArg, (caddr_t) NULL},
#endif
#if OPT_SAME_NAME
{"-samename", "*sameName", XrmoptionNoArg, (caddr_t) "on"},
{"+samename", "*sameName", XrmoptionNoArg, (caddr_t) "off"},
#endif
#if OPT_SESSION_MGT
{"-sm", "*sessionMgt", XrmoptionNoArg, (caddr_t) "on"},
{"+sm", "*sessionMgt", XrmoptionNoArg, (caddr_t) "off"},
#endif
#if OPT_TOOLBAR
{"-tb", "*"XtNtoolBar, XrmoptionNoArg, (caddr_t) "on"},
{"+tb", "*"XtNtoolBar, XrmoptionNoArg, (caddr_t) "off"},
#endif
#if OPT_MAXIMIZE
{"-maximized", "*maximized", XrmoptionNoArg, (caddr_t) "on"},
{"+maximized", "*maximized", XrmoptionNoArg, (caddr_t) "off"},
#endif
{"-help", NULL, XrmoptionSkipNArgs, (caddr_t) NULL},
{"-version", NULL, XrmoptionSkipNArgs, (caddr_t) NULL},
{"-class", NULL, XrmoptionSkipArg, (caddr_t) NULL},
{"-e", NULL, XrmoptionSkipLine, (caddr_t) NULL},
{"-into", NULL, XrmoptionSkipArg, (caddr_t) NULL},
{"%", "*tekGeometry", XrmoptionStickyArg, (caddr_t) NULL},
{"#", ".iconGeometry",XrmoptionStickyArg, (caddr_t) NULL},
{"-T", ".title", XrmoptionSepArg, (caddr_t) NULL},
{"-n", "*iconName", XrmoptionSepArg, (caddr_t) NULL},
{"-r", "*reverseVideo",XrmoptionNoArg, (caddr_t) "on"},
{"+r", "*reverseVideo",XrmoptionNoArg, (caddr_t) "off"},
{"-rv", "*reverseVideo",XrmoptionNoArg, (caddr_t) "on"},
{"+rv", "*reverseVideo",XrmoptionNoArg, (caddr_t) "off"},
{"-w", ".borderWidth", XrmoptionSepArg, (caddr_t) NULL},
};
static OptionHelp xtermOptions[] = {
{ "-version", "print the version number" },
{ "-help", "print out this message" },
{ "-display displayname", "X server to contact" },
{ "-geometry geom", "size (in characters) and position" },
{ "-/+rv", "turn on/off reverse video" },
{ "-bg color", "background color" },
{ "-fg color", "foreground color" },
{ "-bd color", "border color" },
{ "-bw number", "border width in pixels" },
{ "-fn fontname", "normal text font" },
{ "-fb fontname", "bold text font" },
{ "-/+fbb", "turn on/off normal/bold font comparison inhibit"},
{ "-/+fbx", "turn off/on linedrawing characters"},
#if OPT_RENDERFONT
{ "-fa pattern", "FreeType font-selection pattern" },
{ "-fd pattern", "FreeType Doublesize font-selection pattern" },
{ "-fs size", "FreeType font-size" },
#endif
#if OPT_WIDE_CHARS
{ "-fw fontname", "doublewidth text font" },
{ "-fwb fontname", "doublewidth bold text font" },
#endif
#if OPT_INPUT_METHOD
{ "-fx fontname", "XIM fontset" },
#endif
{ "-iconic", "start iconic" },
{ "-name string", "client instance, icon, and title strings" },
{ "-class string", "class string (XTerm)" },
{ "-title string", "title string" },
{ "-xrm resourcestring", "additional resource specifications" },
{ "-/+132", "turn on/off 80/132 column switching" },
{ "-/+ah", "turn on/off always highlight" },
#ifndef NO_ACTIVE_ICON
{ "-/+ai", "turn off/on active icon" },
{ "-fi fontname", "icon font for active icon" },
#endif
{ "-b number", "internal border in pixels" },
{ "-/+bc", "turn on/off text cursor blinking" },
{ "-bcf milliseconds", "time text cursor is off when blinking"},
{ "-bcn milliseconds", "time text cursor is on when blinking"},
{ "-/+bdc", "turn off/on display of bold as color"},
{ "-/+cb", "turn on/off cut-to-beginning-of-line inhibit" },
{ "-cc classrange", "specify additional character classes" },
{ "-/+cm", "turn off/on ANSI color mode" },
{ "-/+cn", "turn on/off cut newline inhibit" },
{ "-cr color", "text cursor color" },
{ "-/+cu", "turn on/off curses emulation" },
{ "-/+dc", "turn off/on dynamic color selection" },
#if OPT_HIGHLIGHT_COLOR
{ "-/+hm", "turn on/off selection-color override" },
{ "-selbg color", "selection background color" },
{ "-selfg color", "selection foreground color" },
#endif
#if OPT_HP_FUNC_KEYS
{ "-/+hf", "turn on/off HP Function Key escape codes" },
#endif
{ "-/+hold", "turn on/off logic that retains window after exit" },
#if OPT_INITIAL_ERASE
{ "-/+ie", "turn on/off initialization of 'erase' from pty" },
#endif
{ "-/+im", "use insert mode for TERMCAP" },
{ "-/+j", "turn on/off jump scroll" },
#if OPT_C1_PRINT
{ "-/+k8", "turn on/off C1-printable classification"},
#endif
{ "-kt keyboardtype", "set keyboard type:" KEYBOARD_TYPES },
#ifdef ALLOWLOGGING
{ "-/+l", "turn on/off logging" },
{ "-lf filename", "logging filename" },
#else
{ "-/+l", "turn on/off logging (not supported)" },
{ "-lf filename", "logging filename (not supported)" },
#endif
{ "-/+ls", "turn on/off login shell" },
{ "-/+mb", "turn on/off margin bell" },
{ "-mc milliseconds", "multiclick time in milliseconds" },
{ "-/+mesg", "forbid/allow messages" },
{ "-ms color", "pointer color" },
{ "-nb number", "margin bell in characters from right end" },
{ "-/+nul", "turn off/on display of underlining" },
{ "-/+aw", "turn on/off auto wraparound" },
{ "-/+pc", "turn on/off PC-style bold colors" },
{ "-/+rw", "turn on/off reverse wraparound" },
{ "-/+s", "turn on/off multiscroll" },
{ "-/+sb", "turn on/off scrollbar" },
#ifdef SCROLLBAR_RIGHT
{ "-rightbar", "force scrollbar right (default left)" },
{ "-leftbar", "force scrollbar left" },
#endif
{ "-/+rvc", "turn off/on display of reverse as color" },
{ "-/+sf", "turn on/off Sun Function Key escape codes" },
{ "-/+si", "turn on/off scroll-on-tty-output inhibit" },
{ "-/+sk", "turn on/off scroll-on-keypress" },
{ "-sl number", "number of scrolled lines to save" },
#if OPT_SUNPC_KBD
{ "-/+sp", "turn on/off Sun/PC Function/Keypad mapping" },
#endif
#if OPT_TEK4014
{ "-/+t", "turn on/off Tek emulation window" },
#endif
#if OPT_TOOLBAR
{ "-/+tb", "turn on/off toolbar" },
#endif
{ "-ti termid", "terminal identifier" },
{ "-tm string", "terminal mode keywords and characters" },
{ "-tn name", "TERM environment variable name" },
#if OPT_WIDE_CHARS
{ "-/+u8", "turn on/off UTF-8 mode (implies wide-characters)" },
#endif
#if OPT_LUIT_PROG
{ "-/+lc", "turn on/off locale mode using luit" },
{ "-lcc path", "filename of locale converter (" DEFLOCALEFILTER ")" },
#endif
{ "-/+uc", "turn on/off underline cursor" },
{ "-/+ulc", "turn off/on display of underline as color" },
{ "-/+ut", "turn on/off utmp inhibit (not supported)" },
{ "-/+ulit", "turn off/on display of underline as italics" },
{ "-/+vb", "turn on/off visual bell" },
{ "-/+pob", "turn on/off pop on bell" },
#if OPT_WIDE_CHARS
{ "-/+wc", "turn on/off wide-character mode" },
{ "-/+mk_width", "turn on/off simple width convention" },
{ "-/+cjk_width", "turn on/off legacy CJK width convention" },
#endif
{ "-/+wf", "turn on/off wait for map before command exec" },
{ "-e command args ...", "command to execute" },
#if OPT_TEK4014
{ "%geom", "Tek window geometry" },
#endif
{ "#geom", "icon window geometry" },
{ "-T string", "title name for window" },
{ "-n string", "icon name for window" },
{ "-C", "intercept console messages" },
{ "-Sccn", "slave mode on \"ttycc\", file descriptor \"n\"" },
{ "-into windowId", "use the window id given to -into as the parent window rather than the default root window" },
#if OPT_ZICONBEEP
{ "-ziconbeep percent", "beep and flag icon of window having hidden output" },
#endif
#if OPT_SAME_NAME
{ "-/+samename", "turn on/off the no-flicker option for title and icon name" },
#endif
#if OPT_SESSION_MGT
{ "-/+sm", "turn on/off the session-management support" },
#endif
#if OPT_MAXIMIZE
{"-/+maximized", "turn on/off maxmize on startup" },
#endif
{ NULL, NULL }};
#ifdef DBG_CONSOLE
FILE *confd;
static void
closecons(void)
{
if (confs != 0) {
fclose(confd);
confd = 0;
}
}
static void
opencons(void)
{
closecons();
if ((confd = fopen("/dev/console$", "w")) < 0) {
fputs("!!! Cannot open console device.\n",
stderr);
exit(1);
}
}
#else
#define opencons()
#define closecons()
#endif
static char *message[] =
{
"Fonts should be fixed width and, if both normal and bold are specified, should",
"have the same size. If only a normal font is specified, it will be used for",
"both normal and bold text (by doing overstriking). The -e option, if given,",
"must appear at the end of the command line, otherwise the user's default shell",
"will be started. Options that start with a plus sign (+) restore the default.",
NULL};
static int
decode_keyvalue(char **ptr, int termcap)
{
char *string = *ptr;
int value = -1;
TRACE(("...decode '%s'\n", string));
if (*string == '^') {
switch (*++string) {
case '?':
value = A2E(ANSI_DEL);
break;
case '-':
if (!termcap) {
errno = 0;
#if defined(_POSIX_VDISABLE) && defined(HAVE_UNISTD_H)
value = _POSIX_VDISABLE;
#endif
#if defined(_PC_VDISABLE)
if (value == -1) {
value = fpathconf(0, _PC_VDISABLE);
if (value == -1) {
if (errno != 0)
break;
value = 0377;
}
}
#elif defined(VDISABLE)
if (value == -1)
value = VDISABLE;
#endif
break;
}
default:
value = CONTROL(*string);
break;
}
++string;
} else if (termcap && (*string == '\\')) {
char *d;
int temp = strtol(string + 1, &d, 8);
if (temp > 0 && d != string) {
value = temp;
string = d;
}
} else {
value = CharOf(*string);
++string;
}
*ptr = string;
return value;
}
static int
abbrev(char *tst, char *cmp, size_t need)
{
size_t len = strlen(tst);
return ((len >= need) && (!strncmp(tst, cmp, len)));
}
static void
Syntax(char *badOption)
{
OptionHelp *opt;
OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList));
int col;
fprintf(stderr, "%s: bad command line option \"%s\"\r\n\n",
ProgramName, badOption);
fprintf(stderr, "usage: %s", ProgramName);
col = 8 + strlen(ProgramName);
for (opt = list; opt->opt; opt++) {
int len = 3 + strlen(opt->opt);
if (col + len > 79) {
fprintf(stderr, "\r\n ");
col = 3;
}
fprintf(stderr, " [%s]", opt->opt);
col += len;
}
fprintf(stderr, "\r\n\nType %s -help for a full description.\r\n\n",
ProgramName);
exit(1);
}
static void
Version(void)
{
printf("%s\n", xtermVersion());
fflush(stdout);
}
static void
Help(void)
{
OptionHelp *opt;
OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList));
char **cpp;
printf("%s usage:\n %s [-options ...] [-e command args]\n\n",
xtermVersion(), ProgramName);
printf("where options include:\n");
for (opt = list; opt->opt; opt++) {
printf(" %-28s %s\n", opt->opt, opt->desc);
}
putchar('\n');
for (cpp = message; *cpp; cpp++)
puts(*cpp);
putchar('\n');
fflush(stdout);
}
static Boolean
ConvertConsoleSelection(Widget w GCC_UNUSED,
Atom * selection GCC_UNUSED,
Atom * target GCC_UNUSED,
Atom * type GCC_UNUSED,
XtPointer *value GCC_UNUSED,
unsigned long *length GCC_UNUSED,
int *format GCC_UNUSED)
{
return False;
}
#if OPT_SESSION_MGT
static void
die_callback(Widget w GCC_UNUSED,
XtPointer client_data GCC_UNUSED,
XtPointer call_data GCC_UNUSED)
{
Cleanup(0);
}
static void
save_callback(Widget w GCC_UNUSED,
XtPointer client_data GCC_UNUSED,
XtPointer call_data)
{
XtCheckpointToken token = (XtCheckpointToken) call_data;
token->save_success = True;
}
static void
icewatch(IceConn iceConn,
IcePointer clientData GCC_UNUSED,
Bool opening,
IcePointer * watchData GCC_UNUSED)
{
if (opening) {
ice_fd = IceConnectionNumber(iceConn);
TRACE(("got IceConnectionNumber %d\n", ice_fd));
} else {
ice_fd = -1;
TRACE(("reset IceConnectionNumber\n"));
}
}
#endif
static void
DeleteWindow(Widget w,
XEvent * event GCC_UNUSED,
String * params GCC_UNUSED,
Cardinal *num_params GCC_UNUSED)
{
#if OPT_TEK4014
if (w == toplevel) {
if (TEK4014_SHOWN(term))
hide_vt_window();
else
do_hangup(w, (XtPointer) 0, (XtPointer) 0);
} else if (term->screen.Vshow)
hide_tek_window();
else
#endif
do_hangup(w, (XtPointer) 0, (XtPointer) 0);
}
static void
KeyboardMapping(Widget w GCC_UNUSED,
XEvent * event,
String * params GCC_UNUSED,
Cardinal *num_params GCC_UNUSED)
{
switch (event->type) {
case MappingNotify:
XRefreshKeyboardMapping(&event->xmapping);
break;
}
}
static XtActionsRec actionProcs[] =
{
{"DeleteWindow", DeleteWindow},
{"KeyboardMapping", KeyboardMapping},
};
char **gblenvp;
int
main(int argc, char **argv ENVP_ARG)
{
Widget form_top, menu_top;
Dimension menu_high;
TScreen *screen;
int mode;
char *my_class = DEFCLASS;
Window winToEmbedInto = None;
#if OPT_COLOR_RES
Bool reversed = False;
#endif
ProgramName = argv[0];
save_ruid = getuid();
save_rgid = getgid();
TRACE_OPTS(xtermOptions, optionDescList, XtNumber(optionDescList));
TRACE_ARGV("Before XtOpenApplication", argv);
if (argc > 1) {
int n;
unsigned unique = 2;
Bool quit = True;
for (n = 1; n < argc; n++) {
TRACE(("parsing %s\n", argv[n]));
if (abbrev(argv[n], "-version", unique)) {
Version();
} else if (abbrev(argv[n], "-help", unique)) {
Help();
} else if (abbrev(argv[n], "-class", 3)) {
if ((my_class = argv[++n]) == 0) {
Help();
} else {
quit = False;
}
unique = 3;
} else {
#if OPT_COLOR_RES
if (abbrev(argv[n], "-reverse", 2)
|| !strcmp("-rv", argv[n])) {
reversed = True;
} else if (!strcmp("+rv", argv[n])) {
reversed = False;
}
#endif
quit = False;
unique = 3;
}
}
if (quit)
exit(0);
}
gblenvp = envp;
#ifdef I18N
setlocale(LC_ALL, NULL);
#endif
opencons();
ttydev = TypeMallocN(char, PTMS_BUFSZ);
ptydev = TypeMallocN(char, PTMS_BUFSZ);
if (!ttydev || !ptydev) {
fprintf(stderr,
"%s: unable to allocate memory for ttydev or ptydev\n",
ProgramName);
exit(1);
}
strcpy(ttydev, TTYDEV);
strcpy(ptydev, PTYDEV);
d_tio.c_iflag = ICRNL | IXON;
d_tio.c_oflag = OPOST | ONLCR | TAB3;
d_tio.c_cflag = B38400 | CS8 | CREAD | PARENB | HUPCL;
d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
d_tio.c_line = 0;
d_tio.c_cc[VINTR] = CONTROL('C');
d_tio.c_cc[VERASE] = ANSI_DEL;
d_tio.c_cc[VKILL] = CONTROL('U');
d_tio.c_cc[VQUIT] = CQUIT;
d_tio.c_cc[VEOF] = CEOF;
d_tio.c_cc[VEOL] = CEOL;
XtSetErrorHandler(xt_error);
#if OPT_SESSION_MGT
toplevel = XtOpenApplication(&app_con, my_class,
optionDescList,
XtNumber(optionDescList),
&argc, argv, fallback_resources,
sessionShellWidgetClass,
NULL, 0);
IceAddConnectionWatch(icewatch, NULL);
#else
toplevel = XtAppInitialize(&app_con, my_class,
optionDescList,
XtNumber(optionDescList),
&argc, argv, fallback_resources,
NULL, 0);
#endif
XtSetErrorHandler((XtErrorHandler) 0);
XtGetApplicationResources(toplevel, (XtPointer) &resource,
application_resources,
XtNumber(application_resources), NULL, 0);
TRACE_XRES();
XtAppAddActions(app_con, actionProcs, XtNumber(actionProcs));
if (resource.tty_modes) {
int n = parse_tty_modes(resource.tty_modes, ttymodelist);
if (n < 0) {
fprintf(stderr, "%s: bad tty modes \"%s\"\n",
ProgramName, resource.tty_modes);
} else if (n > 0) {
override_tty_modes = True;
}
}
#if OPT_ZICONBEEP
if (resource.zIconBeep > 100 || resource.zIconBeep < -100) {
resource.zIconBeep = 0;
fprintf(stderr,
"a number between -100 and 100 is required for zIconBeep. 0 used by default\n");
}
#endif
hold_screen = resource.hold_screen ? 1 : 0;
xterm_name = resource.xterm_name;
if (strcmp(xterm_name, "-") == 0)
xterm_name = DFT_TERMTYPE;
if (resource.icon_geometry != NULL) {
int scr, junk;
int ix, iy;
Arg args[2];
for (scr = 0;
XtScreen(toplevel) != ScreenOfDisplay(XtDisplay(toplevel), scr);
scr++) ;
args[0].name = XtNiconX;
args[1].name = XtNiconY;
XGeometry(XtDisplay(toplevel), scr, resource.icon_geometry, "",
0, 0, 0, 0, 0, &ix, &iy, &junk, &junk);
args[0].value = (XtArgVal) ix;
args[1].value = (XtArgVal) iy;
XtSetValues(toplevel, args, 2);
}
XtSetValues(toplevel, ourTopLevelShellArgs,
number_ourTopLevelShellArgs);
#if OPT_WIDE_CHARS
init_classtab();
#endif
TRACE_ARGV("After XtOpenApplication", argv);
for (argc--, argv++; argc > 0; argc--, argv++) {
if (**argv != '-')
Syntax(*argv);
TRACE(("parsing %s\n", argv[0]));
switch (argv[0][1]) {
case 'h':
Help();
continue;
case 'v':
Version();
continue;
case 'C':
{
struct stat sbuf;
if (!stat("/dev/console", &sbuf) &&
(sbuf.st_uid == save_ruid) &&
!access("/dev/console", R_OK | W_OK)) {
Console = True;
} else
Console = False;
}
continue;
case 'S':
if (sscanf(*argv + 2, "%c%c%d", passedPty, passedPty + 1,
&am_slave) != 3)
Syntax(*argv);
continue;
#ifdef DEBUG
case 'D':
debug = True;
continue;
#endif
case 'c':
if (strcmp(argv[0] + 1, "class") == 0)
argc--, argv++;
else
Syntax(*argv);
continue;
case 'e':
if (argc <= 1)
Syntax(*argv);
command_to_exec = ++argv;
break;
case 'i':
if (argc <= 1) {
Syntax(*argv);
} else {
char *endPtr;
--argc;
++argv;
winToEmbedInto = (Window) strtol(argv[0], &endPtr, 10);
}
continue;
default:
Syntax(*argv);
}
break;
}
SetupMenus(toplevel, &form_top, &menu_top, &menu_high);
term = (XtermWidget) XtVaCreateManagedWidget("vt100", xtermWidgetClass,
form_top,
#if OPT_TOOLBAR
XtNmenuBar, menu_top,
XtNresizable, True,
XtNfromVert, menu_top,
XtNleft, XawChainLeft,
XtNright, XawChainRight,
XtNtop, XawChainTop,
XtNbottom, XawChainBottom,
XtNmenuHeight, menu_high,
#endif
(XtPointer) 0);
decode_keyboard_type(term, &resource);
screen = TScreenOf(term);
screen->inhibit = 0;
#ifdef ALLOWLOGGING
if (term->misc.logInhibit)
screen->inhibit |= I_LOG;
#endif
if (term->misc.signalInhibit)
screen->inhibit |= I_SIGNAL;
#if OPT_TEK4014
if (term->misc.tekInhibit)
screen->inhibit |= I_TEK;
#endif
#if OPT_TEK4014
if (screen->inhibit & I_TEK)
TEK4014_ACTIVE(term) = False;
if (TEK4014_ACTIVE(term) && !TekInit())
SysError(ERROR_INIT);
#endif
#if OPT_TOOLBAR
ShowToolbar(resource.toolBar);
#endif
#if OPT_SESSION_MGT
if (resource.sessionMgt) {
TRACE(("Enabling session-management callbacks\n"));
XtAddCallback(toplevel, XtNdieCallback, die_callback, NULL);
XtAddCallback(toplevel, XtNsaveCallback, save_callback, NULL);
}
#endif
if (command_to_exec) {
Arg args[2];
if (!resource.title) {
if (command_to_exec) {
resource.title = x_basename(command_to_exec[0]);
}
}
if (!resource.icon_name)
resource.icon_name = resource.title;
XtSetArg(args[0], XtNtitle, resource.title);
XtSetArg(args[1], XtNiconName, resource.icon_name);
TRACE(("setting:\n\ttitle \"%s\"\n\ticon \"%s\"\n\tbased on command \"%s\"\n",
resource.title,
resource.icon_name,
*command_to_exec));
XtSetValues(toplevel, args, 2);
}
#if OPT_LUIT_PROG
if (term->misc.callfilter) {
int u = (term->misc.use_encoding ? 2 : 0);
if (command_to_exec) {
int n;
char **c;
for (n = 0, c = command_to_exec; *c; n++, c++) ;
c = TypeMallocN(char *, n + 3 + u);
if (c == NULL)
SysError(ERROR_LUMALLOC);
memcpy(c + 2 + u, command_to_exec, (n + 1) * sizeof(char *));
c[0] = term->misc.localefilter;
if (u) {
c[1] = "-encoding";
c[2] = term->misc.locale_str;
}
c[1 + u] = "--";
command_to_exec_with_luit = c;
} else {
static char *luit[6];
luit[0] = term->misc.localefilter;
if (u) {
luit[1] = "-encoding";
luit[2] = term->misc.locale_str;
luit[3] = NULL;
} else
luit[1] = NULL;
command_to_exec_with_luit = luit;
}
}
#endif
#ifdef DEBUG
{
char dbglogfile[45];
int i = -1;
if (debug) {
timestamp_filename(dbglogfile, "xterm.debug.log.");
if (creat_as(save_ruid, save_rgid, False, dbglogfile, 0666) > 0) {
i = open(dbglogfile, O_WRONLY | O_TRUNC);
}
}
if (i >= 0) {
dup2(i, 2);
(void) fcntl(i, F_SETFD, 1);
}
}
#endif
spawnXTerm(term);
(void) signal(SIGCHLD, reapchild);
if (am_slave >= 0) {
char buf[80];
buf[0] = '\0';
sprintf(buf, "%lx\n", XtWindow(SHELL_OF(CURRENT_EMU())));
write(screen->respond, buf, strlen(buf));
}
if (0 > (mode = fcntl(screen->respond, F_GETFL, 0)))
SysError(ERROR_F_GETFL);
mode |= O_NDELAY;
if (fcntl(screen->respond, F_SETFL, mode))
SysError(ERROR_F_SETFL);
FD_ZERO(&pty_mask);
FD_ZERO(&X_mask);
FD_ZERO(&Select_mask);
FD_SET(screen->respond, &pty_mask);
FD_SET(ConnectionNumber(screen->display), &X_mask);
FD_SET(screen->respond, &Select_mask);
FD_SET(ConnectionNumber(screen->display), &Select_mask);
max_plus1 = ((screen->respond < ConnectionNumber(screen->display))
? (1 + ConnectionNumber(screen->display))
: (1 + screen->respond));
#ifdef DEBUG
if (debug)
printf("debugging on\n");
#endif
XSetErrorHandler(xerror);
XSetIOErrorHandler(xioerror);
initPtyData(&VTbuffer);
#ifdef ALLOWLOGGING
if (term->misc.log_on) {
StartLog(screen);
}
#endif
if (winToEmbedInto != None) {
XtRealizeWidget(toplevel);
XReparentWindow(XtDisplay(toplevel),
XtWindow(toplevel),
winToEmbedInto, 0, 0);
}
#if OPT_COLOR_RES
TRACE(("checking resource values rv %s fg %s, bg %s\n",
BtoS(term->misc.re_verse0),
NonNull(term->screen.Tcolors[TEXT_FG].resource),
NonNull(term->screen.Tcolors[TEXT_BG].resource)));
if ((reversed && term->misc.re_verse0)
&& ((term->screen.Tcolors[TEXT_FG].resource
&& !isDefaultForeground(term->screen.Tcolors[TEXT_FG].resource))
|| (term->screen.Tcolors[TEXT_BG].resource
&& !isDefaultBackground(term->screen.Tcolors[TEXT_BG].resource))
))
ReverseVideo(term);
#endif
#if OPT_MAXIMIZE
if (resource.maximized)
RequestMaximize(term, True);
#endif
for (;;) {
#if OPT_TEK4014
if (TEK4014_ACTIVE(term))
TekRun();
else
#endif
VTRun();
}
return 0;
}
static int
pty_search(int *pty)
{
char namebuf[PTMS_BUFSZ];
int fd = open("/dev/ptms$", 0);
if (fd && ptioctl(fd, PTMS_GETPTY, namebuf) == 0) {
strcpy(ttydev, namebuf);
strcpy(ptydev, namebuf);
*x_basename(ttydev) = 't';
close(fd);
if ((*pty = open(ptydev, O_RDWR)) >= 0) {
#ifdef PTYDEBUG
ptioctl(*pty, XTY_TRACE, 0);
#endif
return 0;
} else {
fprintf(stderr, "Unable to open %s, errno=%d\n", ptydev, errno);
}
}
return 1;
}
static int
get_pty(int *pty)
{
return pty_search(pty);
}
#if OPT_TEK4014
static char *tekterm[] =
{
"tek4014",
"tek4015",
"tek4012",
"tek4013",
"tek4010",
"dumb",
0
};
#endif
static char *vtterm[] =
{
#ifdef USE_X11TERM
"x11term",
#endif
DFT_TERMTYPE,
"xterm",
"vt102",
"vt100",
"ansi",
"dumb",
0
};
static SIGNAL_T
hungtty(int i GCC_UNUSED)
{
longjmp(env, 1);
SIGNAL_RETURN;
}
#if OPT_PTY_HANDSHAKE
struct {
int rows;
int cols;
} handshake = {
-1, -1
};
void
first_map_occurred(void)
{
if (resource.wait_for_map) {
TScreen *screen = TScreenOf(term);
handshake.rows = screen->max_row;
handshake.cols = screen->max_col;
resource.wait_for_map = False;
}
}
#endif
static void
set_owner(char *device, uid_t uid, gid_t gid, mode_t mode)
{
int why;
if (chown(device, uid, gid) < 0) {
why = errno;
if (why != ENOENT
&& save_ruid == 0) {
fprintf(stderr, "Cannot chown %s to %ld,%ld: %s\n",
device, (long) uid, (long) gid,
strerror(why));
}
}
}
#define THE_PARENT 1
#define THE_CHILD 2
int whoami = -1;
SIGNAL_T
killit(int sig)
{
switch (whoami) {
case -1:
signal(sig, killit);
kill(-getpid(), sig);
break;
case THE_PARENT:
wait(NULL);
signal(SIGTERM, SIG_DFL);
kill(-getpid(), SIGTERM);
Exit(0);
break;
case THE_CHILD:
signal(SIGTERM, SIG_DFL);
kill(-getppid(), SIGTERM);
Exit(0);
break;
}
SIGNAL_RETURN;
}
#define close_fd(fd) close(fd), fd = -1
static int
spawnXTerm(XtermWidget xw)
{
TScreen *screen = TScreenOf(xw);
int Xsocket = ConnectionNumber(screen->display);
int ttyfd = -1;
TERMIO_STRUCT tio;
int status;
Bool ok_termcap;
char *newtc;
char *TermName = NULL;
char *ptr, *shname, buf[64];
int i, no_dev_tty = False;
char *dev_tty_name = (char *) 0;
TTYSIZE_STRUCT ts;
int pgrp = getpid();
char numbuf[12], **envnew;
screen->uid = save_ruid;
screen->gid = save_rgid;
if (am_slave >= 0) {
screen->respond = am_slave;
ptydev[strlen(ptydev) - 2] =
ttydev[strlen(ttydev) - 2] = passedPty[0];
ptydev[strlen(ptydev) - 1] =
ttydev[strlen(ttydev) - 1] = passedPty[1];
(void) xtermResetIds(screen);
} else {
Bool tty_got_hung;
signal(SIGALRM, hungtty);
alarm(2);
if (!setjmp(env)) {
ttyfd = open("/dev/tty", O_RDWR);
alarm(0);
tty_got_hung = False;
} else {
tty_got_hung = True;
ttyfd = -1;
errno = ENXIO;
}
signal(SIGALRM, SIG_DFL);
if (ttyfd < 0) {
if (tty_got_hung || errno == ENXIO || errno == EIO ||
errno == EINVAL || errno == ENOTTY) {
no_dev_tty = True;
tio = d_tio;
} else {
SysError(ERROR_OPDEVTTY);
}
} else {
if (ioctl(ttyfd, TCGETA, &tio) == -1)
tio = d_tio;
close_fd(ttyfd);
}
if (get_pty(&screen->respond)) {
exit(ERROR_PTYS);
}
}
XtSetMappedWhenManaged(SHELL_OF(CURRENT_EMU()), False);
wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW",
False);
if (!TEK4014_ACTIVE(xw))
VTInit();
if (Console) {
XmuGetHostname(mit_console_name + MIT_CONSOLE_LEN, 255);
mit_console = XInternAtom(screen->display, mit_console_name, False);
XtOwnSelection(SHELL_OF(CURRENT_EMU()),
mit_console, CurrentTime,
ConvertConsoleSelection, NULL, NULL);
}
#if OPT_TEK4014
if (TEK4014_ACTIVE(xw)) {
envnew = tekterm;
newtc = TekScreenOf(tekWidget)->tcapbuf;
} else
#endif
{
envnew = vtterm;
newtc = screen->tcapbuf;
}
ok_termcap = True;
if (!get_termcap(TermName = resource.term_name, newtc)) {
char *last = NULL;
TermName = *envnew;
ok_termcap = False;
while (*envnew != NULL) {
if ((last == NULL || strcmp(last, *envnew))
&& get_termcap(*envnew, newtc)) {
TermName = *envnew;
ok_termcap = True;
break;
}
last = *envnew;
envnew++;
}
}
if (ok_termcap) {
resize_termcap(xw, newtc);
}
#if OPT_TEK4014
if (TEK4014_ACTIVE(xw)) {
TTYSIZE_ROWS(ts) = 38;
TTYSIZE_COLS(ts) = 81;
ts.ws_xpixel = TFullWidth(&(tekWidget->screen));
ts.ws_ypixel = TFullHeight(&(tekWidget->screen));
} else
#endif
{
TTYSIZE_ROWS(ts) = MaxRows(screen);
TTYSIZE_COLS(ts) = MaxCols(screen);
ts.ws_xpixel = FullWidth(screen);
ts.ws_ypixel = FullHeight(screen);
}
if (am_slave < 0) {
char sema[40];
HEV sev;
sprintf(sema, "\\SEM32\\xterm%s", &ptydev[8]);
if (DosCreateEventSem(sema, &sev, DC_SEM_SHARED, False))
SysError(ERROR_FORK);
switch ((screen->pid = fork())) {
case -1:
SysError(ERROR_FORK);
default:
whoami = THE_PARENT;
DosWaitEventSem(sev, 1000L);
DosCloseEventSem(sev);
break;
case 0:
whoami = THE_CHILD;
opencons();
close(ConnectionNumber(screen->display));
close(screen->respond);
if ((ttyfd = open(ttydev, O_RDWR)) < 0) {
fprintf(stderr, "Cannot open slave side of PTY\n");
exit(1);
}
#ifdef EMXNOTBOGUS
if ((ptr = ttyname(ttyfd)) != 0) {
ttydev = TypeRealloc(char, strlen(ptr) + 1, ttydev);
if (ttydev == NULL) {
SysError(ERROR_SPREALLOC);
}
(void) strcpy(ttydev, ptr);
}
#else
ptr = ttydev;
#endif
ptioctl(ttyfd, XTY_ENADUP, 0);
set_owner(ttydev, screen->uid, screen->gid,
(resource.messages ? 0622U : 0600U));
{
TERMIO_STRUCT t, t1;
if (ptioctl(ttyfd, TCGETA, (char *) &t) < 0)
t = d_tio;
t.c_iflag = ICRNL;
t.c_oflag = OPOST | ONLCR;
t.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
ptioctl(ttyfd, TCSETA, (char *) &t);
if (Console) {
int on = 1;
if (ioctl(ttyfd, TIOCCONS, (char *) &on) == -1)
fprintf(stderr, "%s: cannot open console: %s\n",
ProgramName, strerror(errno));
}
}
signal(SIGCHLD, SIG_DFL);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
xtermCopyEnv(gblenvp);
xtermSetenv("TERM", TermName);
if (!TermName)
*newtc = 0;
sprintf(buf, "%lu",
((unsigned long) XtWindow(SHELL_OF(CURRENT_EMU()))));
xtermSetenv("WINDOWID", buf);
xtermSetenv("DISPLAY", XDisplayString(screen->display));
xtermSetenv("XTERM_VERSION", xtermVersion());
xtermSetenv("XTERM_LOCALE", xtermEnvLocale());
signal(SIGTERM, SIG_DFL);
for (i = 0; i <= 2; i++)
if (i != ttyfd) {
(void) close(i);
(void) dup(ttyfd);
}
if (ttyfd > 2)
close_fd(ttyfd);
setpgrp(0, pgrp);
(void) xtermResetIds(screen);
if (handshake.rows > 0 && handshake.cols > 0) {
TRACE(("handshake ttysize: %dx%d\n",
handshake.rows, handshake.cols));
set_max_row(screen, handshake.rows);
set_max_col(screen, handshake.cols);
TTYSIZE_ROWS(ts) = MaxRows(screen);
TTYSIZE_COLS(ts) = MaxCols(screen);
ts.ws_xpixel = FullWidth(screen);
ts.ws_ypixel = FullHeight(screen);
}
sprintf(numbuf, "%d", MaxCols(screen));
xtermSetenv("COLUMNS", numbuf);
sprintf(numbuf, "%d", MaxRows(screen));
xtermSetenv("LINES", numbuf);
gblenvp = environ;
ptioctl(0, TIOCSWINSZ, (char *) &ts);
signal(SIGHUP, SIG_DFL);
{
char sema[40];
HEV sev;
sprintf(sema, "\\SEM32\\xterm%s", &ttydev[8]);
DosOpenEventSem(sema, &sev);
DosPostEventSem(sev);
DosCloseEventSem(sev);
}
#if OPT_LUIT_PROG
if (command_to_exec_with_luit) {
xtermSetenv("XTERM_SHELL",
xtermFindShell(*command_to_exec_with_luit, False));
TRACE(("spawning command \"%s\"\n", *command_to_exec_with_luit));
execvp(*command_to_exec_with_luit, command_to_exec_with_luit);
fprintf(stderr, "%s: Can't execvp %s: %s\n",
ProgramName, *command_to_exec_with_luit, strerror(errno));
fprintf(stderr, "%s: cannot support your locale.\n",
ProgramName);
}
#endif
if (command_to_exec) {
xtermSetenv("XTERM_SHELL",
xtermFindShell(*command_to_exec, False));
TRACE(("spawning command \"%s\"\n", *command_to_exec));
execvpe(*command_to_exec, command_to_exec, gblenvp);
fprintf(stderr, "%s: Can't execvp %s\n",
ProgramName, *command_to_exec);
}
ptr = x_getenv("X11SHELL");
if (!ptr)
ptr = x_getenv("SHELL");
if (!ptr)
ptr = x_getenv("OS2_SHELL");
if (!ptr)
ptr = "SORRY_NO_SHELL_FOUND";
xtermSetenv("XTERM_SHELL", ptr);
shname = x_basename(ptr);
if (command_to_exec) {
char *exargv[10];
exargv[0] = ptr;
exargv[1] = "/C";
exargv[2] = command_to_exec[0];
exargv[3] = command_to_exec[1];
exargv[4] = command_to_exec[2];
exargv[5] = command_to_exec[3];
exargv[6] = command_to_exec[4];
exargv[7] = command_to_exec[5];
exargv[8] = command_to_exec[6];
exargv[9] = 0;
execvpe(exargv[0], exargv, gblenvp);
fprintf(stderr, "%s: Can't execvp %s\n",
ProgramName, *command_to_exec);
} else {
execlpe(ptr, shname, 0, gblenvp);
fprintf(stderr, "%s: Could not exec %s!\n",
ProgramName, ptr);
}
sleep(5);
kill(-getppid(), SIGTERM);
exit(ERROR_EXEC);
}
}
signal(SIGHUP, SIG_IGN);
signal(SIGINT, killit);
signal(SIGTERM, killit);
signal(SIGQUIT, SIG_IGN);
return 0;
}
SIGNAL_T
Exit(int n)
{
TScreen *screen = TScreenOf(term);
int pty = term->screen.respond;
close(pty);
#ifdef ALLOWLOGGING
if (screen->logging)
CloseLog(screen);
#endif
if (am_slave < 0) {
set_owner(ttydev, 0, 0, 0666U);
set_owner(ptydev, 0, 0, 0666U);
}
close(screen->respond);
#ifdef ALLOWLOGGING
if (screen->logging)
CloseLog(screen);
#endif
#ifdef NO_LEAKS
if (n == 0) {
TRACE(("Freeing memory leaks\n"));
if (term != 0) {
Display *dpy = term->screen.display;
if (toplevel) {
XtDestroyWidget(toplevel);
TRACE(("destroyed top-level widget\n"));
}
sortedOpts(0, 0, 0);
noleaks_charproc();
noleaks_ptydata();
#if OPT_WIDE_CHARS
noleaks_CharacterClass();
#endif
XtCloseDisplay(dpy);
XtDestroyApplicationContext(app_con);
#if OPT_SESSION_MGT
IceRemoveConnectionWatch(icewatch, NULL);
#endif
TRACE(("closed display\n"));
}
TRACE((0));
}
#endif
exit(n);
SIGNAL_RETURN;
}
static void
resize_termcap(XtermWidget xw, char *newtc)
{
}
int
nonblocking_wait(void)
{
pid_t pid;
pid = waitpid(-1, NULL, WNOHANG);
return pid;
}
static SIGNAL_T
reapchild(int n GCC_UNUSED)
{
int olderrno = errno;
int pid;
pid = wait(NULL);
(void) signal(SIGCHLD, reapchild);
do {
if (pid == term->screen.pid) {
#ifdef DEBUG
if (debug)
fputs("Exiting\n", stderr);
#endif
if (!hold_screen)
need_cleanup = True;
}
} while ((pid = nonblocking_wait()) > 0);
errno = olderrno;
SIGNAL_RETURN;
}
static int
parse_tty_modes(char *s, struct _xttymodes *modelist)
{
struct _xttymodes *mp;
int c;
int count = 0;
TRACE(("parse_tty_modes\n"));
while (1) {
size_t len;
while (*s && isascii(CharOf(*s)) && isspace(CharOf(*s)))
s++;
if (!*s)
return count;
for (len = 0; isalnum(CharOf(s[len])); ++len) ;
for (mp = modelist; mp->name; mp++) {
if (len == mp->len
&& strncmp(s, mp->name, mp->len) == 0)
break;
}
if (!mp->name)
return -1;
s += mp->len;
while (*s && isascii(CharOf(*s)) && isspace(CharOf(*s)))
s++;
if (!*s)
return -1;
if ((c = decode_keyvalue(&s, False)) != -1) {
mp->value = c;
mp->set = 1;
count++;
TRACE(("...parsed #%d: %s=%#x\n", count, mp->name, c));
}
}
}
int
GetBytesAvailable(int fd)
{
long arg;
ioctl(fd, FIONREAD, (char *) &arg);
return (int) arg;
}
int
kill_process_group(int pid, int sig)
{
return kill(-pid, sig);
}
int
ptioctl(int fd, int func, void *data)
{
APIRET rc;
ULONG len;
struct pt_termios pt;
TERMIO_STRUCT *t;
int i;
switch (func) {
case TCGETA:
rc = DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCGETA,
NULL, 0, NULL,
(ULONG *) & pt, sizeof(struct pt_termios), &len);
if (rc)
return -1;
t = (TERMIO_STRUCT *) data;
t->c_iflag = pt.c_iflag;
t->c_oflag = pt.c_oflag;
t->c_cflag = pt.c_cflag;
t->c_lflag = pt.c_lflag;
for (i = 0; i < NCC; i++)
t->c_cc[i] = pt.c_cc[i];
return 0;
case TCSETA:
case TCSETAW:
case TCSETAF:
t = (TERMIO_STRUCT *) data;
pt.c_iflag = t->c_iflag;
pt.c_oflag = t->c_oflag;
pt.c_cflag = t->c_cflag;
pt.c_lflag = t->c_lflag;
for (i = 0; i < NCC; i++)
pt.c_cc[i] = t->c_cc[i];
if (func == TCSETA)
i = XTY_TIOCSETA;
else if (func == TCSETAW)
i = XTY_TIOCSETAW;
else
i = XTY_TIOCSETAF;
rc = DosDevIOCtl(fd, XFREE86_PTY, i,
(ULONG *) & pt, sizeof(struct pt_termios), &len,
NULL, 0, NULL);
return (rc) ? -1 : 0;
case TIOCCONS:
return DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCCONS,
(ULONG *) data, sizeof(ULONG), &len,
NULL, 0, NULL);
case TIOCSWINSZ:
return DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCSWINSZ,
(ULONG *) data, sizeof(TTYSIZE_STRUCT), &len,
NULL, 0, NULL);
case TIOCGWINSZ:
return DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCGWINSZ,
NULL, 0, NULL,
(ULONG *) data, sizeof(TTYSIZE_STRUCT), &len);
case XTY_ENADUP:
i = 1;
return DosDevIOCtl(fd, XFREE86_PTY, XTY_ENADUP,
(ULONG *) & i, sizeof(ULONG), &len,
NULL, 0, NULL);
case XTY_TRACE:
i = 2;
return DosDevIOCtl(fd, XFREE86_PTY, XTY_TRACE,
(ULONG *) & i, sizeof(ULONG), &len,
NULL, 0, NULL);
case PTMS_GETPTY:
i = 1;
return DosDevIOCtl(fd, XFREE86_PTY, PTMS_GETPTY,
(ULONG *) & i, sizeof(ULONG), &len,
(UCHAR *) data, 14, &len);
default:
return -1;
}
}