1
/* removed all foreign stuff to get the code more clear (hv)
2
* and did some rewrite for the obscure OS/2 environment
6
static char *rid = "$XConsortium: main.c,v 1.227.1.2 95/06/29 18:13:15 kaleb Exp $";
8
/* $XFree86: xc/programs/xterm/os2main.c,v 3.57 2002/12/27 21:05:22 dickey Exp $ */
10
/***********************************************************
12
Copyright (c) 1987, 1988 X Consortium
14
Permission is hereby granted, free of charge, to any person obtaining a copy
15
of this software and associated documentation files (the "Software"), to deal
16
in the Software without restriction, including without limitation the rights
17
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
copies of the Software, and to permit persons to whom the Software is
19
furnished to do so, subject to the following conditions:
21
The above copyright notice and this permission notice shall be included in
22
all copies or substantial portions of the Software.
24
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
28
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
Except as contained in this notice, the name of the X Consortium shall not be
32
used in advertising or otherwise to promote the sale, use or other dealings
33
in this Software without prior written authorization from the X Consortium.
35
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard.
39
Permission to use, copy, modify, and distribute this software and its
40
documentation for any purpose and without fee is hereby granted,
41
provided that the above copyright notice appear in all copies and that
42
both that copyright notice and this permission notice appear in
43
supporting documentation, and that the name of Digital not be used in
44
advertising or publicity pertaining to distribution of the software
45
without specific, written prior permission.
47
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
48
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
49
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
50
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
51
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
52
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
55
******************************************************************/
58
#define INCL_DOSFILEMGR
59
#define INCL_DOSDEVIOCTL
60
#define INCL_DOSSEMAPHORES
68
#include <X11/cursorfont.h>
70
#include <X11/Xlocale.h>
75
#if defined(HAVE_LIB_XAW)
76
#include <X11/Xaw/Form.h>
77
#elif defined(HAVE_LIB_XAW3D)
78
#include <X11/Xaw3d/Form.h>
79
#elif defined(HAVE_LIB_NEXTAW)
80
#include <X11/neXtaw/Form.h>
83
#endif /* OPT_TOOLBAR */
96
#include <charclass.h>
101
setpgrp(pid_t pid, gid_t pgid)
107
chown(const char *fn, pid_t pid, gid_t gid)
118
#include <sys/stat.h>
119
#include <sys/param.h> /* for NOFILE */
123
static SIGNAL_T reapchild(int n);
124
static int spawn(void);
125
static void get_terminal(void);
126
static void resize(TScreen * s, char *oldtc, char *newtc);
127
static void set_owner(char *device, int uid, int gid, int mode);
129
static Bool added_utmp_entry = False;
132
** Ordinarily it should be okay to omit the assignment in the following
133
** statement. Apparently the c89 compiler on AIX 4.1.3 has a bug, or does
134
** it? Without the assignment though the compiler will init command_to_exec
135
** to 0xffffffff instead of NULL; and subsequent usage, e.g. in spawn() to
138
static char **command_to_exec = NULL;
141
static char **command_to_exec_with_luit = NULL;
144
/* The following structures are initialized in main() in order
145
** to eliminate any assumptions about the internal order of their
148
static struct termio d_tio;
150
/* allow use of system default characters if defined and reasonable */
152
#define CEOF CONTROL('D')
158
#define CFLUSH CONTROL('O')
161
#define CLNEXT CONTROL('V')
167
#define CQUIT CONTROL('\\')
170
#define CRPRNT CONTROL('R')
173
#define CSTART CONTROL('Q')
176
#define CSTOP CONTROL('S')
179
#define CSUSP CONTROL('Z')
185
#define CWERASE CONTROL('W')
189
* SYSV has the termio.c_cc[V] and ltchars; BSD has tchars and ltchars;
190
* SVR4 has only termio.c_cc, but it includes everything from ltchars.
192
static int override_tty_modes = 0;
200
{ "intr", 4, 0, '\0' }, /* tchars.t_intrc ; VINTR */
201
#define XTTYMODE_intr 0
202
{ "quit", 4, 0, '\0' }, /* tchars.t_quitc ; VQUIT */
203
#define XTTYMODE_quit 1
204
{ "erase", 5, 0, '\0' }, /* sgttyb.sg_erase ; VERASE */
205
#define XTTYMODE_erase 2
206
{ "kill", 4, 0, '\0' }, /* sgttyb.sg_kill ; VKILL */
207
#define XTTYMODE_kill 3
208
{ "eof", 3, 0, '\0' }, /* tchars.t_eofc ; VEOF */
209
#define XTTYMODE_eof 4
210
{ "eol", 3, 0, '\0' }, /* VEOL */
211
#define XTTYMODE_eol 5
212
{ "swtch", 5, 0, '\0' }, /* VSWTCH */
213
#define XTTYMODE_swtch 6
214
{ "start", 5, 0, '\0' }, /* tchars.t_startc */
215
#define XTTYMODE_start 7
216
{ "stop", 4, 0, '\0' }, /* tchars.t_stopc */
217
#define XTTYMODE_stop 8
218
{ "brk", 3, 0, '\0' }, /* tchars.t_brkc */
219
#define XTTYMODE_brk 9
220
{ "susp", 4, 0, '\0' }, /* ltchars.t_suspc ; VSUSP */
221
#define XTTYMODE_susp 10
222
{ "dsusp", 5, 0, '\0' }, /* ltchars.t_dsuspc ; VDSUSP */
223
#define XTTYMODE_dsusp 11
224
{ "rprnt", 5, 0, '\0' }, /* ltchars.t_rprntc ; VREPRINT */
225
#define XTTYMODE_rprnt 12
226
{ "flush", 5, 0, '\0' }, /* ltchars.t_flushc ; VDISCARD */
227
#define XTTYMODE_flush 13
228
{ "weras", 5, 0, '\0' }, /* ltchars.t_werasc ; VWERASE */
229
#define XTTYMODE_weras 14
230
{ "lnext", 5, 0, '\0' }, /* ltchars.t_lnextc ; VLNEXT */
231
#define XTTYMODE_lnext 15
232
{ NULL, 0, 0, '\0' }, /* end of data */
236
static int parse_tty_modes(char *s, struct _xttymodes *modelist);
239
static char passedPty[2]; /* name if pty if slave */
242
#include <X11/Xmu/SysUtil.h> /* XmuGetHostname */
243
#define MIT_CONSOLE_LEN 12
244
#define MIT_CONSOLE "MIT_CONSOLE_"
245
static char mit_console_name[255 + MIT_CONSOLE_LEN + 1] = MIT_CONSOLE;
246
static Atom mit_console;
251
/* used by VT (charproc.c) */
253
#define offset(field) XtOffsetOf(XTERM_RESOURCE, field)
255
static XtResource application_resources[] =
257
{"name", "Name", XtRString, sizeof(char *),
258
offset(xterm_name), XtRString, DFT_TERMTYPE},
259
{"iconGeometry", "IconGeometry", XtRString, sizeof(char *),
260
offset(icon_geometry), XtRString, (caddr_t) NULL},
261
{XtNtitle, XtCTitle, XtRString, sizeof(char *),
262
offset(title), XtRString, (caddr_t) NULL},
263
{XtNiconName, XtCIconName, XtRString, sizeof(char *),
264
offset(icon_name), XtRString, (caddr_t) NULL},
265
{"termName", "TermName", XtRString, sizeof(char *),
266
offset(term_name), XtRString, (caddr_t) NULL},
267
{"ttyModes", "TtyModes", XtRString, sizeof(char *),
268
offset(tty_modes), XtRString, (caddr_t) NULL},
269
{"hold", "Hold", XtRBoolean, sizeof(Boolean),
270
offset(hold_screen), XtRString, "false"},
271
{"utmpInhibit", "UtmpInhibit", XtRBoolean, sizeof(Boolean),
272
offset(utmpInhibit), XtRString, "false"},
273
{"messages", "Messages", XtRBoolean, sizeof(Boolean),
274
offset(messages), XtRString, "true"},
275
{"sunFunctionKeys", "SunFunctionKeys", XtRBoolean, sizeof(Boolean),
276
offset(sunFunctionKeys), XtRString, "false"},
278
{"sunKeyboard", "SunKeyboard", XtRBoolean, sizeof(Boolean),
279
offset(sunKeyboard), XtRString, "false"},
282
{"hpFunctionKeys", "HpFunctionKeys", XtRBoolean, sizeof(Boolean),
283
offset(hpFunctionKeys), XtRString, "false"},
285
{"waitForMap", "WaitForMap", XtRBoolean, sizeof(Boolean),
286
offset(wait_for_map), XtRString, "false"},
287
{"useInsertMode", "UseInsertMode", XtRBoolean, sizeof(Boolean),
288
offset(useInsertMode), XtRString, "false"},
290
{"zIconBeep", "ZIconBeep", XtRInt, sizeof(int),
291
offset(zIconBeep), XtRImmediate, 0},
294
{"sameName", "SameName", XtRBoolean, sizeof(Boolean),
295
offset(sameName), XtRString, "true"},
298
{"sessionMgt", "SessionMgt", XtRBoolean, sizeof(Boolean),
299
offset(sessionMgt), XtRString, "true"},
304
static char *fallback_resources[] =
306
"*SimpleMenu*menuLabel.vertSpace: 100",
307
"*SimpleMenu*HorizontalMargins: 16",
308
"*SimpleMenu*Sme.height: 16",
309
"*SimpleMenu*Cursor: left_ptr",
310
"*mainMenu.Label: Main Options (no app-defaults)",
311
"*vtMenu.Label: VT Options (no app-defaults)",
312
"*fontMenu.Label: VT Fonts (no app-defaults)",
314
"*tekMenu.Label: Tek Options (no app-defaults)",
319
/* Command line options table. Only resources are entered here...there is a
320
pass over the remaining options after XrmParseCommand is let loose. */
322
static XrmOptionDescRec optionDescList[] = {
323
{"-geometry", "*vt100.geometry",XrmoptionSepArg, (caddr_t) NULL},
324
{"-132", "*c132", XrmoptionNoArg, (caddr_t) "on"},
325
{"+132", "*c132", XrmoptionNoArg, (caddr_t) "off"},
326
{"-ah", "*alwaysHighlight", XrmoptionNoArg, (caddr_t) "on"},
327
{"+ah", "*alwaysHighlight", XrmoptionNoArg, (caddr_t) "off"},
328
{"-aw", "*autoWrap", XrmoptionNoArg, (caddr_t) "on"},
329
{"+aw", "*autoWrap", XrmoptionNoArg, (caddr_t) "off"},
330
#ifndef NO_ACTIVE_ICON
331
{"-ai", "*activeIcon", XrmoptionNoArg, (caddr_t) "off"},
332
{"+ai", "*activeIcon", XrmoptionNoArg, (caddr_t) "on"},
333
#endif /* NO_ACTIVE_ICON */
334
{"-b", "*internalBorder",XrmoptionSepArg, (caddr_t) NULL},
335
{"-bc", "*cursorBlink", XrmoptionNoArg, (caddr_t) "on"},
336
{"+bc", "*cursorBlink", XrmoptionNoArg, (caddr_t) "off"},
337
{"-bcf", "*cursorOffTime",XrmoptionSepArg, (caddr_t) NULL},
338
{"-bcn", "*cursorOnTime",XrmoptionSepArg, (caddr_t) NULL},
339
{"-bdc", "*colorBDMode", XrmoptionNoArg, (caddr_t) "off"},
340
{"+bdc", "*colorBDMode", XrmoptionNoArg, (caddr_t) "on"},
341
{"-cb", "*cutToBeginningOfLine", XrmoptionNoArg, (caddr_t) "off"},
342
{"+cb", "*cutToBeginningOfLine", XrmoptionNoArg, (caddr_t) "on"},
343
{"-cc", "*charClass", XrmoptionSepArg, (caddr_t) NULL},
344
{"-cm", "*colorMode", XrmoptionNoArg, (caddr_t) "off"},
345
{"+cm", "*colorMode", XrmoptionNoArg, (caddr_t) "on"},
346
{"-cn", "*cutNewline", XrmoptionNoArg, (caddr_t) "off"},
347
{"+cn", "*cutNewline", XrmoptionNoArg, (caddr_t) "on"},
348
{"-cr", "*cursorColor", XrmoptionSepArg, (caddr_t) NULL},
349
{"-cu", "*curses", XrmoptionNoArg, (caddr_t) "on"},
350
{"+cu", "*curses", XrmoptionNoArg, (caddr_t) "off"},
351
{"-dc", "*dynamicColors",XrmoptionNoArg, (caddr_t) "off"},
352
{"+dc", "*dynamicColors",XrmoptionNoArg, (caddr_t) "on"},
353
{"-fb", "*boldFont", XrmoptionSepArg, (caddr_t) NULL},
354
{"-fbb", "*freeBoldBox", XrmoptionNoArg, (caddr_t)"off"},
355
{"+fbb", "*freeBoldBox", XrmoptionNoArg, (caddr_t)"on"},
356
{"-fbx", "*forceBoxChars", XrmoptionNoArg, (caddr_t)"off"},
357
{"+fbx", "*forceBoxChars", XrmoptionNoArg, (caddr_t)"on"},
358
#ifndef NO_ACTIVE_ICON
359
{"-fi", "*iconFont", XrmoptionSepArg, (caddr_t) NULL},
360
#endif /* NO_ACTIVE_ICON */
362
{"-fa", "*faceName", XrmoptionSepArg, (caddr_t) NULL},
363
{"-fs", "*faceSize", XrmoptionSepArg, (caddr_t) NULL},
366
{"-fw", "*wideFont", XrmoptionSepArg, (caddr_t) NULL},
367
{"-fwb", "*wideBoldFont", XrmoptionSepArg, (caddr_t) NULL},
369
#if OPT_HIGHLIGHT_COLOR
370
{"-hc", "*highlightColor", XrmoptionSepArg, (caddr_t) NULL},
373
{"-hf", "*hpFunctionKeys",XrmoptionNoArg, (caddr_t) "on"},
374
{"+hf", "*hpFunctionKeys",XrmoptionNoArg, (caddr_t) "off"},
376
{"-hold", "*hold", XrmoptionNoArg, (caddr_t) "on"},
377
{"+hold", "*hold", XrmoptionNoArg, (caddr_t) "off"},
378
{"-j", "*jumpScroll", XrmoptionNoArg, (caddr_t) "on"},
379
{"+j", "*jumpScroll", XrmoptionNoArg, (caddr_t) "off"},
380
/* parse logging options anyway for compatibility */
381
{"-l", "*logging", XrmoptionNoArg, (caddr_t) "on"},
382
{"+l", "*logging", XrmoptionNoArg, (caddr_t) "off"},
383
{"-lf", "*logFile", XrmoptionSepArg, (caddr_t) NULL},
384
{"-ls", "*loginShell", XrmoptionNoArg, (caddr_t) "on"},
385
{"+ls", "*loginShell", XrmoptionNoArg, (caddr_t) "off"},
386
{"-mb", "*marginBell", XrmoptionNoArg, (caddr_t) "on"},
387
{"+mb", "*marginBell", XrmoptionNoArg, (caddr_t) "off"},
388
{"-mc", "*multiClickTime", XrmoptionSepArg, (caddr_t) NULL},
389
{"-mesg", "*messages", XrmoptionNoArg, (caddr_t) "off"},
390
{"+mesg", "*messages", XrmoptionNoArg, (caddr_t) "on"},
391
{"-ms", "*pointerColor",XrmoptionSepArg, (caddr_t) NULL},
392
{"-nb", "*nMarginBell", XrmoptionSepArg, (caddr_t) NULL},
393
{"-nul", "*underLine", XrmoptionNoArg, (caddr_t) "off"},
394
{"+nul", "*underLine", XrmoptionNoArg, (caddr_t) "on"},
395
{"-pc", "*boldColors", XrmoptionNoArg, (caddr_t) "on"},
396
{"+pc", "*boldColors", XrmoptionNoArg, (caddr_t) "off"},
397
{"-rw", "*reverseWrap", XrmoptionNoArg, (caddr_t) "on"},
398
{"+rw", "*reverseWrap", XrmoptionNoArg, (caddr_t) "off"},
399
{"-s", "*multiScroll", XrmoptionNoArg, (caddr_t) "on"},
400
{"+s", "*multiScroll", XrmoptionNoArg, (caddr_t) "off"},
401
{"-sb", "*scrollBar", XrmoptionNoArg, (caddr_t) "on"},
402
{"+sb", "*scrollBar", XrmoptionNoArg, (caddr_t) "off"},
403
#ifdef SCROLLBAR_RIGHT
404
{"-leftbar", "*rightScrollBar", XrmoptionNoArg, (caddr_t) "off"},
405
{"-rightbar", "*rightScrollBar", XrmoptionNoArg, (caddr_t) "on"},
407
{"-rvc", "*colorRVMode", XrmoptionNoArg, (caddr_t) "off"},
408
{"+rvc", "*colorRVMode", XrmoptionNoArg, (caddr_t) "on"},
409
{"-sf", "*sunFunctionKeys", XrmoptionNoArg, (caddr_t) "on"},
410
{"+sf", "*sunFunctionKeys", XrmoptionNoArg, (caddr_t) "off"},
411
{"-si", "*scrollTtyOutput", XrmoptionNoArg, (caddr_t) "off"},
412
{"+si", "*scrollTtyOutput", XrmoptionNoArg, (caddr_t) "on"},
413
{"-sk", "*scrollKey", XrmoptionNoArg, (caddr_t) "on"},
414
{"+sk", "*scrollKey", XrmoptionNoArg, (caddr_t) "off"},
415
{"-sl", "*saveLines", XrmoptionSepArg, (caddr_t) NULL},
417
{"-sp", "*sunKeyboard", XrmoptionNoArg, (caddr_t) "on"},
418
{"+sp", "*sunKeyboard", XrmoptionNoArg, (caddr_t) "off"},
420
{"-t", "*tekStartup", XrmoptionNoArg, (caddr_t) "on"},
421
{"+t", "*tekStartup", XrmoptionNoArg, (caddr_t) "off"},
422
{"-ti", "*decTerminalID",XrmoptionSepArg, (caddr_t) NULL},
423
{"-tm", "*ttyModes", XrmoptionSepArg, (caddr_t) NULL},
424
{"-tn", "*termName", XrmoptionSepArg, (caddr_t) NULL},
426
{"-u8", "*utf8", XrmoptionNoArg, (caddr_t) "2"},
427
{"+u8", "*utf8", XrmoptionNoArg, (caddr_t) "0"},
430
{"-lc", "*locale", XrmoptionNoArg, (caddr_t) "True"},
431
{"+lc", "*locale", XrmoptionNoArg, (caddr_t) "False"},
432
{"-lcc", "*localeFilter",XrmoptionSepArg, (caddr_t) NULL},
433
{"-en", "*locale", XrmoptionSepArg, (caddr_t) NULL},
435
{"-ulc", "*colorULMode", XrmoptionNoArg, (caddr_t) "off"},
436
{"+ulc", "*colorULMode", XrmoptionNoArg, (caddr_t) "on"},
437
{"-ut", "*utmpInhibit", XrmoptionNoArg, (caddr_t) "on"},
438
{"+ut", "*utmpInhibit", XrmoptionNoArg, (caddr_t) "off"},
439
{"-im", "*useInsertMode", XrmoptionNoArg, (caddr_t) "on"},
440
{"+im", "*useInsertMode", XrmoptionNoArg, (caddr_t) "off"},
441
{"-vb", "*visualBell", XrmoptionNoArg, (caddr_t) "on"},
442
{"+vb", "*visualBell", XrmoptionNoArg, (caddr_t) "off"},
443
{"-pob", "*popOnBell", XrmoptionNoArg, (caddr_t) "on"},
444
{"+pob", "*popOnBell", XrmoptionNoArg, (caddr_t) "off"},
446
{"-wc", "*wideChars", XrmoptionNoArg, (caddr_t) "on"},
447
{"+wc", "*wideChars", XrmoptionNoArg, (caddr_t) "off"},
448
{"-cjk_width", "*cjkWidth", XrmoptionNoArg, (caddr_t) "on"},
449
{"+cjk_width", "*cjkWidth", XrmoptionNoArg, (caddr_t) "off"},
451
{"-wf", "*waitForMap", XrmoptionNoArg, (caddr_t) "on"},
452
{"+wf", "*waitForMap", XrmoptionNoArg, (caddr_t) "off"},
454
{"-ziconbeep", "*zIconBeep", XrmoptionSepArg, (caddr_t) NULL},
457
{"-samename", "*sameName", XrmoptionNoArg, (caddr_t) "on"},
458
{"+samename", "*sameName", XrmoptionNoArg, (caddr_t) "off"},
461
{"-sm", "*sessionMgt", XrmoptionNoArg, (caddr_t) "on"},
462
{"+sm", "*sessionMgt", XrmoptionNoArg, (caddr_t) "off"},
464
/* options that we process ourselves */
465
{"-help", NULL, XrmoptionSkipNArgs, (caddr_t) NULL},
466
{"-version", NULL, XrmoptionSkipNArgs, (caddr_t) NULL},
467
{"-class", NULL, XrmoptionSkipArg, (caddr_t) NULL},
468
{"-e", NULL, XrmoptionSkipLine, (caddr_t) NULL},
469
{"-into", NULL, XrmoptionSkipArg, (caddr_t) NULL},
470
/* bogus old compatibility stuff for which there are
471
standard XtOpenApplication options now */
472
{"%", "*tekGeometry", XrmoptionStickyArg, (caddr_t) NULL},
473
{"#", ".iconGeometry",XrmoptionStickyArg, (caddr_t) NULL},
474
{"-T", ".title", XrmoptionSepArg, (caddr_t) NULL},
475
{"-n", "*iconName", XrmoptionSepArg, (caddr_t) NULL},
476
{"-r", "*reverseVideo",XrmoptionNoArg, (caddr_t) "on"},
477
{"+r", "*reverseVideo",XrmoptionNoArg, (caddr_t) "off"},
478
{"-rv", "*reverseVideo",XrmoptionNoArg, (caddr_t) "on"},
479
{"+rv", "*reverseVideo",XrmoptionNoArg, (caddr_t) "off"},
480
{"-w", ".borderWidth", XrmoptionSepArg, (caddr_t) NULL},
483
static OptionHelp xtermOptions[] = {
484
{ "-version", "print the version number" },
485
{ "-help", "print out this message" },
486
{ "-display displayname", "X server to contact" },
487
{ "-geometry geom", "size (in characters) and position" },
488
{ "-/+rv", "turn on/off reverse video" },
489
{ "-bg color", "background color" },
490
{ "-fg color", "foreground color" },
491
{ "-bd color", "border color" },
492
{ "-bw number", "border width in pixels" },
493
{ "-fn fontname", "normal text font" },
494
{ "-fb fontname", "bold text font" },
495
{ "-/+fbb", "turn on/off normal/bold font comparison inhibit"},
496
{ "-/+fbx", "turn off/on linedrawing characters"},
498
{ "-fa pattern", "FreeType font-selection pattern" },
499
{ "-fs size", "FreeType font-size" },
502
{ "-fw fontname", "doublewidth text font" },
503
{ "-fwb fontname", "doublewidth bold text font" },
505
{ "-iconic", "start iconic" },
506
{ "-name string", "client instance, icon, and title strings" },
507
{ "-class string", "class string (XTerm)" },
508
{ "-title string", "title string" },
509
{ "-xrm resourcestring", "additional resource specifications" },
510
{ "-/+132", "turn on/off 80/132 column switching" },
511
{ "-/+ah", "turn on/off always highlight" },
512
#ifndef NO_ACTIVE_ICON
513
{ "-/+ai", "turn off/on active icon" },
514
{ "-fi fontname", "icon font for active icon" },
515
#endif /* NO_ACTIVE_ICON */
516
{ "-b number", "internal border in pixels" },
517
{ "-/+bc", "turn on/off text cursor blinking" },
518
{ "-bcf milliseconds", "time text cursor is off when blinking"},
519
{ "-bcn milliseconds", "time text cursor is on when blinking"},
520
{ "-/+bdc", "turn off/on display of bold as color"},
521
{ "-/+cb", "turn on/off cut-to-beginning-of-line inhibit" },
522
{ "-cc classrange", "specify additional character classes" },
523
{ "-/+cm", "turn off/on ANSI color mode" },
524
{ "-/+cn", "turn on/off cut newline inhibit" },
525
{ "-cr color", "text cursor color" },
526
{ "-/+cu", "turn on/off curses emulation" },
527
{ "-/+dc", "turn off/on dynamic color selection" },
528
#if OPT_HIGHLIGHT_COLOR
529
{ "-hc color", "selection background color" },
532
{ "-/+hf", "turn on/off HP Function Key escape codes" },
534
{ "-/+hold", "turn on/off logic that retains window after exit" },
535
{ "-/+im", "use insert mode for TERMCAP" },
536
{ "-/+j", "turn on/off jump scroll" },
538
{ "-/+l", "turn on/off logging" },
539
{ "-lf filename", "logging filename" },
541
{ "-/+l", "turn on/off logging (not supported)" },
542
{ "-lf filename", "logging filename (not supported)" },
544
{ "-/+ls", "turn on/off login shell" },
545
{ "-/+mb", "turn on/off margin bell" },
546
{ "-mc milliseconds", "multiclick time in milliseconds" },
547
{ "-/+mesg", "forbid/allow messages" },
548
{ "-ms color", "pointer color" },
549
{ "-nb number", "margin bell in characters from right end" },
550
{ "-/+nul", "turn off/on display of underlining" },
551
{ "-/+aw", "turn on/off auto wraparound" },
552
{ "-/+pc", "turn on/off PC-style bold colors" },
553
{ "-/+rw", "turn on/off reverse wraparound" },
554
{ "-/+s", "turn on/off multiscroll" },
555
{ "-/+sb", "turn on/off scrollbar" },
556
#ifdef SCROLLBAR_RIGHT
557
{ "-rightbar", "force scrollbar right (default left)" },
558
{ "-leftbar", "force scrollbar left" },
560
{ "-/+rvc", "turn off/on display of reverse as color" },
561
{ "-/+sf", "turn on/off Sun Function Key escape codes" },
562
{ "-/+si", "turn on/off scroll-on-tty-output inhibit" },
563
{ "-/+sk", "turn on/off scroll-on-keypress" },
564
{ "-sl number", "number of scrolled lines to save" },
566
{ "-/+sp", "turn on/off Sun/PC Function/Keypad mapping" },
569
{ "-/+t", "turn on/off Tek emulation window" },
571
{ "-ti termid", "terminal identifier" },
572
{ "-tm string", "terminal mode keywords and characters" },
573
{ "-tn name", "TERM environment variable name" },
575
{ "-/+u8", "turn on/off UTF-8 mode (implies wide-characters)" },
578
{ "-/+lc", "turn on/off locale mode using luit" },
579
{ "-lcc path", "filename of locale converter (" DEFLOCALEFILTER ")" },
581
{ "-/+ulc", "turn off/on display of underline as color" },
582
{ "-/+ut", "turn on/off utmp inhibit (not supported)" },
583
{ "-/+vb", "turn on/off visual bell" },
584
{ "-/+pob", "turn on/off pop on bell" },
586
{ "-/+wc", "turn on/off wide-character mode" },
587
{ "-/+cjk_width", "turn on/off legacy CJK width convention" },
589
{ "-/+wf", "turn on/off wait for map before command exec" },
590
{ "-e command args ...", "command to execute" },
592
{ "%geom", "Tek window geometry" },
594
{ "#geom", "icon window geometry" },
595
{ "-T string", "title name for window" },
596
{ "-n string", "icon name for window" },
597
{ "-C", "intercept console messages" },
598
{ "-Sccn", "slave mode on \"ttycc\", file descriptor \"n\"" },
599
{ "-into windowId", "use the window id given to -into as the parent window rather than the default root window" },
601
{ "-ziconbeep percent", "beep and flag icon of window having hidden output" },
604
{ "-/+samename", "turn on/off the no-flicker option for title and icon name" },
607
{ "-/+sm", "turn on/off the session-management support" },
612
/*debug FILE *confd;*/
613
/*static void opencons()
615
if ((confd=fopen("/dev/console$","w")) < 0) {
616
fputs("!!! Cannot open console device.\n",
622
static void closecons(void)
627
static char *message[] =
629
"Fonts should be fixed width and, if both normal and bold are specified, should",
630
"have the same size. If only a normal font is specified, it will be used for",
631
"both normal and bold text (by doing overstriking). The -e option, if given,",
632
"must appear at the end of the command line, otherwise the user's default shell",
633
"will be started. Options that start with a plus sign (+) restore the default.",
637
* Decode a key-definition. This combines the termcap and ttyModes, for
638
* comparison. Note that octal escapes in ttyModes are done by the normal
639
* resource translation. Also, ttyModes allows '^-' as a synonym for disabled.
642
decode_keyvalue(char **ptr, int termcap)
647
TRACE(("...decode '%s'\n", string));
648
if (*string == '^') {
656
#if defined(_POSIX_VDISABLE) && defined(HAVE_UNISTD_H)
657
value = _POSIX_VDISABLE;
659
#if defined(_PC_VDISABLE)
661
value = fpathconf(0, _PC_VDISABLE);
664
break; /* skip this (error) */
668
#elif defined(VDISABLE)
676
value = CONTROL(*string);
680
} else if (termcap && (*string == '\\')) {
682
int temp = strtol(string + 1, &d, 8);
683
if (temp > 0 && d != string) {
688
value = CharOf(*string);
696
* If we're linked to terminfo, tgetent() will return an empty buffer. We
697
* cannot use that to adjust the $TERMCAP variable.
700
get_termcap(char *name, char *buffer, char *resized)
702
register TScreen *screen = &term->screen;
704
*buffer = 0; /* initialize, in case we're using terminfo's tgetent */
707
if (tgetent(buffer, name) == 1) {
708
TRACE(("get_termcap(%s) succeeded (%s)\n", name,
710
? "ok:termcap, we can update $TERMCAP"
711
: "assuming this is terminfo")));
713
if (!TEK4014_ACTIVE(screen)) {
714
resize(screen, buffer, resized);
719
*buffer = 0; /* just in case */
726
abbrev(char *tst, char *cmp, size_t need)
728
size_t len = strlen(tst);
729
return ((len >= need) && (!strncmp(tst, cmp, len)));
733
Syntax(char *badOption)
736
OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList));
739
fprintf(stderr, "%s: bad command line option \"%s\"\r\n\n",
740
ProgramName, badOption);
742
fprintf(stderr, "usage: %s", ProgramName);
743
col = 8 + strlen(ProgramName);
744
for (opt = list; opt->opt; opt++) {
745
int len = 3 + strlen(opt->opt); /* space [ string ] */
746
if (col + len > 79) {
747
fprintf(stderr, "\r\n "); /* 3 spaces */
750
fprintf(stderr, " [%s]", opt->opt);
754
fprintf(stderr, "\r\n\nType %s -help for a full description.\r\n\n",
762
printf("%s(%d)\n", XFREE86_VERSION, XTERM_PATCH);
770
OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList));
774
"%s(%d) usage:\n %s [-options ...] [-e command args]\n\n",
775
XFREE86_VERSION, XTERM_PATCH, ProgramName);
776
fprintf(stderr, "where options include:\n");
777
for (opt = list; opt->opt; opt++) {
778
fprintf(stderr, " %-28s %s\n", opt->opt, opt->desc);
782
for (cpp = message; *cpp; cpp++) {
792
ConvertConsoleSelection(Widget w GCC_UNUSED,
793
Atom * selection GCC_UNUSED,
794
Atom * target GCC_UNUSED,
795
Atom * type GCC_UNUSED,
796
XtPointer * value GCC_UNUSED,
797
unsigned long *length GCC_UNUSED,
798
int *format GCC_UNUSED)
800
/* we don't save console output, so can't offer it */
806
die_callback(Widget w GCC_UNUSED,
807
XtPointer client_data GCC_UNUSED,
808
XtPointer call_data GCC_UNUSED)
814
save_callback(Widget w GCC_UNUSED,
815
XtPointer client_data GCC_UNUSED,
818
XtCheckpointToken token = (XtCheckpointToken) call_data;
819
/* we have nothing to save */
820
token->save_success = True;
822
#endif /* OPT_SESSION_MGT */
825
int (*my_wcwidth) (wchar_t);
829
* DeleteWindow(): Action proc to implement ICCCM delete_window.
833
DeleteWindow(Widget w,
834
XEvent * event GCC_UNUSED,
835
String * params GCC_UNUSED,
836
Cardinal * num_params GCC_UNUSED)
840
if (term->screen.Tshow)
843
do_hangup(w, (XtPointer) 0, (XtPointer) 0);
844
} else if (term->screen.Vshow)
848
do_hangup(w, (XtPointer) 0, (XtPointer) 0);
853
KeyboardMapping(Widget w GCC_UNUSED,
855
String * params GCC_UNUSED,
856
Cardinal * num_params GCC_UNUSED)
858
switch (event->type) {
860
XRefreshKeyboardMapping(&event->xmapping);
865
XtActionsRec actionProcs[] =
867
{"DeleteWindow", DeleteWindow},
868
{"KeyboardMapping", KeyboardMapping},
872
extern char **environ;
875
main(int argc, char **argv ENVP_ARG)
877
Widget form_top, menu_top;
878
register TScreen *screen;
880
char *my_class = DEFCLASS;
881
Window winToEmbedInto = None;
883
/* Do these first, since we may not be able to open the display */
884
ProgramName = argv[0];
885
TRACE_OPTS(xtermOptions, optionDescList, XtNumber(optionDescList));
886
TRACE_ARGV("Before XtOpenApplication", argv);
892
for (n = 1; n < argc; n++) {
893
TRACE(("parsing %s\n", argv[n]));
894
if (abbrev(argv[n], "-version", unique)) {
896
} else if (abbrev(argv[n], "-help", unique)) {
898
} else if (abbrev(argv[n], "-class", 3)) {
899
if ((my_class = argv[++n]) == 0) {
914
/* XXX: for some obscure reason EMX seems to lose the value of
915
* the environ variable, don't understand why, so save it recently
920
setlocale(LC_ALL, NULL);
923
/*debug opencons();*/
925
ttydev = (char *) malloc(PTMS_BUFSZ);
926
ptydev = (char *) malloc(PTMS_BUFSZ);
927
if (!ttydev || !ptydev) {
929
"%s: unable to allocate memory for ttydev or ptydev\n",
933
strcpy(ttydev, TTYDEV);
934
strcpy(ptydev, PTYDEV);
936
/* Initialization is done here rather than above in order
937
* to prevent any assumptions about the order of the contents
938
* of the various terminal structures (which may change from
939
* implementation to implementation).
941
d_tio.c_iflag = ICRNL | IXON;
942
d_tio.c_oflag = OPOST | ONLCR | TAB3;
943
d_tio.c_cflag = B38400 | CS8 | CREAD | PARENB | HUPCL;
944
d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
946
d_tio.c_cc[VINTR] = CONTROL('C'); /* '^C' */
947
d_tio.c_cc[VERASE] = 0x7f; /* DEL */
948
d_tio.c_cc[VKILL] = CONTROL('U'); /* '^U' */
949
d_tio.c_cc[VQUIT] = CQUIT; /* '^\' */
950
d_tio.c_cc[VEOF] = CEOF; /* '^D' */
951
d_tio.c_cc[VEOL] = CEOL; /* '^@' */
953
/* Init the Toolkit. */
954
XtSetErrorHandler(xt_error);
956
toplevel = XtOpenApplication(&app_con, my_class,
958
XtNumber(optionDescList),
959
&argc, argv, fallback_resources,
960
sessionShellWidgetClass,
963
toplevel = XtAppInitialize(&app_con, my_class,
965
XtNumber(optionDescList),
966
&argc, argv, fallback_resources,
968
#endif /* OPT_SESSION_MGT */
969
XtSetErrorHandler((XtErrorHandler) 0);
971
XtGetApplicationResources(toplevel, (XtPointer) & resource,
972
application_resources,
973
XtNumber(application_resources), NULL, 0);
975
waiting_for_initial_map = resource.wait_for_map;
978
* ICCCM delete_window.
980
XtAppAddActions(app_con, actionProcs, XtNumber(actionProcs));
983
* fill in terminal modes
985
if (resource.tty_modes) {
986
int n = parse_tty_modes(resource.tty_modes, ttymodelist);
988
fprintf(stderr, "%s: bad tty modes \"%s\"\n",
989
ProgramName, resource.tty_modes);
991
override_tty_modes = 1;
995
zIconBeep = resource.zIconBeep;
996
zIconBeep_flagged = False;
997
if (zIconBeep > 100 || zIconBeep < -100) {
998
zIconBeep = 0; /* was 100, but I prefer to defaulting off. */
1000
"a number between -100 and 100 is required for zIconBeep. 0 used by default\n");
1002
#endif /* OPT_ZICONBEEP */
1004
sameName = resource.sameName;
1006
hold_screen = resource.hold_screen ? 1 : 0;
1007
xterm_name = resource.xterm_name;
1008
if (strcmp(xterm_name, "-") == 0)
1009
xterm_name = DFT_TERMTYPE;
1010
if (resource.icon_geometry != NULL) {
1015
for (scr = 0; /* yyuucchh */
1016
XtScreen(toplevel) != ScreenOfDisplay(XtDisplay(toplevel), scr);
1019
args[0].name = XtNiconX;
1020
args[1].name = XtNiconY;
1021
XGeometry(XtDisplay(toplevel), scr, resource.icon_geometry, "",
1022
0, 0, 0, 0, 0, &ix, &iy, &junk, &junk);
1023
args[0].value = (XtArgVal) ix;
1024
args[1].value = (XtArgVal) iy;
1025
XtSetValues(toplevel, args, 2);
1028
XtSetValues(toplevel, ourTopLevelShellArgs,
1029
number_ourTopLevelShellArgs);
1032
/* seems as good a place as any */
1036
/* Parse the rest of the command line */
1037
TRACE_ARGV("After XtOpenApplication", argv);
1038
for (argc--, argv++; argc > 0; argc--, argv++) {
1042
TRACE(("parsing %s\n", argv[0]));
1043
switch (argv[0][1]) {
1044
case 'h': /* -help */
1047
case 'v': /* -version */
1054
/* Must be owner and have read/write permission.
1055
xdm cooperates to give the console the right user. */
1056
if (!stat("/dev/console", &sbuf) &&
1057
(sbuf.st_uid == getuid()) &&
1058
!access("/dev/console", R_OK | W_OK)) {
1065
if (sscanf(*argv + 2, "%c%c%d", passedPty, passedPty + 1,
1074
case 'c': /* -class param */
1075
if (strcmp(argv[0] + 1, "class") == 0)
1083
command_to_exec = ++argv;
1092
winToEmbedInto = (Window) strtol(argv[0], &endPtr, 10);
1102
SetupMenus(toplevel, &form_top, &menu_top);
1104
term = (XtermWidget) XtVaCreateManagedWidget("vt100", xtermWidgetClass,
1107
XtNmenuBar, menu_top,
1109
XtNfromVert, menu_top,
1110
XtNleft, XawChainLeft,
1111
XtNright, XawChainRight,
1112
XtNbottom, XawChainBottom,
1115
/* this causes the initialize method to be called */
1117
#if OPT_HP_FUNC_KEYS
1118
init_keyboard_type(keyboardIsHP, resource.hpFunctionKeys);
1120
init_keyboard_type(keyboardIsSun, resource.sunFunctionKeys);
1122
init_keyboard_type(keyboardIsVT220, resource.sunKeyboard);
1125
screen = &term->screen;
1129
if (term->misc.logInhibit)
1132
if (term->misc.signalInhibit)
1133
inhibit |= I_SIGNAL;
1135
if (term->misc.tekInhibit)
1140
my_wcwidth = &mk_wcwidth;
1141
if (term->misc.cjk_width)
1142
my_wcwidth = &mk_wcwidth_cjk;
1146
if (resource.sessionMgt) {
1147
TRACE(("Enabling session-management callbacks\n"));
1148
XtAddCallback(toplevel, XtNdieCallback, die_callback, NULL);
1149
XtAddCallback(toplevel, XtNsaveCallback, save_callback, NULL);
1154
* Set title and icon name if not specified
1156
if (command_to_exec) {
1159
if (!resource.title) {
1160
if (command_to_exec) {
1161
resource.title = x_basename(command_to_exec[0]);
1162
} /* else not reached */
1165
if (!resource.icon_name)
1166
resource.icon_name = resource.title;
1167
XtSetArg(args[0], XtNtitle, resource.title);
1168
XtSetArg(args[1], XtNiconName, resource.icon_name);
1170
TRACE(("setting:\n\ttitle \"%s\"\n\ticon \"%s\"\n\tbased on command \"%s\"\n",
1175
XtSetValues(toplevel, args, 2);
1178
if (term->misc.callfilter) {
1179
int u = (term->misc.use_encoding ? 2 : 0);
1180
if (command_to_exec) {
1183
for (n = 0, c = command_to_exec; *c; n++, c++) ;
1184
c = malloc((n + 3 + u) * sizeof(char *));
1186
SysError(ERROR_LUMALLOC);
1187
memcpy(c + 2 + u, command_to_exec, (n + 1) * sizeof(char *));
1188
c[0] = term->misc.localefilter;
1191
c[2] = term->misc.locale_str;
1194
command_to_exec_with_luit = c;
1196
static char *luit[4];
1197
luit[0] = term->misc.localefilter;
1199
luit[1] = "-encoding";
1200
luit[2] = term->misc.locale_str;
1204
command_to_exec_with_luit = luit;
1209
if (inhibit & I_TEK)
1210
screen->TekEmu = FALSE;
1212
if (screen->TekEmu && !TekInit())
1218
/* Set up stderr properly. Opening this log file cannot be
1219
done securely by a privileged xterm process (although we try),
1220
so the debug feature is disabled by default. */
1223
creat_as(getuid(), getgid(), True, "xterm.debug.log", 0666);
1224
i = open("xterm.debug.log", O_WRONLY | O_TRUNC);
1229
/* mark this file as close on exec */
1230
(void) fcntl(i, F_SETFD, 1);
1235
/* open a terminal for client */
1240
/* Child process is out there, let's catch its termination */
1241
(void) signal(SIGCHLD, reapchild);
1243
/* Realize procs have now been executed */
1245
if (am_slave >= 0) { /* Write window id so master end can read and use */
1249
sprintf(buf, "%lx\n", XtWindow(XtParent(CURRENT_EMU(screen))));
1250
write(screen->respond, buf, strlen(buf));
1253
screen->inhibit = inhibit;
1255
if (0 > (mode = fcntl(screen->respond, F_GETFL, 0)))
1256
SysError(ERROR_F_GETFL);
1259
if (fcntl(screen->respond, F_SETFL, mode))
1260
SysError(ERROR_F_SETFL);
1264
FD_ZERO(&Select_mask);
1265
FD_SET(screen->respond, &pty_mask);
1266
FD_SET(ConnectionNumber(screen->display), &X_mask);
1267
FD_SET(screen->respond, &Select_mask);
1268
FD_SET(ConnectionNumber(screen->display), &Select_mask);
1269
max_plus1 = ((screen->respond < ConnectionNumber(screen->display))
1270
? (1 + ConnectionNumber(screen->display))
1271
: (1 + screen->respond));
1275
printf("debugging on\n");
1277
XSetErrorHandler(xerror);
1278
XSetIOErrorHandler(xioerror);
1281
if (term->misc.log_on) {
1286
if (winToEmbedInto != None) {
1287
XtRealizeWidget(toplevel);
1289
* This should probably query the tree or check the attributes of
1290
* winToEmbedInto in order to verify that it exists, but I'm still not
1291
* certain what is the best way to do it -GPS
1293
XReparentWindow(XtDisplay(toplevel),
1295
winToEmbedInto, 0, 0);
1310
* Called from get_pty to iterate over likely pseudo terminals
1311
* we might allocate. Used on those systems that do not have
1312
* a functional interface for allocating a pty.
1313
* Returns 0 if found a pty, 1 if fails.
1316
pty_search(int *pty)
1318
char namebuf[PTMS_BUFSZ];
1320
/* ask the PTY manager */
1321
int fd = open("/dev/ptms$", 0);
1322
if (fd && ptioctl(fd, PTMS_GETPTY, namebuf) == 0) {
1323
strcpy(ttydev, namebuf);
1324
strcpy(ptydev, namebuf);
1325
*x_basename(ttydev) = 't';
1327
if ((*pty = open(ptydev, O_RDWR)) >= 0) {
1329
ptioctl(*pty, XTY_TRACE, 0);
1338
* This function opens up a pty master and stuffs its value into pty.
1340
* If it finds one, it returns a value of 0. If it does not find one,
1341
* it returns a value of !0. This routine is designed to be re-entrant,
1342
* so that if a pty master is found and later, we find that the slave
1343
* has problems, we can re-enter this function and get another one.
1348
return pty_search(pty);
1352
* sets up X and initializes the terminal structure except for term.buf.fildes.
1357
register TScreen *screen = &term->screen;
1359
screen->arrow = make_colored_cursor(XC_left_ptr,
1361
screen->mousecolorback);
1365
* The only difference in /etc/termcap between 4014 and 4015 is that
1366
* the latter has support for switching character sets. We support the
1367
* 4015 protocol, but ignore the character switches. Therefore, we
1368
* choose 4014 over 4015.
1370
* Features of the 4014 over the 4012: larger (19") screen, 12-bit
1371
* graphics addressing (compatible with 4012 10-bit addressing),
1372
* special point plot mode, incremental plot mode (not implemented in
1373
* later Tektronix terminals), and 4 character sizes.
1374
* All of these are supported by xterm.
1378
static char *tekterm[] =
1381
"tek4015", /* 4014 with APL character set support */
1382
"tek4012", /* 4010 with lower case */
1383
"tek4013", /* 4012 with APL character set support */
1384
"tek4010", /* small screen, upper-case only */
1390
/* The VT102 is a VT100 with the Advanced Video Option included standard.
1391
* It also adds Escape sequences for insert/delete character/line.
1392
* The VT220 adds 8-bit character sets, selective erase.
1393
* The VT320 adds a 25th status line, terminal state interrogation.
1394
* The VT420 has up to 48 lines on the screen.
1397
static char *vtterm[] =
1400
"x11term", /* for people who want special term name */
1402
DFT_TERMTYPE, /* for people who want special term name */
1403
"xterm", /* the prefered name, should be fastest */
1413
hungtty(int i GCC_UNUSED)
1428
first_map_occurred(void)
1430
register TScreen *screen = &term->screen;
1431
handshake.rows = screen->max_row;
1432
handshake.cols = screen->max_col;
1433
waiting_for_initial_map = False;
1437
set_owner(char *device, int uid, int gid, int mode)
1439
if (chown(device, uid, gid) < 0) {
1442
fprintf(stderr, "Cannot chown %s to %d,%d: %s\n",
1443
device, uid, gid, strerror(errno));
1446
chmod(device, mode);
1449
#define THE_PARENT 1
1458
signal(sig, killit);
1459
kill(-getpid(), sig);
1463
signal(SIGTERM, SIG_DFL);
1464
kill(-getpid(), SIGTERM);
1468
signal(SIGTERM, SIG_DFL);
1469
kill(-getppid(), SIGTERM);
1480
* Inits pty and tty and forks a login process.
1481
* Does not close fd Xsocket.
1482
* If slave, the pty named in passedPty is already open for use
1485
register TScreen *screen = &term->screen;
1486
int Xsocket = ConnectionNumber(screen->display);
1492
char termcap[TERMCAP_SIZE], newtc[TERMCAP_SIZE];
1493
char *TermName = NULL;
1494
char *ptr, *shname, buf[64];
1495
int i, no_dev_tty = FALSE, envsize;
1496
char *dev_tty_name = (char *) 0;
1498
int pgrp = getpid();
1499
char numbuf[12], **envnew;
1501
screen->uid = getuid();
1502
screen->gid = getgid();
1504
if (am_slave >= 0) {
1505
screen->respond = am_slave;
1506
ptydev[strlen(ptydev) - 2] =
1507
ttydev[strlen(ttydev) - 2] = passedPty[0];
1508
ptydev[strlen(ptydev) - 1] =
1509
ttydev[strlen(ttydev) - 1] = passedPty[1];
1511
setgid(screen->gid);
1512
setuid(screen->uid);
1517
* Sometimes /dev/tty hangs on open (as in the case of a pty
1518
* that has gone away). Simply make up some reasonable
1522
signal(SIGALRM, hungtty);
1523
alarm(2); /* alarm(1) might return too soon */
1525
tty = open("/dev/tty", O_RDWR);
1527
tty_got_hung = False;
1529
tty_got_hung = True;
1533
signal(SIGALRM, SIG_DFL);
1536
* Check results and ignore current control terminal if
1537
* necessary. ENXIO is what is normally returned if there is
1538
* no controlling terminal, but some systems (e.g. SunOS 4.0)
1539
* seem to return EIO. Solaris 2.3 is said to return EINVAL.
1542
if (tty_got_hung || errno == ENXIO || errno == EIO ||
1543
errno == EINVAL || errno == ENOTTY) {
1547
SysError(ERROR_OPDEVTTY);
1551
/* Get a copy of the current terminal's state,
1552
* if we can. Some systems (e.g., SVR4 and MacII)
1553
* may not have a controlling terminal at this point
1554
* if started directly from xdm or xinit,
1555
* in which case we just use the defaults as above.
1557
if (ioctl(tty, TCGETA, &tio) == -1)
1561
/* tty is no longer an open fd! */
1565
if (get_pty(&screen->respond)) {
1571
/* avoid double MapWindow requests */
1572
XtSetMappedWhenManaged(XtParent(CURRENT_EMU(screen)), False);
1574
wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW",
1577
if (!TEK4014_ACTIVE(screen))
1578
VTInit(); /* realize now so know window size for tty driver */
1582
* Inform any running xconsole program
1583
* that we are going to steal the console.
1585
XmuGetHostname(mit_console_name + MIT_CONSOLE_LEN, 255);
1586
mit_console = XInternAtom(screen->display, mit_console_name, False);
1587
/* the user told us to be the console, so we can use CurrentTime */
1588
XtOwnSelection(XtParent(CURRENT_EMU(screen)),
1589
mit_console, CurrentTime,
1590
ConvertConsoleSelection, NULL, NULL);
1593
if (screen->TekEmu) {
1604
* This used to exit if no termcap entry was found for the specified
1605
* terminal name. That's a little unfriendly, so instead we'll allow
1606
* the program to proceed (but not to set $TERMCAP) if the termcap
1607
* entry is not found.
1609
get_termcap(TermName = resource.term_name, ptr, newtc);
1612
* This block is invoked only if there was no terminal name specified
1613
* by the command-line option "-tn".
1617
while (*envnew != NULL) {
1618
if (get_termcap(*envnew, ptr, newtc)) {
1626
/* tell tty how big window is */
1628
if (TEK4014_ACTIVE(screen)) {
1631
ws.ws_xpixel = TFullWidth(screen);
1632
ws.ws_ypixel = TFullHeight(screen);
1636
ws.ws_row = screen->max_row + 1;
1637
ws.ws_col = screen->max_col + 1;
1638
ws.ws_xpixel = FullWidth(screen);
1639
ws.ws_ypixel = FullHeight(screen);
1646
/* start a child process
1647
* use an event sema for sync
1649
sprintf(sema, "\\SEM32\\xterm%s", &ptydev[8]);
1650
if (DosCreateEventSem(sema, &sev, DC_SEM_SHARED, FALSE))
1651
SysError(ERROR_FORK);
1653
switch ((screen->pid = fork())) {
1654
case -1: /* error */
1655
SysError(ERROR_FORK);
1656
default: /* parent */
1657
whoami = THE_PARENT;
1658
DosWaitEventSem(sev, 1000L);
1659
DosCloseEventSem(sev);
1664
/*debug fclose(confd);
1666
/* we don't need the socket, or the pty master anymore */
1667
close(ConnectionNumber(screen->display));
1668
close(screen->respond);
1670
/* Now is the time to set up our process group and
1671
* open up the pty slave.
1673
if ((tty = open(ttydev, O_RDWR)) < 0) {
1675
fprintf(stderr, "Cannot open slave side of PTY\n");
1679
/* use the same tty name that everyone else will use
1683
if ((ptr = ttyname(tty)) != 0) {
1684
/* it may be bigger */
1685
ttydev = realloc(ttydev,
1686
(unsigned) (strlen(ptr) + 1));
1687
if (ttydev == NULL) {
1688
SysError(ERROR_SPREALLOC);
1690
(void) strcpy(ttydev, ptr);
1695
/* for safety: enable DUPs */
1696
ptioctl(tty, XTY_ENADUP, 0);
1698
/* change ownership of tty to real group and user id */
1699
set_owner(ttydev, screen->uid, screen->gid,
1700
(resource.messages ? 0622 : 0600));
1702
/* for the xf86sup-pty, we set the pty to bypass: OS/2 does
1703
* not have a line discipline structure
1706
struct termio t, t1;
1707
if (ptioctl(tty, TCGETA, (char *) &t) < 0)
1711
t.c_oflag = OPOST | ONLCR;
1712
t.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
1714
/* ignore error code, user will see it :-) */
1715
ptioctl(tty, TCSETA, (char *) &t);
1717
/* set the console mode */
1720
if (ioctl(tty, TIOCCONS, (char *) &on) == -1)
1721
fprintf(stderr, "%s: cannot open console\n", xterm_name);
1725
signal(SIGCHLD, SIG_DFL);
1726
signal(SIGHUP, SIG_IGN);
1728
/* restore various signals to their defaults */
1729
signal(SIGINT, SIG_DFL);
1730
signal(SIGQUIT, SIG_DFL);
1731
signal(SIGTERM, SIG_DFL);
1733
/* copy the environment before Setenving */
1734
for (i = 0; gblenvp[i] != NULL; i++) ;
1736
/* compute number of xtermSetenv() calls below */
1737
envsize = 1; /* (NULL terminating entry) */
1738
envsize += 3; /* TERM, WINDOWID, DISPLAY */
1739
envsize += 2; /* COLUMNS, LINES */
1741
envnew = (char **) calloc((unsigned) i + envsize, sizeof(char *));
1742
memmove((char *) envnew, (char *) gblenvp, i * sizeof(char *));
1744
xtermSetenv("TERM=", TermName);
1749
((unsigned long) XtWindow(XtParent(CURRENT_EMU(screen)))));
1750
xtermSetenv("WINDOWID=", buf);
1752
/* put the display into the environment of the shell */
1753
xtermSetenv("DISPLAY=", XDisplayString(screen->display));
1755
signal(SIGTERM, SIG_DFL);
1757
/* this is the time to go and set up stdin, out, and err
1760
for (i = 0; i <= 2; i++)
1766
/* and close the tty */
1771
setgid(screen->gid);
1772
setuid(screen->uid);
1774
if (handshake.rows > 0 && handshake.cols > 0) {
1775
screen->max_row = handshake.rows;
1776
screen->max_col = handshake.cols;
1777
ws.ws_row = screen->max_row + 1;
1778
ws.ws_col = screen->max_col + 1;
1779
ws.ws_xpixel = FullWidth(screen);
1780
ws.ws_ypixel = FullHeight(screen);
1783
sprintf(numbuf, "%d", screen->max_col + 1);
1784
xtermSetenv("COLUMNS=", numbuf);
1785
sprintf(numbuf, "%d", screen->max_row + 1);
1786
xtermSetenv("LINES=", numbuf);
1788
/* reconstruct dead environ variable */
1791
/* need to reset after all the ioctl bashing we did above */
1792
ptioctl(0, TIOCSWINSZ, (char *) &ws);
1794
signal(SIGHUP, SIG_DFL);
1796
/* okay everything seems right, so tell the parent, we are going */
1800
sprintf(sema, "\\SEM32\\xterm%s", &ttydev[8]);
1801
DosOpenEventSem(sema, &sev);
1802
DosPostEventSem(sev);
1803
DosCloseEventSem(sev);
1808
* Use two copies of command_to_exec, in case luit is not actually
1809
* there, or refuses to run. In that case we will fall-through to
1810
* to command that the user gave anyway.
1812
if (command_to_exec_with_luit) {
1813
TRACE(("spawning command \"%s\"\n", *command_to_exec_with_luit));
1814
execvp(*command_to_exec_with_luit, command_to_exec_with_luit);
1815
/* print error message on screen */
1816
fprintf(stderr, "%s: Can't execvp %s: %s\n",
1817
xterm_name, *command_to_exec_with_luit, strerror(errno));
1818
fprintf(stderr, "%s: cannot support your locale.\n",
1822
if (command_to_exec) {
1823
TRACE(("spawning command \"%s\"\n", *command_to_exec));
1824
execvpe(*command_to_exec, command_to_exec, gblenvp);
1826
/* print error message on screen */
1827
fprintf(stderr, "%s: Can't execvp %s\n",
1828
xterm_name, *command_to_exec);
1831
/* use a layered mechanism to find a shell */
1832
ptr = getenv("X11SHELL");
1834
ptr = getenv("SHELL");
1836
ptr = getenv("OS2_SHELL");
1838
ptr = "SORRY_NO_SHELL_FOUND";
1840
shname = x_basename(ptr);
1841
if (command_to_exec) {
1842
char *exargv[10]; /*XXX */
1846
exargv[2] = command_to_exec[0];
1847
exargv[3] = command_to_exec[1];
1848
exargv[4] = command_to_exec[2];
1849
exargv[5] = command_to_exec[3];
1850
exargv[6] = command_to_exec[4];
1851
exargv[7] = command_to_exec[5];
1852
exargv[8] = command_to_exec[6];
1854
execvpe(exargv[0], exargv, gblenvp);
1856
execvpe(*command_to_exec, command_to_exec, gblenvp);
1858
/* print error message on screen */
1859
fprintf(stderr, "%s: Can't execvp %s\n",
1860
xterm_name, *command_to_exec);
1862
execlpe(ptr, shname, 0, gblenvp);
1865
fprintf(stderr, "%s: Could not exec %s!\n",
1870
/* preventively shoot the parent */
1871
kill(-getppid(), SIGTERM);
1877
signal(SIGHUP, SIG_IGN);
1879
* Unfortunately, System V seems to have trouble divorcing the child process
1880
* from the process group of xterm. This is a problem because hitting the
1881
* INTR or QUIT characters on the keyboard will cause xterm to go away if we
1882
* don't ignore the signals. This is annoying.
1885
/* signal (SIGINT, SIG_IGN);*/
1886
signal(SIGINT, killit);
1887
signal(SIGTERM, killit);
1889
/* hung shell problem */
1890
signal(SIGQUIT, SIG_IGN);
1891
/* signal (SIGTERM, SIG_IGN);*/
1898
register TScreen *screen = &term->screen;
1899
int pty = term->screen.respond; /* file descriptor of pty */
1900
close(pty); /* close explicitly to avoid race with slave side */
1902
if (screen->logging)
1906
/* restore ownership of tty and pty */
1907
set_owner(ttydev, 0, 0, 0666);
1908
set_owner(ptydev, 0, 0, 0666);
1916
resize(TScreen * screen, register char *oldtc, char *newtc)
1921
* Does a non-blocking wait for a child process. If the system
1922
* doesn't support non-blocking wait, do nothing.
1923
* Returns the pid of the child, or 0 or -1 if none or error.
1926
nonblocking_wait(void)
1930
pid = waitpid(-1, NULL, WNOHANG);
1936
reapchild(int n GCC_UNUSED)
1938
int olderrno = errno;
1943
/* cannot re-enable signal before waiting for child
1944
* because then SVR4 loops. Sigh. HP-UX 9.01 too.
1946
(void) signal(SIGCHLD, reapchild);
1949
if (pid == term->screen.pid) {
1952
fputs("Exiting\n", stderr);
1957
} while ((pid = nonblocking_wait()) > 0);
1964
* parse_tty_modes accepts lines of the following form:
1968
* where setting consists of the words in the modelist followed by a character
1972
parse_tty_modes(char *s, struct _xttymodes *modelist)
1974
struct _xttymodes *mp;
1978
TRACE(("parse_tty_modes\n"));
1980
while (*s && isascii(CharOf(*s)) && isspace(CharOf(*s)))
1985
for (mp = modelist; mp->name; mp++) {
1986
if (strncmp(s, mp->name, mp->len) == 0)
1993
while (*s && isascii(CharOf(*s)) && isspace(CharOf(*s)))
1998
if ((c = decode_keyvalue(&s, False)) != -1) {
2002
TRACE(("...parsed #%d: %s=%#x\n", count, mp->name, c));
2008
GetBytesAvailable(int fd)
2011
ioctl(fd, FIONREAD, (char *) &arg);
2015
/* Utility function to try to hide system differences from
2016
everybody who used to call killpg() */
2019
kill_process_group(int pid, int sig)
2021
return kill(-pid, sig);
2025
ptioctl(int fd, int func, void *data)
2029
struct pt_termios pt;
2035
rc = DosDevIOCtl(fd, XFREE86_PTY, func,
2037
(ULONG *) & pt, sizeof(struct pt_termios), &len);
2040
t = (struct termio *) data;
2041
t->c_iflag = pt.c_iflag;
2042
t->c_oflag = pt.c_oflag;
2043
t->c_cflag = pt.c_cflag;
2044
t->c_lflag = pt.c_lflag;
2045
for (i = 0; i < NCC; i++)
2046
t->c_cc[i] = pt.c_cc[i];
2051
t = (struct termio *) data;
2052
pt.c_iflag = t->c_iflag;
2053
pt.c_oflag = t->c_oflag;
2054
pt.c_cflag = t->c_cflag;
2055
pt.c_lflag = t->c_lflag;
2057
for (i = 0; i < NCC; i++)
2058
pt.c_cc[i] = t->c_cc[i];
2061
else if (func == TCSETAW)
2065
rc = DosDevIOCtl(fd, XFREE86_PTY, i,
2066
(ULONG *) & pt, sizeof(struct pt_termios), &len,
2068
return (rc) ? -1 : 0;
2070
return DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCCONS,
2071
(ULONG *) data, sizeof(ULONG), &len,
2074
return DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCSWINSZ,
2075
(ULONG *) data, sizeof(struct winsize), &len,
2078
return DosDevIOCtl(fd, XFREE86_PTY, XTY_TIOCGWINSZ,
2080
(ULONG *) data, sizeof(struct winsize), &len);
2083
return DosDevIOCtl(fd, XFREE86_PTY, XTY_ENADUP,
2084
(ULONG *) & i, sizeof(ULONG), &len,
2088
return DosDevIOCtl(fd, XFREE86_PTY, XTY_TRACE,
2089
(ULONG *) & i, sizeof(ULONG), &len,
2093
return DosDevIOCtl(fd, XFREE86_PTY, PTMS_GETPTY,
2094
(ULONG *) & i, sizeof(ULONG), &len,
2095
(UCHAR *) data, 14, &len);