home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xterm / main.c.orig < prev    next >
Encoding:
Text File  |  1993-07-21  |  77.7 KB  |  2,926 lines

  1. #ifndef lint
  2. static char *rid="$XConsortium: main.c,v 1.199 91/12/23 17:02:24 gildea Exp $";
  3. #endif /* lint */
  4.  
  5. /*
  6.  *                  W A R N I N G
  7.  * 
  8.  * If you think you know what all of this code is doing, you are
  9.  * probably very mistaken.  There be serious and nasty dragons here.
  10.  *
  11.  * This client is *not* to be taken as an example of how to write X
  12.  * Toolkit applications.  It is in need of a substantial rewrite,
  13.  * ideally to create a generic tty widget with several different parsing
  14.  * widgets so that you can plug 'em together any way you want.  Don't
  15.  * hold your breath, though....
  16.  */
  17.  
  18. /***********************************************************
  19. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard,
  20. Massachusetts, and the Massachusetts Institute of Technology,
  21. Cambridge, Massachusetts.
  22.  
  23.                         All Rights Reserved
  24.  
  25. Permission to use, copy, modify, and distribute this software and its 
  26. documentation for any purpose and without fee is hereby granted, 
  27. provided that the above copyright notice appear in all copies and that
  28. both that copyright notice and this permission notice appear in 
  29. supporting documentation, and that the names of Digital or MIT not be
  30. used in advertising or publicity pertaining to distribution of the
  31. software without specific, written prior permission.  
  32.  
  33. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  34. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  35. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  36. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  37. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  38. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  39. SOFTWARE.
  40.  
  41. ******************************************************************/
  42.  
  43.  
  44. /* main.c */
  45.  
  46. #include "ptyx.h"
  47. #include "data.h"
  48. #include "error.h"
  49. #include "menu.h"
  50. #include <X11/StringDefs.h>
  51. #include <X11/Shell.h>
  52.  
  53. #include <X11/Xos.h>
  54. #include <X11/cursorfont.h>
  55. #include <X11/Xaw/SimpleMenu.h>
  56. #include <pwd.h>
  57. #include <ctype.h>
  58.  
  59. #ifdef att
  60. #define ATT
  61. #endif
  62.  
  63. #ifdef SVR4
  64. #define SYSV            /* SVR4 is (approx) superset of SVR3 */
  65. #define USE_SYSV_UTMP
  66. #define ATT
  67. #define USE_TERMIOS
  68. #endif
  69.   
  70. #ifdef SYSV386
  71. #define USE_SYSV_UTMP
  72. #define ATT
  73. #define USE_HANDSHAKE
  74. static Bool IsPts = False;
  75. #endif
  76.  
  77. #ifdef ATT
  78. #define USE_USG_PTYS
  79. #else
  80. #define USE_HANDSHAKE
  81. #endif
  82.  
  83. #if defined(SYSV) && !defined(SVR4)
  84. /* older SYSV systems cannot ignore SIGHUP.
  85.    Shell hangs, or you get extra shells, or something like that */
  86. #define USE_SYSV_SIGHUP
  87. #endif
  88.  
  89. #if defined(sony) && defined(bsd43) && !defined(KANJI)
  90. #define KANJI
  91. #endif
  92. #include <sys/ioctl.h>
  93. #include <sys/stat.h>
  94.  
  95. #ifdef USE_TERMIOS
  96. #include <termios.h>
  97. /* this hacked termios support only works on SYSV */
  98. #define USE_SYSV_TERMIO
  99. #define termio termios
  100. #undef TCGETA
  101. #define TCGETA TCGETS
  102. #undef TCSETA
  103. #define TCSETA TCSETS
  104. #else /* USE_TERMIOS */
  105. #ifdef SYSV
  106. #include <sys/termio.h>
  107. #endif /* SYSV */
  108. #endif /* USE_TERMIOS else */
  109.  
  110. #ifdef SVR4
  111. #undef TIOCSLTC                /* defined, but not useable */
  112. #endif
  113.  
  114. #ifdef SYSV
  115. #ifdef USE_USG_PTYS            /* AT&T SYSV has no ptyio.h */
  116. #include <sys/stream.h>            /* get typedef used in ptem.h */
  117. #include <sys/ptem.h>            /* get struct winsize */
  118. #include <sys/stropts.h>        /* for I_PUSH */
  119. #include <poll.h>            /* for POLLIN */
  120. #endif /* USE_USG_PTYS */
  121. #define USE_SYSV_TERMIO
  122. #define USE_SYSV_SIGNALS
  123. #define    USE_SYSV_PGRP
  124. #define USE_SYSV_ENVVARS        /* COLUMNS/LINES vs. TERMCAP */
  125. /*
  126.  * now get system-specific includes
  127.  */
  128. #ifdef CRAY
  129. #define USE_SYSV_UTMP
  130. #define HAS_UTMP_UT_HOST
  131. #define HAS_BSD_GROUPS
  132. #endif
  133. #ifdef macII
  134. #define HAS_UTMP_UT_HOST
  135. #define HAS_BSD_GROUPS
  136. #include <sys/ttychars.h>
  137. #undef USE_SYSV_ENVVARS
  138. #undef FIOCLEX
  139. #undef FIONCLEX
  140. #define setpgrp2 setpgrp
  141. #include <sgtty.h>
  142. #include <sys/resource.h>
  143. #endif
  144. #ifdef hpux
  145. #define HAS_BSD_GROUPS
  146. #include <sys/ptyio.h>
  147. #endif /* hpux */
  148. #ifdef sgi
  149. #include <sys/sysmacros.h>
  150. #endif /* sgi */
  151. #endif /* SYSV */
  152.  
  153. #ifndef SYSV                /* BSD systems */
  154. #include <sgtty.h>
  155. #include <sys/resource.h>
  156. #define HAS_UTMP_UT_HOST
  157. #define HAS_BSD_GROUPS
  158. #endif    /* !SYSV */
  159.  
  160. #ifdef _POSIX_SOURCE
  161. #define USE_POSIX_WAIT
  162. #endif
  163. #ifdef SVR4
  164. #define USE_POSIX_WAIT
  165. #endif
  166.  
  167. #include <stdio.h>
  168. #include <errno.h>
  169. #include <setjmp.h>
  170.  
  171. #ifdef hpux
  172. #include <sys/utsname.h>
  173. #endif /* hpux */
  174.  
  175. #ifdef apollo
  176. #define ttyslot() 1
  177. #endif /* apollo */
  178.  
  179. #include <utmp.h>
  180. #ifdef LASTLOG
  181. #include <lastlog.h>
  182. #endif
  183. #include <sys/param.h>    /* for NOFILE */
  184.  
  185. #ifdef  PUCC_PTYD
  186. #include <local/openpty.h>
  187. int    Ptyfd;
  188. #endif /* PUCC_PTYD */
  189.  
  190. #ifdef sequent
  191. #define USE_GET_PSEUDOTTY
  192. #endif
  193.  
  194. #ifndef UTMP_FILENAME
  195. #define UTMP_FILENAME "/etc/utmp"
  196. #endif
  197. #ifndef LASTLOG_FILENAME
  198. #define LASTLOG_FILENAME "/usr/adm/lastlog"  /* only on BSD systems */
  199. #endif
  200. #ifndef WTMP_FILENAME
  201. #if defined(SYSV)
  202. #define WTMP_FILENAME "/etc/wtmp"
  203. #else
  204. #define WTMP_FILENAME "/usr/adm/wtmp"
  205. #endif
  206. #endif
  207.  
  208. #include <signal.h>
  209.  
  210. #if defined(SCO) || defined(ISC)
  211. #undef SIGTSTP            /* defined, but not the BSD way */
  212. #endif
  213.  
  214. #ifdef SIGTSTP
  215. #include <sys/wait.h>
  216. #ifdef hpux
  217. #include <sys/bsdtty.h>
  218. #endif
  219. #endif
  220.  
  221. #ifdef SIGNALRETURNSINT
  222. #define SIGNAL_T int
  223. #define SIGNAL_RETURN return 0
  224. #else
  225. #define SIGNAL_T void
  226. #define SIGNAL_RETURN return
  227. #endif
  228.  
  229. SIGNAL_T Exit();
  230.  
  231. #ifndef X_NOT_POSIX
  232. #include <unistd.h>
  233. #else
  234. extern long lseek();
  235. #ifdef USG
  236. extern unsigned sleep();
  237. #else
  238. extern void sleep();
  239. #endif
  240. #endif
  241.  
  242. #ifndef X_NOT_STDC_ENV
  243. #include <stdlib.h>
  244. #else
  245. extern char *malloc();
  246. extern char *calloc();
  247. extern char *realloc();
  248. extern char *getenv();
  249. extern void exit();
  250. #endif
  251. #ifdef X_NOT_POSIX
  252. extern char *ttyname();
  253. #endif
  254. #if defined(macII) && !defined(__STDC__)  /* stdlib.h fails to define these */
  255. char *malloc(), *realloc(), *calloc();
  256. char *ttyname(); /* and we don't get this from unistd.h */
  257. #endif /* macII */
  258.  
  259. #ifdef SYSV
  260. extern char *ptsname();
  261. #endif
  262.  
  263. extern char *strindex ();
  264. extern void HandlePopupMenu();
  265.  
  266. int switchfb[] = {0, 2, 1, 3};
  267.  
  268. static SIGNAL_T reapchild ();
  269.  
  270. static Bool added_utmp_entry = False;
  271.  
  272. static char **command_to_exec;
  273.  
  274. #ifdef USE_SYSV_TERMIO
  275. /* The following structures are initialized in main() in order
  276. ** to eliminate any assumptions about the internal order of their
  277. ** contents.
  278. */
  279. static struct termio d_tio;
  280. #ifdef TIOCSLTC
  281. static struct ltchars d_ltc;
  282. #endif    /* TIOCSLTC */
  283. #ifdef TIOCLSET
  284. static unsigned int d_lmode;
  285. #endif    /* TIOCLSET */
  286. #else /* not USE_SYSV_TERMIO */
  287. static struct  sgttyb d_sg = {
  288.         0, 0, 0177, CKILL, EVENP|ODDP|ECHO|XTABS|CRMOD
  289. };
  290. static struct  tchars d_tc = {
  291.         CINTR, CQUIT, CSTART,
  292.         CSTOP, CEOF, CBRK,
  293. };
  294. static struct  ltchars d_ltc = {
  295.         CSUSP, CDSUSP, CRPRNT,
  296.         CFLUSH, CWERASE, CLNEXT
  297. };
  298. static int d_disipline = NTTYDISC;
  299. static long int d_lmode = LCRTBS|LCRTERA|LCRTKIL|LCTLECH;
  300. #ifdef sony
  301. static long int d_jmode = KM_SYSSJIS|KM_ASCII;
  302. static struct jtchars d_jtc = {
  303.     'J', 'B'
  304. };
  305. #endif /* sony */
  306. #endif /* USE_SYSV_TERMIO */
  307.  
  308. static int parse_tty_modes ();
  309. /*
  310.  * SYSV has the termio.c_cc[V] and ltchars; BSD has tchars and ltchars;
  311.  * SVR4 has only termio.c_cc, but it includes everything from ltchars.
  312.  */
  313. static int override_tty_modes = 0;
  314. struct _xttymodes {
  315.     char *name;
  316.     int len;
  317.     int set;
  318.     char value;
  319. } ttymodelist[] = {
  320. { "intr", 4, 0, '\0' },            /* tchars.t_intrc ; VINTR */
  321. #define XTTYMODE_intr 0
  322. { "quit", 4, 0, '\0' },            /* tchars.t_quitc ; VQUIT */
  323. #define XTTYMODE_quit 1
  324. { "erase", 5, 0, '\0' },        /* sgttyb.sg_erase ; VERASE */
  325. #define XTTYMODE_erase 2
  326. { "kill", 4, 0, '\0' },            /* sgttyb.sg_kill ; VKILL */
  327. #define XTTYMODE_kill 3
  328. { "eof", 3, 0, '\0' },            /* tchars.t_eofc ; VEOF */
  329. #define XTTYMODE_eof 4
  330. { "eol", 3, 0, '\0' },            /* VEOL */
  331. #define XTTYMODE_eol 5
  332. { "swtch", 5, 0, '\0' },        /* VSWTCH */
  333. #define XTTYMODE_swtch 6
  334. { "start", 5, 0, '\0' },        /* tchars.t_startc */
  335. #define XTTYMODE_start 7
  336. { "stop", 4, 0, '\0' },            /* tchars.t_stopc */
  337. #define XTTYMODE_stop 8
  338. { "brk", 3, 0, '\0' },            /* tchars.t_brkc */
  339. #define XTTYMODE_brk 9
  340. { "susp", 4, 0, '\0' },            /* ltchars.t_suspc ; VSUSP */
  341. #define XTTYMODE_susp 10
  342. { "dsusp", 5, 0, '\0' },        /* ltchars.t_dsuspc ; VDSUSP */
  343. #define XTTYMODE_dsusp 11
  344. { "rprnt", 5, 0, '\0' },        /* ltchars.t_rprntc ; VREPRINT */
  345. #define XTTYMODE_rprnt 12
  346. { "flush", 5, 0, '\0' },        /* ltchars.t_flushc ; VDISCARD */
  347. #define XTTYMODE_flush 13
  348. { "weras", 5, 0, '\0' },        /* ltchars.t_werasc ; VWERASE */
  349. #define XTTYMODE_weras 14
  350. { "lnext", 5, 0, '\0' },        /* ltchars.t_lnextc ; VLNEXT */
  351. #define XTTYMODE_lnext 15
  352. { NULL, 0, 0, '\0' },            /* end of data */
  353. };
  354.  
  355. #ifdef USE_SYSV_UTMP
  356. #ifndef SVR4            /* otherwise declared in utmp.h */
  357. extern struct utmp *getutent();
  358. extern struct utmp *getutid();
  359. extern struct utmp *getutline();
  360. extern void pututline();
  361. extern void setutent();
  362. extern void endutent();
  363. extern void utmpname();
  364. #endif /* !SVR4 */
  365.  
  366. #ifndef SYSV386            /* could remove paragraph unconditionally? */
  367. extern struct passwd *getpwent();
  368. extern struct passwd *getpwuid();
  369. extern struct passwd *getpwnam();
  370. extern void setpwent();
  371. extern void endpwent();
  372. #endif
  373.  
  374. extern struct passwd *fgetpwent();
  375. #else    /* not USE_SYSV_UTMP */
  376. static char etc_utmp[] = UTMP_FILENAME;
  377. #ifdef LASTLOG
  378. static char etc_lastlog[] = LASTLOG_FILENAME;
  379. #endif 
  380. #endif    /* USE_SYSV_UTMP */
  381.  
  382. #ifdef WTMP
  383. static char etc_wtmp[] = WTMP_FILENAME;
  384. #endif
  385.  
  386. /*
  387.  * Some people with 4.3bsd /bin/login seem to like to use login -p -f user
  388.  * to implement xterm -ls.  They can turn on USE_LOGIN_DASH_P and turn off
  389.  * WTMP and LASTLOG.
  390.  */
  391. #ifdef USE_LOGIN_DASH_P
  392. #ifndef LOGIN_FILENAME
  393. #define LOGIN_FILENAME "/bin/login"
  394. #endif
  395. static char bin_login[] = LOGIN_FILENAME;
  396. #endif
  397.  
  398. static int inhibit;
  399. static char passedPty[2];    /* name if pty if slave */
  400.  
  401. #ifdef TIOCCONS
  402. static int Console;
  403. #include <X11/Xmu/SysUtil.h>    /* XmuGetHostname */
  404. #define MIT_CONSOLE_LEN    12
  405. #define MIT_CONSOLE "MIT_CONSOLE_"
  406. static char mit_console_name[255 + MIT_CONSOLE_LEN + 1] = MIT_CONSOLE;
  407. static Atom mit_console;
  408. #endif    /* TIOCCONS */
  409.  
  410. #ifndef USE_SYSV_UTMP
  411. static int tslot;
  412. #endif    /* USE_SYSV_UTMP */
  413. static jmp_buf env;
  414.  
  415. char *ProgramName;
  416. Boolean sunFunctionKeys;
  417.  
  418. static struct _resource {
  419.     char *xterm_name;
  420.     char *icon_geometry;
  421.     char *title;
  422.     char *icon_name;
  423.     char *term_name;
  424.     char *tty_modes;
  425.     Boolean utmpInhibit;
  426.     Boolean sunFunctionKeys;    /* %%% should be widget resource? */
  427.     Boolean wait_for_map;
  428.     Boolean useInsertMode;
  429. } resource;
  430.  
  431. /* used by VT (charproc.c) */
  432.  
  433. #define offset(field)    XtOffsetOf(struct _resource, field)
  434.  
  435. static XtResource application_resources[] = {
  436.     {"name", "Name", XtRString, sizeof(char *),
  437.     offset(xterm_name), XtRString, "xterm"},
  438.     {"iconGeometry", "IconGeometry", XtRString, sizeof(char *),
  439.     offset(icon_geometry), XtRString, (caddr_t) NULL},
  440.     {XtNtitle, XtCTitle, XtRString, sizeof(char *),
  441.     offset(title), XtRString, (caddr_t) NULL},
  442.     {XtNiconName, XtCIconName, XtRString, sizeof(char *),
  443.     offset(icon_name), XtRString, (caddr_t) NULL},
  444.     {"termName", "TermName", XtRString, sizeof(char *),
  445.     offset(term_name), XtRString, (caddr_t) NULL},
  446.     {"ttyModes", "TtyModes", XtRString, sizeof(char *),
  447.     offset(tty_modes), XtRString, (caddr_t) NULL},
  448.     {"utmpInhibit", "UtmpInhibit", XtRBoolean, sizeof (Boolean),
  449.     offset(utmpInhibit), XtRString, "false"},
  450.     {"sunFunctionKeys", "SunFunctionKeys", XtRBoolean, sizeof (Boolean),
  451.     offset(sunFunctionKeys), XtRString, "false"},
  452.     {"waitForMap", "WaitForMap", XtRBoolean, sizeof (Boolean),
  453.         offset(wait_for_map), XtRString, "false"},
  454.     {"useInsertMode", "UseInsertMode", XtRBoolean, sizeof (Boolean),
  455.         offset(useInsertMode), XtRString, "false"},
  456. };
  457. #undef offset
  458.  
  459. static char *fallback_resources[] = {
  460.     "XTerm*SimpleMenu*menuLabel.vertSpace: 100",
  461.     "XTerm*SimpleMenu*HorizontalMargins: 16",
  462.     "XTerm*SimpleMenu*Sme.height: 16",
  463.     "XTerm*SimpleMenu*Cursor: left_ptr",
  464.     "XTerm*mainMenu.Label:  Main Options (no app-defaults)",
  465.     "XTerm*vtMenu.Label:  VT Options (no app-defaults)",
  466.     "XTerm*fontMenu.Label:  VT Fonts (no app-defaults)",
  467.     "XTerm*tekMenu.Label:  Tek Options (no app-defaults)",
  468.     NULL
  469. };
  470.  
  471. /* Command line options table.  Only resources are entered here...there is a
  472.    pass over the remaining options after XrmParseCommand is let loose. */
  473.  
  474. static XrmOptionDescRec optionDescList[] = {
  475. {"-geometry",    "*vt100.geometry",XrmoptionSepArg,    (caddr_t) NULL},
  476. {"-132",    "*c132",    XrmoptionNoArg,        (caddr_t) "on"},
  477. {"+132",    "*c132",    XrmoptionNoArg,        (caddr_t) "off"},
  478. {"-ah",        "*alwaysHighlight", XrmoptionNoArg,    (caddr_t) "on"},
  479. {"+ah",        "*alwaysHighlight", XrmoptionNoArg,    (caddr_t) "off"},
  480. {"-b",        "*internalBorder",XrmoptionSepArg,    (caddr_t) NULL},
  481. {"-cb",        "*cutToBeginningOfLine", XrmoptionNoArg, (caddr_t) "off"},
  482. {"+cb",        "*cutToBeginningOfLine", XrmoptionNoArg, (caddr_t) "on"},
  483. {"-cc",        "*charClass",    XrmoptionSepArg,    (caddr_t) NULL},
  484. {"-cn",        "*cutNewline",    XrmoptionNoArg,        (caddr_t) "off"},
  485. {"+cn",        "*cutNewline",    XrmoptionNoArg,        (caddr_t) "on"},
  486. {"-cr",        "*cursorColor",    XrmoptionSepArg,    (caddr_t) NULL},
  487. {"-cu",        "*curses",    XrmoptionNoArg,        (caddr_t) "on"},
  488. {"+cu",        "*curses",    XrmoptionNoArg,        (caddr_t) "off"},
  489. {"-e",        NULL,        XrmoptionSkipLine,    (caddr_t) NULL},
  490. {"-fb",        "*boldFont",    XrmoptionSepArg,    (caddr_t) NULL},
  491. {"-j",        "*jumpScroll",    XrmoptionNoArg,        (caddr_t) "on"},
  492. {"+j",        "*jumpScroll",    XrmoptionNoArg,        (caddr_t) "off"},
  493. {"-l",        "*logging",    XrmoptionNoArg,        (caddr_t) "on"},
  494. {"+l",        "*logging",    XrmoptionNoArg,        (caddr_t) "off"},
  495. {"-lf",        "*logFile",    XrmoptionSepArg,    (caddr_t) NULL},
  496. {"-ls",        "*loginShell",    XrmoptionNoArg,        (caddr_t) "on"},
  497. {"+ls",        "*loginShell",    XrmoptionNoArg,        (caddr_t) "off"},
  498. {"-mb",        "*marginBell",    XrmoptionNoArg,        (caddr_t) "on"},
  499. {"+mb",        "*marginBell",    XrmoptionNoArg,        (caddr_t) "off"},
  500. {"-mc",        "*multiClickTime", XrmoptionSepArg,    (caddr_t) NULL},
  501. {"-ms",        "*pointerColor",XrmoptionSepArg,    (caddr_t) NULL},
  502. {"-nb",        "*nMarginBell",    XrmoptionSepArg,    (caddr_t) NULL},
  503. {"-rw",        "*reverseWrap",    XrmoptionNoArg,        (caddr_t) "on"},
  504. {"+rw",        "*reverseWrap",    XrmoptionNoArg,        (caddr_t) "off"},
  505. {"-aw",        "*autoWrap",    XrmoptionNoArg,        (caddr_t) "on"},
  506. {"+aw",        "*autoWrap",    XrmoptionNoArg,        (caddr_t) "off"},
  507. {"-s",        "*multiScroll",    XrmoptionNoArg,        (caddr_t) "on"},
  508. {"+s",        "*multiScroll",    XrmoptionNoArg,        (caddr_t) "off"},
  509. {"-sb",        "*scrollBar",    XrmoptionNoArg,        (caddr_t) "on"},
  510. {"+sb",        "*scrollBar",    XrmoptionNoArg,        (caddr_t) "off"},
  511. {"-sf",        "*sunFunctionKeys", XrmoptionNoArg,    (caddr_t) "on"},
  512. {"+sf",        "*sunFunctionKeys", XrmoptionNoArg,    (caddr_t) "off"},
  513. {"-si",        "*scrollTtyOutput",    XrmoptionNoArg,        (caddr_t) "off"},
  514. {"+si",        "*scrollTtyOutput",    XrmoptionNoArg,        (caddr_t) "on"},
  515. {"-sk",        "*scrollKey",    XrmoptionNoArg,        (caddr_t) "on"},
  516. {"+sk",        "*scrollKey",    XrmoptionNoArg,        (caddr_t) "off"},
  517. {"-sl",        "*saveLines",    XrmoptionSepArg,    (caddr_t) NULL},
  518. {"-t",        "*tekStartup",    XrmoptionNoArg,        (caddr_t) "on"},
  519. {"+t",        "*tekStartup",    XrmoptionNoArg,        (caddr_t) "off"},
  520. {"-tm",        "*ttyModes",    XrmoptionSepArg,    (caddr_t) NULL},
  521. {"-tn",        "*termName",    XrmoptionSepArg,    (caddr_t) NULL},
  522. {"-ut",        "*utmpInhibit",    XrmoptionNoArg,        (caddr_t) "on"},
  523. {"+ut",        "*utmpInhibit",    XrmoptionNoArg,        (caddr_t) "off"},
  524. {"-im",        "*useInsertMode", XrmoptionNoArg,    (caddr_t) "on"},
  525. {"+im",        "*useInsertMode", XrmoptionNoArg,    (caddr_t) "off"},
  526. {"-vb",        "*visualBell",    XrmoptionNoArg,        (caddr_t) "on"},
  527. {"+vb",        "*visualBell",    XrmoptionNoArg,        (caddr_t) "off"},
  528. {"-wf",        "*waitForMap",    XrmoptionNoArg,        (caddr_t) "on"},
  529. {"+wf",        "*waitForMap",    XrmoptionNoArg,        (caddr_t) "off"},
  530. /* bogus old compatibility stuff for which there are
  531.    standard XtAppInitialize options now */
  532. {"%",        "*tekGeometry",    XrmoptionStickyArg,    (caddr_t) NULL},
  533. {"#",        ".iconGeometry",XrmoptionStickyArg,    (caddr_t) NULL},
  534. {"-T",        "*title",    XrmoptionSepArg,    (caddr_t) NULL},
  535. {"-n",        "*iconName",    XrmoptionSepArg,    (caddr_t) NULL},
  536. {"-r",        "*reverseVideo",XrmoptionNoArg,        (caddr_t) "on"},
  537. {"+r",        "*reverseVideo",XrmoptionNoArg,        (caddr_t) "off"},
  538. {"-rv",        "*reverseVideo",XrmoptionNoArg,        (caddr_t) "on"},
  539. {"+rv",        "*reverseVideo",XrmoptionNoArg,        (caddr_t) "off"},
  540. {"-w",        ".borderWidth", XrmoptionSepArg,    (caddr_t) NULL},
  541. };
  542.  
  543. static struct _options {
  544.   char *opt;
  545.   char *desc;
  546. } options[] = {
  547. { "-help",                 "print out this message" },
  548. { "-display displayname",  "X server to contact" },
  549. { "-geometry geom",        "size (in characters) and position" },
  550. { "-/+rv",                 "turn on/off reverse video" },
  551. { "-bg color",             "background color" },
  552. { "-fg color",             "foreground color" },
  553. { "-bd color",             "border color" },
  554. { "-bw number",            "border width in pixels" },
  555. { "-fn fontname",          "normal text font" },
  556. { "-iconic",               "start iconic" },
  557. { "-name string",          "client instance, icon, and title strings" },
  558. { "-title string",         "title string" },
  559. { "-xrm resourcestring",   "additional resource specifications" },
  560. { "-/+132",                "turn on/off column switch inhibiting" },
  561. { "-/+ah",                 "turn on/off always highlight" },
  562. { "-b number",             "internal border in pixels" },
  563. { "-/+cb",                 "turn on/off cut-to-beginning-of-line inhibit" },
  564. { "-cc classrange",        "specify additional character classes" },
  565. { "-/+cn",                 "turn on/off cut newline inhibit" },
  566. { "-cr color",             "text cursor color" },
  567. { "-/+cu",                 "turn on/off curses emulation" },
  568. { "-fb fontname",          "bold text font" },
  569. { "-/+im",           "use insert mode for TERMCAP" },
  570. { "-/+j",                  "turn on/off jump scroll" },
  571. { "-/+l",                  "turn on/off logging" },
  572. { "-lf filename",          "logging filename" },
  573. { "-/+ls",                 "turn on/off login shell" },
  574. { "-/+mb",                 "turn on/off margin bell" },
  575. { "-mc milliseconds",      "multiclick time in milliseconds" },
  576. { "-ms color",             "pointer color" },
  577. { "-nb number",            "margin bell in characters from right end" },
  578. { "-/+aw",                 "turn on/off auto wraparound" },
  579. { "-/+rw",                 "turn on/off reverse wraparound" },
  580. { "-/+s",                  "turn on/off multiscroll" },
  581. { "-/+sb",                 "turn on/off scrollbar" },
  582. { "-/+sf",                 "turn on/off Sun Function Key escape codes" },
  583. { "-/+si",                 "turn on/off scroll-on-tty-output inhibit" },
  584. { "-/+sk",                 "turn on/off scroll-on-keypress" },
  585. { "-sl number",            "number of scrolled lines to save" },
  586. { "-/+t",                  "turn on/off Tek emulation window" },
  587. { "-tm string",            "terminal mode keywords and characters" },
  588. { "-tn name",              "TERM environment variable name" },
  589. #ifdef UTMP
  590. { "-/+ut",                 "turn on/off utmp inhibit" },
  591. #else
  592. { "-/+ut",                 "turn on/off utmp inhibit (not supported)" },
  593. #endif
  594. { "-/+vb",                 "turn on/off visual bell" },
  595. { "-/+wf",                 "turn on/off wait for map before command exec" },
  596. { "-e command args ...",   "command to execute" },
  597. { "%geom",                 "Tek window geometry" },
  598. { "#geom",                 "icon window geometry" },
  599. { "-T string",             "title name for window" },
  600. { "-n string",             "icon name for window" },
  601. #ifdef TIOCCONS
  602. { "-C",                    "intercept console messages" },
  603. #else
  604. { "-C",                    "intercept console messages (not supported)" },
  605. #endif
  606. { "-Sxxd",                 "slave mode on \"ttyxx\", file descriptor \"d\"" },
  607. { NULL, NULL }};
  608.  
  609. static char *message[] = {
  610. "Fonts must be fixed width and, if both normal and bold are specified, must",
  611. "have the same size.  If only a normal font is specified, it will be used for",
  612. "both normal and bold text (by doing overstriking).  The -e option, if given,",
  613. "must be appear at the end of the command line, otherwise the user's default",
  614. "shell will be started.  Options that start with a plus sign (+) restore the",
  615. "default.",
  616. NULL};
  617.  
  618. static void Syntax (badOption)
  619.     char *badOption;
  620. {
  621.     struct _options *opt;
  622.     int col;
  623.  
  624.     fprintf (stderr, "%s:  bad command line option \"%s\"\r\n\n",
  625.          ProgramName, badOption);
  626.  
  627.     fprintf (stderr, "usage:  %s", ProgramName);
  628.     col = 8 + strlen(ProgramName);
  629.     for (opt = options; opt->opt; opt++) {
  630.     int len = 3 + strlen(opt->opt);     /* space [ string ] */
  631.     if (col + len > 79) {
  632.         fprintf (stderr, "\r\n   ");  /* 3 spaces */
  633.         col = 3;
  634.     }
  635.     fprintf (stderr, " [%s]", opt->opt);
  636.     col += len;
  637.     }
  638.  
  639.     fprintf (stderr, "\r\n\nType %s -help for a full description.\r\n\n",
  640.          ProgramName);
  641.     exit (1);
  642. }
  643.  
  644. static void Help ()
  645. {
  646.     struct _options *opt;
  647.     char **cpp;
  648.  
  649.     fprintf (stderr, "usage:\n        %s [-options ...] [-e command args]\n\n",
  650.          ProgramName);
  651.     fprintf (stderr, "where options include:\n");
  652.     for (opt = options; opt->opt; opt++) {
  653.     fprintf (stderr, "    %-28s %s\n", opt->opt, opt->desc);
  654.     }
  655.  
  656.     putc ('\n', stderr);
  657.     for (cpp = message; *cpp; cpp++) {
  658.     fputs (*cpp, stderr);
  659.     putc ('\n', stderr);
  660.     }
  661.     putc ('\n', stderr);
  662.  
  663.     exit (0);
  664. }
  665.  
  666. #ifdef TIOCCONS
  667. /* ARGSUSED */
  668. static Boolean
  669. ConvertConsoleSelection(w, selection, target, type, value, length, format)
  670.     Widget w;
  671.     Atom *selection, *target, *type;
  672.     XtPointer *value;
  673.     unsigned long *length;
  674.     int *format;
  675. {
  676.     /* we don't save console output, so can't offer it */
  677.     return False;
  678. }
  679. #endif /* TIOCCONS */
  680.  
  681.  
  682. extern WidgetClass xtermWidgetClass;
  683.  
  684. Arg ourTopLevelShellArgs[] = {
  685.     { XtNallowShellResize, (XtArgVal) TRUE },    
  686.     { XtNinput, (XtArgVal) TRUE },
  687. };
  688. int number_ourTopLevelShellArgs = 2;
  689.     
  690. XtAppContext app_con;
  691. Widget toplevel;
  692. Bool waiting_for_initial_map;
  693.  
  694. extern void do_hangup();
  695.  
  696. /*
  697.  * DeleteWindow(): Action proc to implement ICCCM delete_window.
  698.  */
  699. /* ARGSUSED */
  700. void
  701. DeleteWindow(w, event, params, num_params)
  702.     Widget w;
  703.     XEvent *event;
  704.     String *params;
  705.     Cardinal *num_params;
  706. {
  707.   if (w == toplevel)
  708.     if (term->screen.Tshow)
  709.       hide_vt_window();
  710.     else
  711.       do_hangup(w);
  712.   else
  713.     if (term->screen.Vshow)
  714.       hide_tek_window();
  715.     else
  716.       do_hangup(w);
  717. }
  718.  
  719. /* ARGSUSED */
  720. void
  721. KeyboardMapping(w, event, params, num_params)
  722.     Widget w;
  723.     XEvent *event;
  724.     String *params;
  725.     Cardinal *num_params;
  726. {
  727.     switch (event->type) {
  728.        case MappingNotify:
  729.       XRefreshKeyboardMapping(&event->xmapping);
  730.       break;
  731.     }
  732. }
  733.  
  734. XtActionsRec actionProcs[] = {
  735.     "DeleteWindow", DeleteWindow,
  736.     "KeyboardMapping", KeyboardMapping,
  737. };
  738.  
  739. Atom wm_delete_window;
  740.  
  741. main (argc, argv)
  742. int argc;
  743. char **argv;
  744. {
  745.     register TScreen *screen;
  746.     register int i, pty;
  747.     int Xsocket, mode;
  748.     char *base_name();
  749.     int xerror(), xioerror();
  750.  
  751.     ProgramName = argv[0];
  752.  
  753.     ttydev = (char *) malloc (strlen (TTYDEV) + 1);
  754.     ptydev = (char *) malloc (strlen (PTYDEV) + 1);
  755.     if (!ttydev || !ptydev) {
  756.         fprintf (stderr, 
  757.                  "%s:  unable to allocate memory for ttydev or ptydev\n",
  758.              ProgramName);
  759.         exit (1);
  760.     }
  761.     strcpy (ttydev, TTYDEV);
  762.     strcpy (ptydev, PTYDEV);
  763.  
  764. #ifdef USE_SYSV_TERMIO
  765.     /* Initialization is done here rather than above in order
  766.     ** to prevent any assumptions about the order of the contents
  767.     ** of the various terminal structures (which may change from
  768.     ** implementation to implementation).
  769.     */
  770. #if defined(macII) || defined(ATT) || defined(CRAY)
  771.     d_tio.c_iflag = ICRNL|IXON;
  772.     d_tio.c_oflag = OPOST|ONLCR|TAB3;
  773.         d_tio.c_cflag = B9600|CS8|CREAD|PARENB|HUPCL;
  774.         d_tio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
  775.  
  776. #ifndef USE_TERMIOS
  777.     d_tio.c_line = 0;
  778. #endif
  779.  
  780.     d_tio.c_cc[VINTR] = CINTR;
  781.     d_tio.c_cc[VQUIT] = CQUIT;
  782.     d_tio.c_cc[VERASE] = CERASE;
  783.     d_tio.c_cc[VKILL] = CKILL;
  784.         d_tio.c_cc[VEOF] = CEOF;
  785.     d_tio.c_cc[VEOL] = CNUL;
  786.     d_tio.c_cc[VEOL2] = CNUL;
  787.     d_tio.c_cc[VSWTCH] = CNUL;
  788.  
  789. #ifdef USE_TERMIOS
  790.     d_tio.c_cc[VSUSP] = CSUSP;
  791.     d_tio.c_cc[VDSUSP] = CDSUSP;
  792.     d_tio.c_cc[VREPRINT] = CNUL;
  793.     d_tio.c_cc[VDISCARD] = CNUL;
  794.     d_tio.c_cc[VWERASE] = CNUL;
  795.     d_tio.c_cc[VLNEXT] = CNUL;
  796. #endif
  797. #ifdef TIOCSLTC
  798.         d_ltc.t_suspc = CSUSP;        /* t_suspc */
  799.         d_ltc.t_dsuspc = CDSUSP;    /* t_dsuspc */
  800.         d_ltc.t_rprntc = 0;        /* reserved...*/
  801.         d_ltc.t_flushc = 0;
  802.         d_ltc.t_werasc = 0;
  803.         d_ltc.t_lnextc = 0;
  804. #endif /* TIOCSLTC */
  805. #ifdef TIOCLSET
  806.     d_lmode = 0;
  807. #endif /* TIOCLSET */
  808. #else  /* else !macII */
  809.     d_tio.c_iflag = ICRNL|IXON;
  810.     d_tio.c_oflag = OPOST|ONLCR|TAB3;
  811. #ifdef BAUD_0
  812.         d_tio.c_cflag = CS8|CREAD|PARENB|HUPCL;
  813. #else    /* !BAUD_0 */
  814.         d_tio.c_cflag = B9600|CS8|CREAD|PARENB|HUPCL;
  815. #endif    /* !BAUD_0 */
  816.         d_tio.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
  817.     d_tio.c_line = 0;
  818.     d_tio.c_cc[VINTR] = 0x7f;        /* DEL  */
  819.     d_tio.c_cc[VQUIT] = '\\' & 0x3f;    /* '^\'    */
  820.     d_tio.c_cc[VERASE] = '#';        /* '#'    */
  821.     d_tio.c_cc[VKILL] = '@';        /* '@'    */
  822.         d_tio.c_cc[VEOF] = 'D' & 0x3f;        /* '^D'    */
  823.     d_tio.c_cc[VEOL] = '@' & 0x3f;        /* '^@'    */
  824. #ifdef VSWTCH
  825.     d_tio.c_cc[VSWTCH] = '@' & 0x3f;    /* '^@'    */
  826. #endif    /* VSWTCH */
  827.     /* now, try to inherit tty settings */
  828.     {
  829.         int i;
  830.  
  831.         for (i = 0; i <= 2; i++) {
  832.         struct termio deftio;
  833.         if (ioctl (i, TCGETA, &deftio) == 0) {
  834.             d_tio.c_cc[VINTR] = deftio.c_cc[VINTR];
  835.             d_tio.c_cc[VQUIT] = deftio.c_cc[VQUIT];
  836.             d_tio.c_cc[VERASE] = deftio.c_cc[VERASE];
  837.             d_tio.c_cc[VKILL] = deftio.c_cc[VKILL];
  838.             d_tio.c_cc[VEOF] = deftio.c_cc[VEOF];
  839.             d_tio.c_cc[VEOL] = deftio.c_cc[VEOL];
  840. #ifdef VSWTCH
  841.             d_tio.c_cc[VSWTCH] = deftio.c_cc[VSWTCH];
  842. #endif /* VSWTCH */
  843.             break;
  844.         }
  845.         }
  846.     }
  847. #ifdef TIOCSLTC
  848.         d_ltc.t_suspc = '\000';        /* t_suspc */
  849.         d_ltc.t_dsuspc = '\000';    /* t_dsuspc */
  850.         d_ltc.t_rprntc = '\377';    /* reserved...*/
  851.         d_ltc.t_flushc = '\377';
  852.         d_ltc.t_werasc = '\377';
  853.         d_ltc.t_lnextc = '\377';
  854. #endif    /* TIOCSLTC */
  855. #ifdef USE_TERMIOS
  856.     d_tio.c_cc[VSUSP] = '\000';
  857.     d_tio.c_cc[VDSUSP] = '\000';
  858.     d_tio.c_cc[VREPRINT] = '\377';
  859.     d_tio.c_cc[VDISCARD] = '\377';
  860.     d_tio.c_cc[VWERASE] = '\377';
  861.     d_tio.c_cc[VLNEXT] = '\377';
  862. #endif
  863. #ifdef TIOCLSET
  864.     d_lmode = 0;
  865. #endif    /* TIOCLSET */
  866. #endif  /* macII */
  867. #endif    /* USE_SYSV_TERMIO */
  868.  
  869.     /* Init the Toolkit. */
  870.     toplevel = XtAppInitialize (&app_con, "XTerm", 
  871.                     optionDescList, XtNumber(optionDescList), 
  872.                     &argc, argv, fallback_resources, NULL, 0);
  873.  
  874.     XtGetApplicationResources(toplevel, (XtPointer) &resource,
  875.                   application_resources,
  876.                   XtNumber(application_resources), NULL, 0);
  877.  
  878.     waiting_for_initial_map = resource.wait_for_map;
  879.  
  880.     /*
  881.      * ICCCM delete_window.
  882.      */
  883.     XtAppAddActions(app_con, actionProcs, XtNumber(actionProcs));
  884.  
  885.     /*
  886.      * fill in terminal modes
  887.      */
  888.     if (resource.tty_modes) {
  889.         int n = parse_tty_modes (resource.tty_modes, ttymodelist);
  890.         if (n < 0) {
  891.         fprintf (stderr, "%s:  bad tty modes \"%s\"\n",
  892.              ProgramName, resource.tty_modes);
  893.         } else if (n > 0) {
  894.         override_tty_modes = 1;
  895.         }
  896.     }
  897.  
  898.     xterm_name = resource.xterm_name;
  899.     sunFunctionKeys = resource.sunFunctionKeys;
  900.     if (strcmp(xterm_name, "-") == 0) xterm_name = "xterm";
  901.     if (resource.icon_geometry != NULL) {
  902.         int scr, junk;
  903.         int ix, iy;
  904.         Arg args[2];
  905.  
  906.         for(scr = 0;    /* yyuucchh */
  907.         XtScreen(toplevel) != ScreenOfDisplay(XtDisplay(toplevel),scr);
  908.         scr++);
  909.  
  910.         args[0].name = XtNiconX;
  911.         args[1].name = XtNiconY;
  912.         XGeometry(XtDisplay(toplevel), scr, resource.icon_geometry, "",
  913.               0, 0, 0, 0, 0, &ix, &iy, &junk, &junk);
  914.         args[0].value = (XtArgVal) ix;
  915.         args[1].value = (XtArgVal) iy;
  916.         XtSetValues( toplevel, args, 2);
  917.     }
  918.  
  919.     XtSetValues (toplevel, ourTopLevelShellArgs, 
  920.              number_ourTopLevelShellArgs);
  921.  
  922.  
  923.     /* Parse the rest of the command line */
  924.     for (argc--, argv++ ; argc > 0 ; argc--, argv++) {
  925.         if(**argv != '-') Syntax (*argv);
  926.  
  927.         switch(argv[0][1]) {
  928.          case 'h':
  929.         Help ();
  930.         /* NOTREACHED */
  931.          case 'C':
  932. #ifdef TIOCCONS
  933.         {
  934.             struct stat sbuf;
  935.  
  936.             /* Must be owner and have read/write permission.
  937.                xdm cooperates to give the console the right user. */
  938.             if ( !stat("/dev/console", &sbuf) &&
  939.              (sbuf.st_uid == getuid()) &&
  940.              !access("/dev/console", R_OK|W_OK))
  941.             {
  942.             Console = TRUE;
  943.             } else
  944.             Console = FALSE;
  945.         }
  946. #endif    /* TIOCCONS */
  947.         continue;
  948.          case 'S':
  949.         if (sscanf(*argv + 2, "%c%c%d", passedPty, passedPty+1,
  950.                &am_slave) != 3)
  951.             Syntax(*argv);
  952.         continue;
  953. #ifdef DEBUG
  954.          case 'D':
  955.         debug = TRUE;
  956.         continue;
  957. #endif    /* DEBUG */
  958.          case 'e':
  959.         if (argc <= 1) Syntax (*argv);
  960.         command_to_exec = ++argv;
  961.         break;
  962.          default:
  963.         Syntax (*argv);
  964.         }
  965.         break;
  966.     }
  967.  
  968.     XawSimpleMenuAddGlobalActions (app_con);
  969.     XtRegisterGrabAction (HandlePopupMenu, True,
  970.                   (ButtonPressMask|ButtonReleaseMask),
  971.                   GrabModeAsync, GrabModeAsync);
  972.  
  973.         term = (XtermWidget) XtCreateManagedWidget(
  974.         "vt100", xtermWidgetClass, toplevel, NULL, 0);
  975.             /* this causes the initialize method to be called */
  976.  
  977.         screen = &term->screen;
  978.  
  979.     if (screen->savelines < 0) screen->savelines = 0;
  980.  
  981.     term->flags = 0;
  982.     if (!screen->jumpscroll) {
  983.         term->flags |= SMOOTHSCROLL;
  984.         update_jumpscroll();
  985.     }
  986.     if (term->misc.reverseWrap) {
  987.         term->flags |= REVERSEWRAP;
  988.         update_reversewrap();
  989.     }
  990.     if (term->misc.autoWrap) {
  991.         term->flags |= WRAPAROUND;
  992.         update_autowrap();
  993.     }
  994.     if (term->misc.re_verse) {
  995.         term->flags |= REVERSE_VIDEO;
  996.         update_reversevideo();
  997.     }
  998.  
  999.     inhibit = 0;
  1000.     if (term->misc.logInhibit)         inhibit |= I_LOG;
  1001.     if (term->misc.signalInhibit)        inhibit |= I_SIGNAL;
  1002.     if (term->misc.tekInhibit)            inhibit |= I_TEK;
  1003.  
  1004.     term->initflags = term->flags;
  1005.  
  1006.     if (term->misc.appcursorDefault) {
  1007.         term->keyboard.flags |= CURSOR_APL;
  1008.         update_appcursor();
  1009.     }
  1010.  
  1011.     if (term->misc.appkeypadDefault) {
  1012.         term->keyboard.flags |= KYPD_APL;
  1013.         update_appkeypad();
  1014.     }
  1015.  
  1016. /*
  1017.  * Set title and icon name if not specified
  1018.  */
  1019.  
  1020.     if (command_to_exec) {
  1021.         Arg args[2];
  1022.  
  1023.         if (!resource.title) {
  1024.         if (command_to_exec) {
  1025.             resource.title = base_name (command_to_exec[0]);
  1026.         } /* else not reached */
  1027.         }
  1028.  
  1029.         if (!resource.icon_name) 
  1030.           resource.icon_name = resource.title;
  1031.         XtSetArg (args[0], XtNtitle, resource.title);
  1032.         XtSetArg (args[1], XtNiconName, resource.icon_name);        
  1033.  
  1034.         XtSetValues (toplevel, args, 2);
  1035.     }
  1036.  
  1037.  
  1038.     if(inhibit & I_TEK)
  1039.         screen->TekEmu = FALSE;
  1040.  
  1041.     if(screen->TekEmu && !TekInit())
  1042.         exit(ERROR_INIT);
  1043.  
  1044.     /* set up stderr properly */
  1045.     i = -1;
  1046. #ifdef DEBUG
  1047.     if(debug)
  1048.         i = open ("xterm.debug.log", O_WRONLY | O_CREAT | O_TRUNC,
  1049.          0666);
  1050. #endif    /* DEBUG */
  1051.     if(i >= 0) {
  1052. #if defined(USE_SYSV_TERMIO) && !defined(SVR4)
  1053.         /* SYSV has another pointer which should be part of the
  1054.         ** FILE structure but is actually a seperate array.
  1055.         */
  1056.         unsigned char *old_bufend;
  1057.  
  1058.         old_bufend = (unsigned char *) _bufend(stderr);
  1059.         stderr->_file = i;
  1060.         _bufend(stderr) = old_bufend;
  1061. #else    /* USE_SYSV_TERMIO */
  1062.         stderr->_file = i;
  1063. #endif    /* USE_SYSV_TERMIO */
  1064.  
  1065.         /* mark this file as close on exec */
  1066.         (void) fcntl(i, F_SETFD, 1);
  1067.     }
  1068.  
  1069.     /* open a terminal for client */
  1070.     get_terminal ();
  1071.     spawn ();
  1072.     /* Child process is out there, let's catch its termination */
  1073.     signal (SIGCHLD, reapchild);
  1074.  
  1075.     /* Realize procs have now been executed */
  1076.  
  1077.     Xsocket = ConnectionNumber(screen->display);
  1078.     pty = screen->respond;
  1079.  
  1080.     if (am_slave) { /* Write window id so master end can read and use */
  1081.         char buf[80];
  1082.  
  1083.         buf[0] = '\0';
  1084.         sprintf (buf, "%lx\n", 
  1085.                  screen->TekEmu ? XtWindow (XtParent (tekWidget)) :
  1086.                       XtWindow (XtParent (term)));
  1087.         write (pty, buf, strlen (buf));
  1088.     }
  1089.  
  1090.     if (term->misc.log_on) {
  1091.         StartLog(screen);
  1092.     }
  1093.     screen->inhibit = inhibit;
  1094.  
  1095. #ifdef AIXV3
  1096.     /* In AIXV3, xterms started from /dev/console have CLOCAL set.
  1097.      * This means we need to clear CLOCAL so that SIGHUP gets sent
  1098.      * to the slave-pty process when xterm exits. 
  1099.      */
  1100.  
  1101.     {
  1102.         struct termio tio;
  1103.  
  1104.         if(ioctl(pty, TCGETA, &tio) == -1)
  1105.         SysError(ERROR_TIOCGETP);
  1106.  
  1107.         tio.c_cflag &= ~(CLOCAL);
  1108.  
  1109.         if (ioctl (pty, TCSETA, &tio) == -1)
  1110.         SysError(ERROR_TIOCSETP);
  1111.     }
  1112. #endif
  1113. #ifdef USE_SYSV_TERMIO
  1114.     if (0 > (mode = fcntl(pty, F_GETFL, 0)))
  1115.         Error();
  1116. #ifdef O_NDELAY
  1117.     mode |= O_NDELAY;
  1118. #else
  1119.     mode |= O_NONBLOCK;
  1120. #endif /* O_NDELAY */
  1121.     if (fcntl(pty, F_SETFL, mode))
  1122.         Error();
  1123. #else    /* USE_SYSV_TERMIO */
  1124.     mode = 1;
  1125.     if (ioctl (pty, FIONBIO, (char *)&mode) == -1) SysError (ERROR_FIONBIO);
  1126. #endif    /* USE_SYSV_TERMIO */
  1127.     
  1128.     pty_mask = 1 << pty;
  1129.     X_mask = 1 << Xsocket;
  1130.     Select_mask = pty_mask | X_mask;
  1131.     max_plus1 = (pty < Xsocket) ? (1 + Xsocket) : (1 + pty);
  1132.  
  1133. #ifdef DEBUG
  1134.     if (debug) printf ("debugging on\n");
  1135. #endif    /* DEBUG */
  1136.     XSetErrorHandler(xerror);
  1137.     XSetIOErrorHandler(xioerror);
  1138.     for( ; ; ) {
  1139.         if(screen->TekEmu) {
  1140.             TekRun();
  1141.         } else
  1142.             VTRun();
  1143.     }
  1144. }
  1145.  
  1146. char *base_name(name)
  1147. char *name;
  1148. {
  1149.     register char *cp;
  1150.  
  1151.     cp = rindex(name, '/');
  1152.     return(cp ? cp + 1 : name);
  1153. }
  1154.  
  1155. /* This function opens up a pty master and stuffs its value into pty.
  1156.  * If it finds one, it returns a value of 0.  If it does not find one,
  1157.  * it returns a value of !0.  This routine is designed to be re-entrant,
  1158.  * so that if a pty master is found and later, we find that the slave
  1159.  * has problems, we can re-enter this function and get another one.
  1160.  */
  1161.  
  1162. get_pty (pty)
  1163.     int *pty;
  1164. {
  1165. #if defined(SYSV) && defined(SYSV386)
  1166.         /*
  1167.       The order of this code is *important*.  On SYSV/386 we want to open
  1168.       a /dev/ttyp? first if at all possible.  If none are available, then
  1169.       we'll try to open a /dev/pts??? device.
  1170.       
  1171.       The reason for this is because /dev/ttyp? works correctly, where
  1172.       as /dev/pts??? devices have a number of bugs, (won't update
  1173.       screen correcly, will hang -- it more or less works, but you
  1174.       really don't want to use it).
  1175.       
  1176.       Most importantly, for boxes of this nature, one of the major
  1177.       "features" is that you can emulate a 8086 by spawning off a UNIX
  1178.       program on 80386/80486 in v86 mode.  In other words, you can spawn
  1179.       off multiple MS-DOS environments.  On ISC the program that does
  1180.       this is named "vpix."  The catcher is that "vpix" will *not* work
  1181.       with a /dev/pts??? device, will only work with a /dev/ttyp? device.
  1182.       
  1183.       Since we can open either a /dev/ttyp? or a /dev/pts??? device,
  1184.       the flag "IsPts" is set here so that we know which type of
  1185.       device we're dealing with in routine spawn().  That's the reason
  1186.       for the "if (IsPts)" statement in spawn(); we have two different
  1187.       device types which need to be handled differently.
  1188.       */
  1189.         if (pty_search(pty) == 0)
  1190.         return 0;
  1191. #endif /* SYSV && SYSV386 */
  1192. #ifdef ATT
  1193.     if ((*pty = open ("/dev/ptmx", O_RDWR)) < 0) {
  1194.         return 1;
  1195.     }
  1196. #if defined(SVR4) || defined(SYSV386)
  1197.     strcpy(ttydev, ptsname(*pty));
  1198. #if defined (SYSV) && defined(SYSV386)
  1199.     IsPts = True;
  1200. #endif
  1201. #endif
  1202.     return 0;
  1203. #else /* ATT else */
  1204. #ifdef AIXV3
  1205.     if ((*pty = open ("/dev/ptc", O_RDWR)) < 0) {
  1206.         return 1;
  1207.     }
  1208.     strcpy(ttydev, ttyname(*pty));
  1209.     return 0;
  1210. #endif
  1211. #ifdef sgi
  1212.     {
  1213.         char    *tty_name;
  1214.  
  1215.         tty_name = _getpty (pty, O_RDWR, 0622, 0);
  1216.         if (tty_name == 0)
  1217.         return 1;
  1218.         strcpy (ttydev, tty_name);
  1219.         return 0;
  1220.     }
  1221. #endif
  1222. #ifdef __convex__
  1223.         {
  1224.         char *pty_name, *getpty();
  1225.  
  1226.         while ((pty_name = getpty()) != NULL) {
  1227.         if ((*pty = open (pty_name, O_RDWR)) >= 0) {
  1228.             strcpy(ptydev, pty_name);
  1229.             strcpy(ttydev, pty_name);
  1230.             ttydev[5] = 't';
  1231.             return 0;
  1232.         }
  1233.         }
  1234.         return 1;
  1235.     }
  1236. #endif /* __convex__ */
  1237. #ifdef USE_GET_PSEUDOTTY
  1238.     return ((*pty = getpseudotty (&ttydev, &ptydev)) >= 0 ? 0 : 1);
  1239. #else
  1240. #if (defined(umips) && defined (SYSTYPE_SYSV))
  1241.     struct stat fstat_buf;
  1242.  
  1243.     *pty = open ("/dev/ptc", O_RDWR);
  1244.     if (*pty < 0 || (fstat (*pty, &fstat_buf)) < 0) {
  1245.       return(1);
  1246.     }
  1247.     sprintf (ttydev, "/dev/ttyq%d", minor(fstat_buf.st_rdev));
  1248. #ifndef sgi
  1249.     sprintf (ptydev, "/dev/ptyq%d", minor(fstat_buf.st_rdev));
  1250.     if ((*tty = open (ttydev, O_RDWR)) < 0) {
  1251.       close (*pty);
  1252.       return(1);
  1253.     }
  1254. #endif /* !sgi */
  1255.     /* got one! */
  1256.     return(0);
  1257. #else /* sgi or umips */
  1258.  
  1259.     return pty_search(pty);
  1260.  
  1261. #endif /* sgi or umips else */
  1262. #endif /* USE_GET_PSEUDOTTY else */
  1263. #endif /* ATT else */
  1264. }
  1265.  
  1266. /*
  1267.  * Called from get_pty to iterate over likely pseudo terminals
  1268.  * we might allocate.  Used on those systems that do not have
  1269.  * a functional interface for allocating a pty.
  1270.  * Returns 0 if found a pty, 1 if fails.
  1271.  */
  1272. int pty_search(pty)
  1273.     int *pty;
  1274. {
  1275.     static int devindex, letter = 0;
  1276.  
  1277. #ifdef CRAY
  1278.     for (; devindex < 256; devindex++) {
  1279.     sprintf (ttydev, "/dev/ttyp%03d", devindex);
  1280.     sprintf (ptydev, "/dev/pty/%03d", devindex);
  1281.  
  1282.     if ((*pty = open (ptydev, O_RDWR)) >= 0) {
  1283.         /* We need to set things up for our next entry
  1284.          * into this function!
  1285.          */
  1286.         (void) devindex++;
  1287.         return 0;
  1288.     }
  1289.     }
  1290. #else /* CRAY */
  1291.     while (PTYCHAR1[letter]) {
  1292.     ttydev [strlen(ttydev) - 2]  = ptydev [strlen(ptydev) - 2] =
  1293.         PTYCHAR1 [letter];
  1294.  
  1295.     while (PTYCHAR2[devindex]) {
  1296.         ttydev [strlen(ttydev) - 1] = ptydev [strlen(ptydev) - 1] =
  1297.         PTYCHAR2 [devindex];
  1298.         if ((*pty = open (ptydev, O_RDWR)) >= 0) {
  1299.         /* We need to set things up for our next entry
  1300.          * into this function!
  1301.          */
  1302.         (void) devindex++;
  1303.         return 0;
  1304.         }
  1305.         devindex++;
  1306.     }
  1307.     devindex = 0;
  1308.     (void) letter++;
  1309.     }
  1310. #endif /* CRAY else */
  1311.     /*
  1312.      * We were unable to allocate a pty master!  Return an error
  1313.      * condition and let our caller terminate cleanly.
  1314.      */
  1315.     return 1;
  1316. }
  1317.  
  1318. get_terminal ()
  1319. /* 
  1320.  * sets up X and initializes the terminal structure except for term.buf.fildes.
  1321.  */
  1322. {
  1323.     register TScreen *screen = &term->screen;
  1324.     
  1325.     screen->arrow = make_colored_cursor (XC_left_ptr, 
  1326.                          screen->mousecolor,
  1327.                          screen->mousecolorback);
  1328. }
  1329.  
  1330. /*
  1331.  * The only difference in /etc/termcap between 4014 and 4015 is that 
  1332.  * the latter has support for switching character sets.  We support the
  1333.  * 4015 protocol, but ignore the character switches.  Therefore, we 
  1334.  * choose 4014 over 4015.
  1335.  *
  1336.  * Features of the 4014 over the 4012: larger (19") screen, 12-bit
  1337.  * graphics addressing (compatible with 4012 10-bit addressing),
  1338.  * special point plot mode, incremental plot mode (not implemented in
  1339.  * later Tektronix terminals), and 4 character sizes.
  1340.  * All of these are supported by xterm.
  1341.  */
  1342.  
  1343. static char *tekterm[] = {
  1344.     "tek4014",
  1345.     "tek4015",        /* 4014 with APL character set support */
  1346.     "tek4012",        /* 4010 with lower case */
  1347.     "tek4013",        /* 4012 with APL character set support */
  1348.     "tek4010",        /* small screen, upper-case only */
  1349.     "dumb",
  1350.     0
  1351. };
  1352.  
  1353. /* The VT102 is a VT100 with the Advanced Video Option included standard.
  1354.  * It also adds Escape sequences for insert/delete character/line.
  1355.  * The VT220 adds 8-bit character sets, selective erase.
  1356.  * The VT320 adds a 25th status line, terminal state interrogation.
  1357.  * The VT420 has up to 48 lines on the screen.
  1358.  */
  1359.  
  1360. static char *vtterm[] = {
  1361. #ifdef USE_X11TERM
  1362.     "x11term",        /* for people who want special term name */
  1363. #endif
  1364.     "xterm",        /* the prefered name, should be fastest */
  1365.     "vt102",
  1366.     "vt100",
  1367.     "ansi",
  1368.     "dumb",
  1369.     0
  1370. };
  1371.  
  1372. /* ARGSUSED */
  1373. SIGNAL_T hungtty(i)
  1374.     int i;
  1375. {
  1376.     longjmp(env, 1);
  1377.     SIGNAL_RETURN;
  1378. }
  1379.  
  1380. #ifdef USE_HANDSHAKE
  1381. typedef enum {        /* c == child, p == parent                        */
  1382.     PTY_BAD,    /* c->p: can't open pty slave for some reason     */
  1383.     PTY_FATALERROR,    /* c->p: we had a fatal error with the pty        */
  1384.     PTY_GOOD,    /* c->p: we have a good pty, let's go on          */
  1385.     PTY_NEW,    /* p->c: here is a new pty slave, try this        */
  1386.     PTY_NOMORE,    /* p->c; no more pty's, terminate                 */
  1387.     UTMP_ADDED,    /* c->p: utmp entry has been added                */
  1388.     UTMP_TTYSLOT,    /* c->p: here is my ttyslot                       */
  1389.     PTY_EXEC    /* p->c: window has been mapped the first time    */
  1390. } status_t;
  1391.  
  1392. typedef struct {
  1393.     status_t status;
  1394.     int error;
  1395.     int fatal_error;
  1396.     int tty_slot;
  1397.     int rows;
  1398.     int cols;
  1399.     char buffer[1024];
  1400. } handshake_t;
  1401.  
  1402. /* HsSysError()
  1403.  *
  1404.  * This routine does the equivalent of a SysError but it handshakes
  1405.  * over the errno and error exit to the master process so that it can
  1406.  * display our error message and exit with our exit code so that the
  1407.  * user can see it.
  1408.  */
  1409.  
  1410. void
  1411. HsSysError(pf, error)
  1412. int pf;
  1413. int error;
  1414. {
  1415.     handshake_t handshake;
  1416.  
  1417.     handshake.status = PTY_FATALERROR;
  1418.     handshake.error = errno;
  1419.     handshake.fatal_error = error;
  1420.     strcpy(handshake.buffer, ttydev);
  1421.     write(pf, (char *) &handshake, sizeof(handshake));
  1422.     exit(error);
  1423. }
  1424.  
  1425. static int pc_pipe[2];    /* this pipe is used for parent to child transfer */
  1426. static int cp_pipe[2];    /* this pipe is used for child to parent transfer */
  1427.  
  1428. void first_map_occurred ()
  1429. {
  1430.     handshake_t handshake;
  1431.     register TScreen *screen = &term->screen;
  1432.  
  1433.     handshake.status = PTY_EXEC;
  1434.     handshake.rows = screen->max_row;
  1435.     handshake.cols = screen->max_col;
  1436.     write (pc_pipe[1], (char *) &handshake, sizeof(handshake));
  1437.     close (cp_pipe[0]);
  1438.     close (pc_pipe[1]);
  1439.     waiting_for_initial_map = False;
  1440. }
  1441. #else
  1442. /*
  1443.  * temporary hack to get xterm working on att ptys
  1444.  */
  1445. void first_map_occurred ()
  1446. {
  1447.     return;
  1448. }
  1449. #define HsSysError(a,b)
  1450. #endif /* USE_HANDSHAKE else !USE_HANDSHAKE */
  1451.  
  1452.  
  1453. spawn ()
  1454. /* 
  1455.  *  Inits pty and tty and forks a login process.
  1456.  *  Does not close fd Xsocket.
  1457.  *  If slave, the pty named in passedPty is already open for use
  1458.  */
  1459. {
  1460.     extern char *SysErrorMsg();
  1461.     register TScreen *screen = &term->screen;
  1462.     int Xsocket = ConnectionNumber(screen->display);
  1463. #ifdef USE_HANDSHAKE
  1464.     handshake_t handshake;
  1465. #else
  1466.     int fds[2];
  1467. #endif
  1468.     int tty = -1;
  1469.     int discipline;
  1470.     int done;
  1471. #ifdef USE_SYSV_TERMIO
  1472.     struct termio tio;
  1473.     struct termio dummy_tio;
  1474. #ifdef TIOCLSET
  1475.     unsigned lmode;
  1476. #endif    /* TIOCLSET */
  1477. #ifdef TIOCSLTC
  1478.     struct ltchars ltc;
  1479. #endif    /* TIOCSLTC */
  1480.     int one = 1;
  1481.     int zero = 0;
  1482.     int status;
  1483. #else    /* else not USE_SYSV_TERMIO */
  1484.     unsigned lmode;
  1485.     struct tchars tc;
  1486.     struct ltchars ltc;
  1487.     struct sgttyb sg;
  1488. #ifdef sony
  1489.     int jmode;
  1490.     struct jtchars jtc;
  1491. #endif /* sony */
  1492. #endif    /* USE_SYSV_TERMIO */
  1493.  
  1494.     char termcap [1024];
  1495.     char newtc [1024];
  1496.     char *ptr, *shname, *shname_minus;
  1497.     int i, no_dev_tty = FALSE;
  1498. #ifdef USE_SYSV_TERMIO
  1499.     char *dev_tty_name = (char *) 0;
  1500.     int fd;            /* for /etc/wtmp */
  1501. #endif    /* USE_SYSV_TERMIO */
  1502.     char **envnew;        /* new environment */
  1503.     int envsize;        /* elements in new environment */
  1504.     char buf[64];
  1505.     char *TermName = NULL;
  1506.     int ldisc = 0;
  1507. #ifdef sun
  1508. #ifdef TIOCSSIZE
  1509.     struct ttysize ts;
  1510. #endif    /* TIOCSSIZE */
  1511. #else    /* not sun */
  1512. #ifdef TIOCSWINSZ
  1513.     struct winsize ws;
  1514. #endif    /* TIOCSWINSZ */
  1515. #endif    /* sun */
  1516.     struct passwd *pw = NULL;
  1517. #ifdef UTMP
  1518.     struct utmp utmp;
  1519. #ifdef LASTLOG
  1520.     struct lastlog lastlog;
  1521. #endif    /* LASTLOG */
  1522. #endif    /* UTMP */
  1523.  
  1524.     screen->uid = getuid();
  1525.     screen->gid = getgid();
  1526.  
  1527. #ifdef SIGTTOU
  1528.     /* so that TIOCSWINSZ || TIOCSIZE doesn't block */
  1529.     signal(SIGTTOU,SIG_IGN);
  1530. #endif
  1531.  
  1532.     if (am_slave) {
  1533.         screen->respond = am_slave;
  1534.         ptydev[strlen(ptydev) - 2] = ttydev[strlen(ttydev) - 2] =
  1535.             passedPty[0];
  1536.         ptydev[strlen(ptydev) - 1] = ttydev[strlen(ttydev) - 1] =
  1537.             passedPty[1];
  1538.  
  1539.         setgid (screen->gid);
  1540.         setuid (screen->uid);
  1541.     } else {
  1542.         Bool tty_got_hung = False;
  1543.  
  1544.          /*
  1545.           * Sometimes /dev/tty hangs on open (as in the case of a pty
  1546.           * that has gone away).  Simply make up some reasonable
  1547.           * defaults.
  1548.           */
  1549.          signal(SIGALRM, hungtty);
  1550.          alarm(2);        /* alarm(1) might return too soon */
  1551.          if (! setjmp(env)) {
  1552.              tty = open ("/dev/tty", O_RDWR, 0);
  1553.              alarm(0);
  1554.          } else {
  1555.             tty_got_hung = True;
  1556.              tty = -1;
  1557.              errno = ENXIO;
  1558.          }
  1559.          signal(SIGALRM, SIG_DFL);
  1560.  
  1561.         /*
  1562.          * Check results and ignore current control terminal if
  1563.          * necessary.  ENXIO is what is normally returned if there is
  1564.          * no controlling terminal, but some systems (e.g. SunOS 4.0)
  1565.          * seem to return EIO.
  1566.          */
  1567.          if (tty < 0) {
  1568.             if (tty_got_hung || errno == ENXIO || errno == EIO ||
  1569.                 errno == ENOTTY) {
  1570.                 no_dev_tty = TRUE;
  1571. #ifdef TIOCSLTC
  1572.                 ltc = d_ltc;
  1573. #endif    /* TIOCSLTC */
  1574. #ifdef TIOCLSET
  1575.                 lmode = d_lmode;
  1576. #endif    /* TIOCLSET */
  1577. #ifdef USE_SYSV_TERMIO
  1578.                 tio = d_tio;
  1579. #else    /* not USE_SYSV_TERMIO */
  1580.                 sg = d_sg;
  1581.                 tc = d_tc;
  1582.                 discipline = d_disipline;
  1583. #ifdef sony
  1584.                 jmode = d_jmode;
  1585.                 jtc = d_jtc;
  1586. #endif /* sony */
  1587. #endif    /* USE_SYSV_TERMIO */
  1588.             } else {
  1589.                 SysError(ERROR_OPDEVTTY);
  1590.             }
  1591.         } else {
  1592.             /* Get a copy of the current terminal's state,
  1593.              * if we can.  Some systems (e.g., SVR4 and MacII)
  1594.              * may not have a controlling terminal at this point
  1595.              * if started directly from xdm or xinit,     
  1596.              * in which case we just use the defaults as above.
  1597.              */
  1598. #ifdef TIOCSLTC
  1599.             if(ioctl(tty, TIOCGLTC, <c) == -1)
  1600.                 ltc = d_ltc;
  1601. #endif    /* TIOCSLTC */
  1602. #ifdef TIOCLSET
  1603.             if(ioctl(tty, TIOCLGET, &lmode) == -1)
  1604.                 lmode = d_lmode;
  1605. #endif    /* TIOCLSET */
  1606. #ifdef USE_SYSV_TERMIO
  1607.                 if(ioctl(tty, TCGETA, &tio) == -1)
  1608.                     tio = d_tio;
  1609.  
  1610. #else    /* not USE_SYSV_TERMIO */
  1611.             if(ioctl(tty, TIOCGETP, (char *)&sg) == -1)
  1612.                     sg = d_sg;
  1613.             if(ioctl(tty, TIOCGETC, (char *)&tc) == -1)
  1614.                     tc = d_tc;
  1615.             if(ioctl(tty, TIOCGETD, (char *)&discipline) == -1)
  1616.                     discipline = d_disipline;
  1617. #ifdef sony
  1618.             if(ioctl(tty, TIOCKGET, (char *)&jmode) == -1)
  1619.                     jmode = d_jmode;
  1620.             if(ioctl(tty, TIOCKGETC, (char *)&jtc) == -1)
  1621.                 jtc = d_jtc;
  1622. #endif /* sony */
  1623. #endif    /* USE_SYSV_TERMIO */
  1624.             close (tty);
  1625.             /* tty is no longer an open fd! */
  1626.             tty = -1;
  1627.         }
  1628.  
  1629. #ifdef     PUCC_PTYD
  1630.         if(-1 == (screen->respond = openrpty(ttydev, ptydev,
  1631.                 (resource.utmpInhibit ?  OPTY_NOP : OPTY_LOGIN),
  1632.                 getuid(), XDisplayString(screen->display)))) {
  1633. #else /* not PUCC_PTYD */
  1634.         if (get_pty (&screen->respond)) {
  1635. #endif /* PUCC_PTYD */
  1636.             /*  no ptys! */
  1637.             (void) fprintf(stderr, "%s: no available ptys\n",
  1638.                        xterm_name);
  1639.             exit (ERROR_PTYS);
  1640. #ifdef PUCC_PTYD
  1641.         }
  1642. #else
  1643.         }            /* keep braces balanced for emacs */
  1644. #endif
  1645. #ifdef PUCC_PTYD
  1646.           else {
  1647.             /*
  1648.              *  set the fd of the master in a global var so
  1649.              *  we can undo all this on exit
  1650.              *
  1651.              */
  1652.             Ptyfd = screen->respond;
  1653.           }
  1654. #endif /* PUCC_PTYD */
  1655.     }
  1656.  
  1657.     /* avoid double MapWindow requests */
  1658.     XtSetMappedWhenManaged( screen->TekEmu ? XtParent(tekWidget) :
  1659.                     XtParent(term), False );
  1660.     wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW",
  1661.                        False);
  1662.     if (!screen->TekEmu)
  1663.         VTInit();        /* realize now so know window size for tty driver */
  1664. #ifdef TIOCCONS
  1665.     if (Console) {
  1666.         /*
  1667.          * Inform any running xconsole program
  1668.          * that we are going to steal the console.
  1669.          */
  1670.         XmuGetHostname (mit_console_name + MIT_CONSOLE_LEN, 255);
  1671.         mit_console = XInternAtom(screen->display, mit_console_name, False);
  1672.         /* the user told us to be the console, so we can use CurrentTime */
  1673.         XtOwnSelection(screen->TekEmu ? XtParent(tekWidget) : XtParent(term),
  1674.                mit_console, CurrentTime,
  1675.                ConvertConsoleSelection, NULL, NULL);
  1676.     }
  1677. #endif
  1678.     if(screen->TekEmu) {
  1679.         envnew = tekterm;
  1680.         ptr = newtc;
  1681.     } else {
  1682.         envnew = vtterm;
  1683.         ptr = termcap;
  1684.     }
  1685.     TermName = NULL;
  1686.     if (resource.term_name) {
  1687.         if (tgetent (ptr, resource.term_name) == 1) {
  1688.         TermName = resource.term_name;
  1689.         if (!screen->TekEmu)
  1690.             resize (screen, TermName, termcap, newtc);
  1691.         } else {
  1692.         fprintf (stderr, "%s:  invalid termcap entry \"%s\".\n",
  1693.              ProgramName, resource.term_name);
  1694.         }
  1695.     }
  1696.     if (!TermName) {
  1697.         while (*envnew != NULL) {
  1698.         if(tgetent(ptr, *envnew) == 1) {
  1699.             TermName = *envnew;
  1700.             if(!screen->TekEmu)
  1701.                 resize(screen, TermName, termcap, newtc);
  1702.             break;
  1703.         }
  1704.         envnew++;
  1705.         }
  1706.         if (TermName == NULL) {
  1707.         fprintf (stderr, "%s:  unable to find usable termcap entry.\n",
  1708.              ProgramName);
  1709.         Exit (1);
  1710.         }
  1711.     }
  1712.  
  1713. #ifdef sun
  1714. #ifdef TIOCSSIZE
  1715.     /* tell tty how big window is */
  1716.     if(screen->TekEmu) {
  1717.         ts.ts_lines = 38;
  1718.         ts.ts_cols = 81;
  1719.     } else {
  1720.         ts.ts_lines = screen->max_row + 1;
  1721.         ts.ts_cols = screen->max_col + 1;
  1722.     }
  1723. #endif    /* TIOCSSIZE */
  1724. #else    /* not sun */
  1725. #ifdef TIOCSWINSZ
  1726.     /* tell tty how big window is */
  1727.     if(screen->TekEmu) {
  1728.         ws.ws_row = 38;
  1729.         ws.ws_col = 81;
  1730.         ws.ws_xpixel = TFullWidth(screen);
  1731.         ws.ws_ypixel = TFullHeight(screen);
  1732.     } else {
  1733.         ws.ws_row = screen->max_row + 1;
  1734.         ws.ws_col = screen->max_col + 1;
  1735.         ws.ws_xpixel = FullWidth(screen);
  1736.         ws.ws_ypixel = FullHeight(screen);
  1737.     }
  1738. #endif    /* TIOCSWINSZ */
  1739. #endif    /* sun */
  1740.  
  1741.     if (!am_slave) {
  1742. #ifdef USE_HANDSHAKE
  1743.         if (pipe(pc_pipe) || pipe(cp_pipe))
  1744.         SysError (ERROR_FORK);
  1745. #endif
  1746.         if ((screen->pid = fork ()) == -1)
  1747.         SysError (ERROR_FORK);
  1748.         
  1749.         if (screen->pid == 0) {
  1750.         /*
  1751.          * now in child process
  1752.          */
  1753.         extern char **environ;
  1754. #if defined(_POSIX_SOURCE) || defined(SVR4) || defined(__convex__)
  1755.         int pgrp = setsid();
  1756. #else
  1757.         int pgrp = getpid();
  1758. #endif
  1759. #ifdef USE_SYSV_TERMIO
  1760.         char numbuf[12];
  1761. #if defined(UTMP) && defined(USE_SYSV_UTMP)
  1762.         char *ptyname;
  1763. #endif
  1764. #endif    /* USE_SYSV_TERMIO */
  1765.  
  1766. #ifdef USE_USG_PTYS
  1767. #if defined(SYSV) && defined(SYSV386)
  1768.                 if (IsPts) {    /* SYSV386 supports both, which did we open? */
  1769. #endif /* SYSV && SYSV386 */
  1770.         int ptyfd;
  1771.  
  1772.         setpgrp();
  1773.         grantpt (screen->respond);
  1774.         unlockpt (screen->respond);
  1775.         if ((ptyfd = open (ptsname(screen->respond), O_RDWR)) < 0) {
  1776.             SysError (1);
  1777.         }
  1778.         if (ioctl (ptyfd, I_PUSH, "ptem") < 0) {
  1779.             SysError (2);
  1780.         }
  1781. #if !defined(SVR4) && !defined(SYSV386)
  1782.         if (!getenv("CONSEM") && ioctl (ptyfd, I_PUSH, "consem") < 0) {
  1783.             SysError (3);
  1784.         }
  1785. #endif /* !SVR4 */
  1786.         if (ioctl (ptyfd, I_PUSH, "ldterm") < 0) {
  1787.             SysError (4);
  1788.         }
  1789. #ifdef SVR4            /* from Sony */
  1790.         if (ioctl (ptyfd, I_PUSH, "ttcompat") < 0) {
  1791.             SysError (5);
  1792.         }
  1793. #endif /* SVR4 */
  1794.         tty = ptyfd;
  1795.         close (screen->respond);
  1796. #ifdef TIOCSWINSZ
  1797.                 /* tell tty how big window is */
  1798.                 if(screen->TekEmu) {
  1799.                         ws.ws_row = 24;
  1800.                         ws.ws_col = 80;
  1801.                         ws.ws_xpixel = TFullWidth(screen);
  1802.                         ws.ws_ypixel = TFullHeight(screen);
  1803.                 } else {
  1804.                         ws.ws_row = screen->max_row + 1;
  1805.                         ws.ws_col = screen->max_col + 1;
  1806.                         ws.ws_xpixel = FullWidth(screen);
  1807.                         ws.ws_ypixel = FullHeight(screen);
  1808.                 }
  1809. #endif
  1810. #if defined(SYSV) && defined(SYSV386)
  1811.                 } else {    /* else pty, not pts */
  1812. #endif /* SYSV && SYSV386 */
  1813. #endif /* USE_USG_PTYS */
  1814.  
  1815. #ifdef USE_HANDSHAKE        /* warning, goes for a long ways */
  1816.         /* close parent's sides of the pipes */
  1817.         close (cp_pipe[0]);
  1818.         close (pc_pipe[1]);
  1819.  
  1820.         /* Make sure that our sides of the pipes are not in the
  1821.          * 0, 1, 2 range so that we don't fight with stdin, out
  1822.          * or err.
  1823.          */
  1824.         if (cp_pipe[1] <= 2) {
  1825.             if ((i = fcntl(cp_pipe[1], F_DUPFD, 3)) >= 0) {
  1826.                 (void) close(cp_pipe[1]);
  1827.                 cp_pipe[1] = i;
  1828.             }
  1829.         }
  1830.         if (pc_pipe[0] <= 2) {
  1831.             if ((i = fcntl(pc_pipe[0], F_DUPFD, 3)) >= 0) {
  1832.                 (void) close(pc_pipe[0]);
  1833.                 pc_pipe[0] = i;
  1834.             }
  1835.         }
  1836.  
  1837.         /* we don't need the socket, or the pty master anymore */
  1838.         close (Xsocket);
  1839.         close (screen->respond);
  1840.  
  1841.         /* Now is the time to set up our process group and
  1842.          * open up the pty slave.
  1843.          */
  1844. #ifdef    USE_SYSV_PGRP
  1845. #if defined(CRAY) && (OSMAJORVERSION > 5)
  1846.         (void) setsid();
  1847. #else
  1848.         (void) setpgrp();
  1849. #endif
  1850. #endif /* USE_SYSV_PGRP */
  1851.         while (1) {
  1852. #ifdef TIOCNOTTY
  1853.             if (!no_dev_tty && (tty = open ("/dev/tty", O_RDWR)) >= 0) {
  1854.                 ioctl (tty, TIOCNOTTY, (char *) NULL);
  1855.                 close (tty);
  1856.             }
  1857. #endif /* TIOCNOTTY */
  1858.             if ((tty = open(ttydev, O_RDWR, 0)) >= 0) {
  1859. #if defined(CRAY) && defined(TCSETCTTY)
  1860.                 /* make /dev/tty work */
  1861.                 ioctl(tty, TCSETCTTY, 0);
  1862. #endif
  1863. #ifdef    USE_SYSV_PGRP
  1864.                 /* We need to make sure that we are acutally
  1865.                  * the process group leader for the pty.  If
  1866.                  * we are, then we should now be able to open
  1867.                  * /dev/tty.
  1868.                  */
  1869.                 if ((i = open("/dev/tty", O_RDWR, 0)) >= 0) {
  1870.                     /* success! */
  1871.                     close(i);
  1872.                     break;
  1873.                 }
  1874. #else    /* USE_SYSV_PGRP */
  1875.                 break;
  1876. #endif    /* USE_SYSV_PGRP */
  1877.             }
  1878.  
  1879. #ifdef TIOCSCTTY
  1880.             ioctl(tty, TIOCSCTTY, 0);
  1881. #endif
  1882.             /* let our master know that the open failed */
  1883.             handshake.status = PTY_BAD;
  1884.             handshake.error = errno;
  1885.             strcpy(handshake.buffer, ttydev);
  1886.             write(cp_pipe[1], (char *) &handshake,
  1887.                 sizeof(handshake));
  1888.  
  1889.             /* get reply from parent */
  1890.             i = read(pc_pipe[0], (char *) &handshake,
  1891.                 sizeof(handshake));
  1892.             if (i <= 0) {
  1893.                 /* parent terminated */
  1894.                 exit(1);
  1895.             }
  1896.  
  1897.             if (handshake.status == PTY_NOMORE) {
  1898.                 /* No more ptys, let's shutdown. */
  1899.                 exit(1);
  1900.             }
  1901.  
  1902.             /* We have a new pty to try */
  1903.             free(ttydev);
  1904.             ttydev = malloc((unsigned)
  1905.                 (strlen(handshake.buffer) + 1));
  1906.             strcpy(ttydev, handshake.buffer);
  1907.         }
  1908.  
  1909.         /* use the same tty name that everyone else will use
  1910.         ** (from ttyname)
  1911.         */
  1912.         if (ptr = ttyname(tty))
  1913.         {
  1914.             /* it may be bigger */
  1915.             ttydev = realloc (ttydev, (unsigned) (strlen(ptr) + 1));
  1916.             (void) strcpy(ttydev, ptr);
  1917.         }
  1918. #if defined(SYSV) && defined(SYSV386)
  1919.                 } /* end of IsPts else clause */
  1920. #endif /* SYSV && SYSV386 */
  1921.  
  1922. #endif /* USE_HANDSHAKE -- from near fork */
  1923.  
  1924. #ifdef USE_TTY_GROUP
  1925.     { 
  1926. #include <grp.h>
  1927.         struct group *ttygrp;
  1928.         if (ttygrp = getgrnam("tty")) {
  1929.             /* change ownership of tty to real uid, "tty" gid */
  1930.             chown (ttydev, screen->uid, ttygrp->gr_gid);
  1931.             chmod (ttydev, 0620);
  1932.         }
  1933.         else {
  1934.             /* change ownership of tty to real group and user id */
  1935.             chown (ttydev, screen->uid, screen->gid);
  1936.             chmod (ttydev, 0622);
  1937.         }
  1938.         endgrent();
  1939.     }
  1940. #else /* else !USE_TTY_GROUP */
  1941.         /* change ownership of tty to real group and user id */
  1942.         chown (ttydev, screen->uid, screen->gid);
  1943.  
  1944.         /* change protection of tty */
  1945.         chmod (ttydev, 0622);
  1946. #endif /* USE_TTY_GROUP */
  1947.  
  1948.         /*
  1949.          * set up the tty modes
  1950.          */
  1951.         {
  1952. #ifdef USE_SYSV_TERMIO
  1953. #if defined(umips) || defined(CRAY)
  1954.             /* If the control tty had its modes screwed around with,
  1955.                eg. by lineedit in the shell, or emacs, etc. then tio
  1956.                will have bad values.  Let's just get termio from the
  1957.                new tty and tailor it.  */
  1958.             if (ioctl (tty, TCGETA, &tio) == -1)
  1959.               SysError (ERROR_TIOCGETP);
  1960.             tio.c_lflag |= ECHOE;
  1961. #endif /* umips */
  1962.             /* Now is also the time to change the modes of the
  1963.              * child pty.
  1964.              */
  1965.             /* input: nl->nl, don't ignore cr, cr->nl */
  1966.             tio.c_iflag &= ~(INLCR|IGNCR);
  1967.             tio.c_iflag |= ICRNL;
  1968.             /* ouput: cr->cr, nl is not return, no delays, ln->cr/nl */
  1969.             tio.c_oflag &=
  1970.              ~(OCRNL|ONLRET|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
  1971.             tio.c_oflag |= ONLCR;
  1972. #ifdef OPOST
  1973.             tio.c_oflag |= OPOST;
  1974. #endif /* OPOST */            
  1975. #ifdef BAUD_0
  1976.             /* baud rate is 0 (don't care) */
  1977.             tio.c_cflag &= ~(CBAUD);
  1978. #else    /* !BAUD_0 */
  1979.             /* baud rate is 9600 (nice default) */
  1980.             tio.c_cflag &= ~(CBAUD);
  1981.             tio.c_cflag |= B9600;
  1982. #endif    /* !BAUD_0 */
  1983.             /* enable signals, canonical processing (erase, kill, etc),
  1984.             ** echo
  1985.             */
  1986.             tio.c_lflag |= ISIG|ICANON|ECHO;
  1987.             /* reset EOL to defalult value */
  1988.             tio.c_cc[VEOL] = '@' & 0x3f;        /* '^@'    */
  1989.             /* certain shells (ksh & csh) change EOF as well */
  1990.             tio.c_cc[VEOF] = 'D' & 0x3f;        /* '^D'    */
  1991.  
  1992. #define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value;
  1993.             if (override_tty_modes) {
  1994.             /* sysv-specific */
  1995.             TMODE (XTTYMODE_intr, tio.c_cc[VINTR]);
  1996.             TMODE (XTTYMODE_quit, tio.c_cc[VQUIT]);
  1997.             TMODE (XTTYMODE_erase, tio.c_cc[VERASE]);
  1998.             TMODE (XTTYMODE_kill, tio.c_cc[VKILL]);
  1999.             TMODE (XTTYMODE_eof, tio.c_cc[VEOF]);
  2000.             TMODE (XTTYMODE_eol, tio.c_cc[VEOL]);
  2001. #ifdef VSWTCH
  2002.             TMODE (XTTYMODE_swtch, d_tio.c_cc[VSWTCH]);
  2003. #endif
  2004. #ifdef TIOCSLTC
  2005.             /* both SYSV and BSD have ltchars */
  2006.             TMODE (XTTYMODE_susp, ltc.t_suspc);
  2007.             TMODE (XTTYMODE_dsusp, ltc.t_dsuspc);
  2008.             TMODE (XTTYMODE_rprnt, ltc.t_rprntc);
  2009.             TMODE (XTTYMODE_flush, ltc.t_flushc);
  2010.             TMODE (XTTYMODE_weras, ltc.t_werasc);
  2011.             TMODE (XTTYMODE_lnext, ltc.t_lnextc);
  2012. #endif
  2013.             }
  2014. #undef TMODE
  2015.  
  2016.             if (ioctl (tty, TCSETA, &tio) == -1)
  2017.                 HsSysError(cp_pipe[1], ERROR_TIOCSETP);
  2018. #ifdef TIOCSLTC
  2019.             if (ioctl (tty, TIOCSLTC, <c) == -1)
  2020.                 HsSysError(cp_pipe[1], ERROR_TIOCSETC);
  2021. #endif    /* TIOCSLTC */
  2022. #ifdef TIOCLSET
  2023.             if (ioctl (tty, TIOCLSET, (char *)&lmode) == -1)
  2024.                 HsSysError(cp_pipe[1], ERROR_TIOCLSET);
  2025. #endif    /* TIOCLSET */
  2026. #else    /* USE_SYSV_TERMIO */
  2027.             sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW);
  2028.             sg.sg_flags |= ECHO | CRMOD;
  2029.             /* make sure speed is set on pty so that editors work right*/
  2030.             sg.sg_ispeed = B9600;
  2031.             sg.sg_ospeed = B9600;
  2032.             /* reset t_brkc to default value */
  2033.             tc.t_brkc = -1;
  2034. #ifdef sony
  2035.             if (screen->input_eight_bits)
  2036.             lmode |= LPASS8;
  2037.             else
  2038.             lmode &= ~(LPASS8);
  2039.             jmode &= ~KM_KANJI;
  2040. #endif /* sony */
  2041.  
  2042. #define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value;
  2043.             if (override_tty_modes) {
  2044.             TMODE (XTTYMODE_intr, tc.t_intrc);
  2045.             TMODE (XTTYMODE_quit, tc.t_quitc);
  2046.             TMODE (XTTYMODE_erase, sg.sg_erase);
  2047.             TMODE (XTTYMODE_kill, sg.sg_kill);
  2048.             TMODE (XTTYMODE_eof, tc.t_eofc);
  2049.             TMODE (XTTYMODE_start, tc.t_startc);
  2050.             TMODE (XTTYMODE_stop, tc.t_stopc);
  2051.             TMODE (XTTYMODE_brk, tc.t_brkc);
  2052.             /* both SYSV and BSD have ltchars */
  2053.             TMODE (XTTYMODE_susp, ltc.t_suspc);
  2054.             TMODE (XTTYMODE_dsusp, ltc.t_dsuspc);
  2055.             TMODE (XTTYMODE_rprnt, ltc.t_rprntc);
  2056.             TMODE (XTTYMODE_flush, ltc.t_flushc);
  2057.             TMODE (XTTYMODE_weras, ltc.t_werasc);
  2058.             TMODE (XTTYMODE_lnext, ltc.t_lnextc);
  2059.             }
  2060. #undef TMODE
  2061.  
  2062.             if (ioctl (tty, TIOCSETP, (char *)&sg) == -1)
  2063.                 HsSysError (cp_pipe[1], ERROR_TIOCSETP);
  2064.             if (ioctl (tty, TIOCSETC, (char *)&tc) == -1)
  2065.                 HsSysError (cp_pipe[1], ERROR_TIOCSETC);
  2066.             if (ioctl (tty, TIOCSETD, (char *)&discipline) == -1)
  2067.                 HsSysError (cp_pipe[1], ERROR_TIOCSETD);
  2068.             if (ioctl (tty, TIOCSLTC, (char *)<c) == -1)
  2069.                 HsSysError (cp_pipe[1], ERROR_TIOCSLTC);
  2070.             if (ioctl (tty, TIOCLSET, (char *)&lmode) == -1)
  2071.                 HsSysError (cp_pipe[1], ERROR_TIOCLSET);
  2072. #ifdef sony
  2073.             if (ioctl (tty, TIOCKSET, (char *)&jmode) == -1)
  2074.                 HsSysError (cp_pipe[1], ERROR_TIOCKSET);
  2075.             if (ioctl (tty, TIOCKSETC, (char *)&jtc) == -1)
  2076.                 HsSysError (cp_pipe[1], ERROR_TIOCKSETC);
  2077. #endif /* sony */
  2078. #endif    /* !USE_SYSV_TERMIO */
  2079. #ifdef TIOCCONS
  2080.             if (Console) {
  2081.             int on = 1;
  2082.             if (ioctl (tty, TIOCCONS, (char *)&on) == -1)
  2083.                 fprintf(stderr, "%s: cannot open console\n",
  2084.                     xterm_name);
  2085.             }
  2086. #endif    /* TIOCCONS */
  2087.         }
  2088.  
  2089.         signal (SIGCHLD, SIG_DFL);
  2090. #ifdef USE_SYSV_SIGHUP
  2091.         /* watch out for extra shells (I don't understand either) */
  2092.         signal (SIGHUP, SIG_DFL);
  2093. #else
  2094.         signal (SIGHUP, SIG_IGN);
  2095. #endif
  2096.         /* restore various signals to their defaults */
  2097.         signal (SIGINT, SIG_DFL);
  2098.         signal (SIGQUIT, SIG_DFL);
  2099.         signal (SIGTERM, SIG_DFL);
  2100.  
  2101.         /* copy the environment before Setenving */
  2102.         for (i = 0 ; environ [i] != NULL ; i++)
  2103.             ;
  2104.         /* compute number of Setenv() calls below */
  2105.         envsize = 1;    /* (NULL terminating entry) */
  2106.         envsize += 3;    /* TERM, WINDOWID, DISPLAY */
  2107. #ifdef UTMP
  2108.         envsize += 1;   /* LOGNAME */
  2109. #endif /* UTMP */
  2110. #ifdef USE_SYSV_ENVVARS
  2111. #ifndef TIOCSWINSZ        /* window size not stored in driver? */
  2112.         envsize += 2;    /* COLUMNS, LINES */
  2113. #endif /* TIOCSWINSZ */
  2114. #ifdef UTMP
  2115.         envsize += 2;   /* HOME, SHELL */
  2116. #endif /* UTMP */
  2117. #else /* USE_SYSV_ENVVARS */
  2118.         envsize += 1;    /* TERMCAP */
  2119. #endif /* USE_SYSV_ENVVARS */
  2120.         envnew = (char **) calloc ((unsigned) i + envsize, sizeof(char *));
  2121.         bcopy((char *)environ, (char *)envnew, i * sizeof(char *));
  2122.         environ = envnew;
  2123.         Setenv ("TERM=", TermName);
  2124.         if(!TermName)
  2125.             *newtc = 0;
  2126.  
  2127.         sprintf (buf, "%lu", screen->TekEmu ? 
  2128.              ((unsigned long) XtWindow (XtParent(tekWidget))) :
  2129.              ((unsigned long) XtWindow (XtParent(term))));
  2130.         Setenv ("WINDOWID=", buf);
  2131.         /* put the display into the environment of the shell*/
  2132.         Setenv ("DISPLAY=", XDisplayString (screen->display));
  2133.  
  2134.         signal(SIGTERM, SIG_DFL);
  2135.  
  2136.         /* this is the time to go and set up stdin, out, and err
  2137.          */
  2138.         {
  2139. #if defined(CRAY) && (OSMAJORVERSION >= 6)
  2140.             (void) close(tty);
  2141.             (void) close(0);
  2142.  
  2143.             if (open ("/dev/tty", O_RDWR)) {
  2144.             fprintf(stderr, "cannot open /dev/tty\n");
  2145.             exit(1);
  2146.             }
  2147.             (void) close(1);
  2148.             (void) close(2);
  2149.             dup(0);
  2150.             dup(0);
  2151. #else
  2152.             /* dup the tty */
  2153.             for (i = 0; i <= 2; i++)
  2154.             if (i != tty) {
  2155.                 (void) close(i);
  2156.                 (void) dup(tty);
  2157.             }
  2158.  
  2159. #ifndef ATT
  2160.             /* and close the tty */
  2161.             if (tty > 2)
  2162.             (void) close(tty);
  2163. #endif
  2164. #endif /* CRAY */
  2165.         }
  2166.  
  2167. #ifndef    USE_SYSV_PGRP
  2168. #ifdef TIOCSCTTY
  2169.         setsid();
  2170.         ioctl(0, TIOCSCTTY, 0);
  2171. #endif
  2172.         ioctl(0, TIOCSPGRP, (char *)&pgrp);
  2173.         setpgrp(0,0);
  2174.         close(open(ttydev, O_WRONLY, 0));
  2175.         setpgrp (0, pgrp);
  2176. #endif /* !USE_SYSV_PGRP */
  2177.  
  2178. #ifdef UTMP
  2179.         pw = getpwuid(screen->uid);
  2180.         if (pw && pw->pw_name)
  2181.             Setenv ("LOGNAME=", pw->pw_name); /* for POSIX */
  2182. #ifdef USE_SYSV_UTMP
  2183.         /* Set up our utmp entry now.  We need to do it here
  2184.         ** for the following reasons:
  2185.         **   - It needs to have our correct process id (for
  2186.         **     login).
  2187.         **   - If our parent was to set it after the fork(),
  2188.         **     it might make it out before we need it.
  2189.         **   - We need to do it before we go and change our
  2190.         **     user and group id's.
  2191.         */
  2192. #ifdef CRAY
  2193. #define PTYCHARLEN 4
  2194. #else
  2195. #define PTYCHARLEN 2
  2196. #endif
  2197.  
  2198.         (void) setutent ();
  2199.         /* set up entry to search for */
  2200.         ptyname = ttydev;
  2201.         (void) strncpy(utmp.ut_id,ptyname + strlen(ptyname)-PTYCHARLEN,
  2202.                    sizeof (utmp.ut_id));
  2203.         utmp.ut_type = DEAD_PROCESS;
  2204.  
  2205.         /* position to entry in utmp file */
  2206.         (void) getutid(&utmp);
  2207.  
  2208.         /* set up the new entry */
  2209.         utmp.ut_type = USER_PROCESS;
  2210.         utmp.ut_exit.e_exit = 2;
  2211.         (void) strncpy(utmp.ut_user,
  2212.                    (pw && pw->pw_name) ? pw->pw_name : "????",
  2213.                    sizeof(utmp.ut_user));
  2214.             
  2215.         (void)strncpy(utmp.ut_id, ptyname + strlen(ptyname)-PTYCHARLEN,
  2216.             sizeof(utmp.ut_id));
  2217.         (void) strncpy (utmp.ut_line,
  2218.             ptyname + strlen("/dev/"), sizeof (utmp.ut_line));
  2219.  
  2220. #ifdef HAS_UTMP_UT_HOST
  2221.         (void) strncpy(buf, DisplayString(screen->display),
  2222.                    sizeof(buf));
  2223.             {
  2224.             char *disfin = rindex(buf, ':');
  2225.             if (disfin)
  2226.             *disfin = '\0';
  2227.         }
  2228.         (void) strncpy(utmp.ut_host, buf, sizeof(utmp.ut_host));
  2229. #endif
  2230.         (void) strncpy(utmp.ut_name, pw->pw_name, 
  2231.                    sizeof(utmp.ut_name));
  2232.  
  2233.         utmp.ut_pid = getpid();
  2234.         utmp.ut_time = time ((long *) 0);
  2235.  
  2236.         /* write out the entry */
  2237.         if (!resource.utmpInhibit)
  2238.             (void) pututline(&utmp);
  2239. #ifdef WTMP
  2240.         if ( term->misc.login_shell &&
  2241.              (i = open(etc_wtmp, O_WRONLY|O_APPEND)) >= 0) {
  2242.             write(i, (char *)&utmp, sizeof(struct utmp));
  2243.             close(i);
  2244.         }
  2245. #endif
  2246.         /* close the file */
  2247.         (void) endutent();
  2248.  
  2249. #else    /* USE_SYSV_UTMP */
  2250.         /* We can now get our ttyslot!  We can also set the initial
  2251.          * UTMP entry.
  2252.          */
  2253.         tslot = ttyslot();
  2254.         added_utmp_entry = False;
  2255.         {
  2256.             if (pw && !resource.utmpInhibit &&
  2257.                 (i = open(etc_utmp, O_WRONLY)) >= 0) {
  2258.                 bzero((char *)&utmp, sizeof(struct utmp));
  2259.                 (void) strncpy(utmp.ut_line,
  2260.                            ttydev + strlen("/dev/"),
  2261.                            sizeof(utmp.ut_line));
  2262.                 (void) strncpy(utmp.ut_name, pw->pw_name,
  2263.                            sizeof(utmp.ut_name));
  2264. #ifdef HAS_UTMP_UT_HOST
  2265.                 (void) strncpy(utmp.ut_host, 
  2266.                            XDisplayString (screen->display),
  2267.                            sizeof(utmp.ut_host));
  2268. #endif
  2269.                 time(&utmp.ut_time);
  2270.                 lseek(i, (long)(tslot * sizeof(struct utmp)), 0);
  2271.                 write(i, (char *)&utmp, sizeof(struct utmp));
  2272.                 close(i);
  2273.                 added_utmp_entry = True;
  2274. #ifdef WTMP
  2275.                 if (term->misc.login_shell &&
  2276.                 (i = open(etc_wtmp, O_WRONLY|O_APPEND)) >= 0) {
  2277.                     int status;
  2278.                     status = write(i, (char *)&utmp,
  2279.                            sizeof(struct utmp));
  2280.                     status = close(i);
  2281.                 }
  2282. #endif /* WTMP */
  2283. #ifdef LASTLOG
  2284.                 if (term->misc.login_shell &&
  2285.                 (i = open(etc_lastlog, O_WRONLY)) >= 0) {
  2286.                     bzero((char *)&lastlog,
  2287.                     sizeof (struct lastlog));
  2288.                     (void) strncpy(lastlog.ll_line, ttydev +
  2289.                     sizeof("/dev"),
  2290.                     sizeof (lastlog.ll_line));
  2291.                     (void) strncpy(lastlog.ll_host, 
  2292.                       XDisplayString (screen->display),
  2293.                       sizeof (lastlog.ll_host));
  2294.                     time(&lastlog.ll_time);
  2295.                     lseek(i, (long)(screen->uid *
  2296.                     sizeof (struct lastlog)), 0);
  2297.                     write(i, (char *)&lastlog,
  2298.                     sizeof (struct lastlog));
  2299.                     close(i);
  2300.                 }
  2301. #endif /* LASTLOG */
  2302.             } else
  2303.                 tslot = -tslot;
  2304.         }
  2305.  
  2306.         /* Let's pass our ttyslot to our parent so that it can
  2307.          * clean up after us.
  2308.          */
  2309. #ifdef USE_HANDSHAKE
  2310.         handshake.tty_slot = tslot;
  2311. #endif /* USE_HANDSHAKE */
  2312. #endif /* USE_SYSV_UTMP */
  2313.  
  2314. #ifdef USE_HANDSHAKE
  2315.         /* Let our parent know that we set up our utmp entry
  2316.          * so that it can clean up after us.
  2317.          */
  2318.         handshake.status = UTMP_ADDED;
  2319.         handshake.error = 0;
  2320.         strcpy(handshake.buffer, ttydev);
  2321.         (void)write(cp_pipe[1], (char *)&handshake, sizeof(handshake));
  2322. #endif /* USE_HANDSHAKE */
  2323. #endif/* UTMP */
  2324.  
  2325.         (void) setgid (screen->gid);
  2326. #ifdef HAS_BSD_GROUPS
  2327.         if (geteuid() == 0 && pw)
  2328.           initgroups (pw->pw_name, pw->pw_gid);
  2329. #endif
  2330.         (void) setuid (screen->uid);
  2331.  
  2332. #ifdef USE_HANDSHAKE
  2333.         /* mark the pipes as close on exec */
  2334.         fcntl(cp_pipe[1], F_SETFD, 1);
  2335.         fcntl(pc_pipe[0], F_SETFD, 1);
  2336.  
  2337.         /* We are at the point where we are going to
  2338.          * exec our shell (or whatever).  Let our parent
  2339.          * know we arrived safely.
  2340.          */
  2341.         handshake.status = PTY_GOOD;
  2342.         handshake.error = 0;
  2343.         (void)strcpy(handshake.buffer, ttydev);
  2344.         (void)write(cp_pipe[1], (char *)&handshake, sizeof(handshake));
  2345.  
  2346.         if (waiting_for_initial_map) {
  2347.             i = read (pc_pipe[0], (char *) &handshake,
  2348.                   sizeof(handshake));
  2349.             if (i != sizeof(handshake) ||
  2350.             handshake.status != PTY_EXEC) {
  2351.             /* some very bad problem occurred */
  2352.             exit (ERROR_PTY_EXEC);
  2353.             }
  2354.             if(handshake.rows > 0 && handshake.cols > 0) {
  2355.             screen->max_row = handshake.rows;
  2356.             screen->max_col = handshake.cols;
  2357. #ifdef sun
  2358. #ifdef TIOCSSIZE
  2359.             ts.ts_lines = screen->max_row + 1;
  2360.             ts.ts_cols = screen->max_col + 1;
  2361. #endif /* TIOCSSIZE */
  2362. #else /* !sun */
  2363. #ifdef TIOCSWINSZ
  2364.             ws.ws_row = screen->max_row + 1;
  2365.             ws.ws_col = screen->max_col + 1;
  2366.             ws.ws_xpixel = FullWidth(screen);
  2367.             ws.ws_ypixel = FullHeight(screen);
  2368. #endif /* TIOCSWINSZ */
  2369. #endif /* sun else !sun */
  2370.             }
  2371.         }
  2372. #endif /* USE_HANDSHAKE */
  2373.  
  2374. #ifdef USE_SYSV_ENVVARS
  2375. #ifndef TIOCSWINSZ        /* window size not stored in driver? */
  2376.         sprintf (numbuf, "%d", screen->max_col + 1);
  2377.         Setenv("COLUMNS=", numbuf);
  2378.         sprintf (numbuf, "%d", screen->max_row + 1);
  2379.         Setenv("LINES=", numbuf);
  2380. #endif /* TIOCSWINSZ */
  2381. #ifdef UTMP
  2382.         if (pw) {    /* SVR4 doesn't provide these */
  2383.             if (!getenv("HOME"))
  2384.             Setenv("HOME=", pw->pw_dir);
  2385.             if (!getenv("SHELL"))
  2386.             Setenv("SHELL=", pw->pw_shell);
  2387.         }
  2388. #endif /* UTMP */
  2389. #else /* USE_SYSV_ENVVAR */
  2390.         if(!screen->TekEmu) {
  2391.             strcpy (termcap, newtc);
  2392.             resize (screen, TermName, termcap, newtc);
  2393.         }
  2394.         if (term->misc.titeInhibit) {
  2395.             remove_termcap_entry (newtc, ":ti=");
  2396.             remove_termcap_entry (newtc, ":te=");
  2397.         }
  2398.         /*
  2399.          * work around broken termcap entries */
  2400.         if (resource.useInsertMode)    {
  2401.             remove_termcap_entry (newtc, ":ic=");
  2402.             /* don't get duplicates */
  2403.             remove_termcap_entry (newtc, ":im=");
  2404.             remove_termcap_entry (newtc, ":ei=");
  2405.             remove_termcap_entry (newtc, ":mi");
  2406.             strcat (newtc, ":im=\\E[4h:ei=\\E[4l:mi:");
  2407.         }
  2408.         Setenv ("TERMCAP=", newtc);
  2409. #endif /* USE_SYSV_ENVVAR */
  2410.  
  2411.  
  2412.         /* need to reset after all the ioctl bashing we did above */
  2413. #ifdef sun
  2414. #ifdef TIOCSSIZE
  2415.         ioctl  (0, TIOCSSIZE, &ts);
  2416. #endif    /* TIOCSSIZE */
  2417. #else    /* not sun */
  2418. #ifdef TIOCSWINSZ
  2419.         ioctl (0, TIOCSWINSZ, (char *)&ws);
  2420. #endif    /* TIOCSWINSZ */
  2421. #endif    /* sun */
  2422.  
  2423.         signal(SIGHUP, SIG_DFL);
  2424.         if (command_to_exec) {
  2425.             execvp(*command_to_exec, command_to_exec);
  2426.             /* print error message on screen */
  2427.             fprintf(stderr, "%s: Can't execvp %s\n", xterm_name,
  2428.              *command_to_exec);
  2429.         } 
  2430.  
  2431. #ifdef USE_SYSV_SIGHUP
  2432.         /* fix pts sh hanging around */
  2433.         signal (SIGHUP, SIG_DFL);
  2434. #endif
  2435.  
  2436. #ifdef UTMP
  2437.         if(((ptr = getenv("SHELL")) == NULL || *ptr == 0) &&
  2438.          ((pw == NULL && (pw = getpwuid(screen->uid)) == NULL) ||
  2439.          *(ptr = pw->pw_shell) == 0))
  2440. #else    /* UTMP */
  2441.         if(((ptr = getenv("SHELL")) == NULL || *ptr == 0) &&
  2442.          ((pw = getpwuid(screen->uid)) == NULL ||
  2443.          *(ptr = pw->pw_shell) == 0))
  2444. #endif    /* UTMP */
  2445.             ptr = "/bin/sh";
  2446.         if(shname = rindex(ptr, '/'))
  2447.             shname++;
  2448.         else
  2449.             shname = ptr;
  2450.         shname_minus = malloc(strlen(shname) + 2);
  2451.         (void) strcpy(shname_minus, "-");
  2452.         (void) strcat(shname_minus, shname);
  2453. #ifndef USE_SYSV_TERMIO
  2454.         ldisc = XStrCmp("csh", shname + strlen(shname) - 3) == 0 ?
  2455.          NTTYDISC : 0;
  2456.         ioctl(0, TIOCSETD, (char *)&ldisc);
  2457. #endif    /* !USE_SYSV_TERMIO */
  2458.  
  2459. #ifdef USE_LOGIN_DASH_P
  2460.         if (term->misc.login_shell && pw && added_utmp_entry)
  2461.           execl (bin_login, "login", "-p", "-f", pw->pw_name, 0);
  2462. #endif
  2463.         execlp (ptr, (term->misc.login_shell ? shname_minus : shname),
  2464.             0);
  2465.  
  2466.         /* Exec failed. */
  2467.         fprintf (stderr, "%s: Could not exec %s!\n", xterm_name, ptr);
  2468.         (void) sleep(5);
  2469.         exit(ERROR_EXEC);
  2470.         }                /* end if in child after fork */
  2471.  
  2472. #ifdef USE_HANDSHAKE
  2473.         /* Parent process.  Let's handle handshaked requests to our
  2474.          * child process.
  2475.          */
  2476.  
  2477.         /* close childs's sides of the pipes */
  2478.         close (cp_pipe[1]);
  2479.         close (pc_pipe[0]);
  2480.  
  2481.         for (done = 0; !done; ) {
  2482.         if (read(cp_pipe[0], (char *) &handshake, sizeof(handshake)) <= 0) {
  2483.             /* Our child is done talking to us.  If it terminated
  2484.              * due to an error, we will catch the death of child
  2485.              * and clean up.
  2486.              */
  2487.             break;
  2488.         }
  2489.  
  2490.         switch(handshake.status) {
  2491.         case PTY_GOOD:
  2492.             /* Success!  Let's free up resources and
  2493.              * continue.
  2494.              */
  2495.             done = 1;
  2496.             break;
  2497.  
  2498.         case PTY_BAD:
  2499.             /* The open of the pty failed!  Let's get
  2500.              * another one.
  2501.              */
  2502.             (void) close(screen->respond);
  2503.             if (get_pty(&screen->respond)) {
  2504.                 /* no more ptys! */
  2505.                 (void) fprintf(stderr,
  2506.                   "%s: child process can find no available ptys\n",
  2507.                   xterm_name);
  2508.                 handshake.status = PTY_NOMORE;
  2509.                 write(pc_pipe[1], (char *) &handshake, sizeof(handshake));
  2510.                 exit (ERROR_PTYS);
  2511.             }
  2512.             handshake.status = PTY_NEW;
  2513.             (void) strcpy(handshake.buffer, ttydev);
  2514.             write(pc_pipe[1], (char *) &handshake, sizeof(handshake));
  2515.             break;
  2516.  
  2517.         case PTY_FATALERROR:
  2518.             errno = handshake.error;
  2519.             close(cp_pipe[0]);
  2520.             close(pc_pipe[1]);
  2521.             SysError(handshake.fatal_error);
  2522.  
  2523.         case UTMP_ADDED:
  2524.             /* The utmp entry was set by our slave.  Remember
  2525.              * this so that we can reset it later.
  2526.              */
  2527.             added_utmp_entry = True;
  2528. #ifndef    USE_SYSV_UTMP
  2529.             tslot = handshake.tty_slot;
  2530. #endif    /* USE_SYSV_UTMP */
  2531.             free(ttydev);
  2532.             ttydev = malloc((unsigned) strlen(handshake.buffer) + 1);
  2533.             strcpy(ttydev, handshake.buffer);
  2534.             break;
  2535.         default:
  2536.             fprintf(stderr, "%s: unexpected handshake status %d\n",
  2537.                     xterm_name, handshake.status);
  2538.         }
  2539.         }
  2540.         /* close our sides of the pipes */
  2541.         if (!waiting_for_initial_map) {
  2542.         close (cp_pipe[0]);
  2543.         close (pc_pipe[1]);
  2544.         }
  2545. #endif /* USE_HANDSHAKE */
  2546.     }                /* end if no slave */
  2547.  
  2548.     /*
  2549.      * still in parent (xterm process)
  2550.      */
  2551.  
  2552. #ifdef USE_SYSV_SIGHUP
  2553.     /* hung sh problem? */
  2554.     signal (SIGHUP, SIG_DFL);
  2555. #else
  2556.     signal (SIGHUP,SIG_IGN);
  2557. #endif
  2558.  
  2559. /*
  2560.  * Unfortunately, System V seems to have trouble divorcing the child process
  2561.  * from the process group of xterm.  This is a problem because hitting the 
  2562.  * INTR or QUIT characters on the keyboard will cause xterm to go away if we
  2563.  * don't ignore the signals.  This is annoying.
  2564.  */
  2565.  
  2566. #if defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP)
  2567.     signal (SIGINT, SIG_IGN);
  2568.  
  2569. #ifndef SYSV
  2570.     /* hung shell problem */
  2571.     signal (SIGQUIT, SIG_IGN);
  2572. #endif
  2573.     signal (SIGTERM, SIG_IGN);
  2574. #else /* else is bsd or has job control */
  2575. #ifdef SYSV
  2576.     /* if we were spawned by a jobcontrol smart shell (like ksh or csh),
  2577.      * then our pgrp and pid will be the same.  If we were spawned by
  2578.      * a jobcontrol dump shell (like /bin/sh), then we will be in out
  2579.      * parents pgrp, and we must ignore keyboard signals, or will will
  2580.      * tank on everything.
  2581.      */
  2582.     if (getpid() == getpgrp()) {
  2583.         (void) signal(SIGINT, Exit);
  2584.         (void) signal(SIGQUIT, Exit);
  2585.         (void) signal(SIGTERM, Exit);
  2586.     } else {
  2587.         (void) signal(SIGINT, SIG_IGN);
  2588.         (void) signal(SIGQUIT, SIG_IGN);
  2589.         (void) signal(SIGTERM, SIG_IGN);
  2590.     }
  2591.     (void) signal(SIGPIPE, Exit);
  2592. #else    /* SYSV */
  2593.     signal (SIGINT, Exit);
  2594.     signal (SIGQUIT, Exit);
  2595.     signal (SIGTERM, Exit);
  2596.         signal (SIGPIPE, Exit);
  2597. #endif    /* SYSV */
  2598. #endif /* USE_SYSV_SIGNALS and not SIGTSTP */
  2599.  
  2600.     return;
  2601. }                            /* end spawn */
  2602.  
  2603. SIGNAL_T
  2604. Exit(n)
  2605.     int n;
  2606. {
  2607.     register TScreen *screen = &term->screen;
  2608.         int pty = term->screen.respond;  /* file descriptor of pty */
  2609. #ifdef UTMP
  2610. #ifdef USE_SYSV_UTMP
  2611.     struct utmp utmp;
  2612.     struct utmp *utptr;
  2613.     char *ptyname;
  2614. #ifdef WTMP
  2615.     int fd;            /* for /etc/wtmp */
  2616.     int i;
  2617. #endif
  2618.     /* cleanup the utmp entry we forged earlier */
  2619.     if (!resource.utmpInhibit
  2620. #ifdef USE_HANDSHAKE        /* without handshake, no way to know */
  2621.         && added_utmp_entry
  2622. #endif /* USE_HANDSHAKE */
  2623.         ) {
  2624.         ptyname = ttydev;
  2625.         utmp.ut_type = USER_PROCESS;
  2626.         (void) strncpy(utmp.ut_id, ptyname + strlen(ptyname) - PTYCHARLEN,
  2627.                sizeof(utmp.ut_id));
  2628.         (void) setutent();
  2629.         utptr = getutid(&utmp);
  2630.         /* write it out only if it exists, and the pid's match */
  2631.         if (utptr && (utptr->ut_pid == screen->pid)) {
  2632.             utptr->ut_type = DEAD_PROCESS;
  2633.             utptr->ut_time = time((long *) 0);
  2634.             (void) pututline(utptr);
  2635. #ifdef WTMP
  2636.             /* set wtmp entry if wtmp file exists */
  2637.             if ((fd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) {
  2638.               i = write(fd, utptr, sizeof(utmp));
  2639.               i = close(fd);
  2640.             }
  2641. #endif
  2642.  
  2643.         }
  2644.         (void) endutent();
  2645.     }
  2646. #else    /* not USE_SYSV_UTMP */
  2647.     register int wfd;
  2648.     register int i;
  2649.     struct utmp utmp;
  2650.  
  2651.     if (!resource.utmpInhibit && added_utmp_entry &&
  2652.         (!am_slave && tslot > 0 && (wfd = open(etc_utmp, O_WRONLY)) >= 0)){
  2653.         bzero((char *)&utmp, sizeof(struct utmp));
  2654.         lseek(wfd, (long)(tslot * sizeof(struct utmp)), 0);
  2655.         write(wfd, (char *)&utmp, sizeof(struct utmp));
  2656.         close(wfd);
  2657. #ifdef WTMP
  2658.         if (term->misc.login_shell &&
  2659.             (wfd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) {
  2660.             (void) strncpy(utmp.ut_line, ttydev +
  2661.                 sizeof("/dev"), sizeof (utmp.ut_line));
  2662.             time(&utmp.ut_time);
  2663.             i = write(wfd, (char *)&utmp, sizeof(struct utmp));
  2664.             i = close(wfd);
  2665.         }
  2666. #endif /* WTMP */
  2667.     }
  2668. #endif    /* USE_SYSV_UTMP */
  2669. #endif    /* UTMP */
  2670.         close(pty); /* close explicitly to avoid race with slave side */
  2671.     if(screen->logging)
  2672.         CloseLog(screen);
  2673.  
  2674.     if (!am_slave) {
  2675.         /* restore ownership of tty and pty */
  2676.         chown (ttydev, 0, 0);
  2677. #ifndef sgi
  2678.         chown (ptydev, 0, 0);
  2679. #endif /* !sgi */
  2680.  
  2681.         /* restore modes of tty and pty */
  2682.         chmod (ttydev, 0666);
  2683. #ifndef sgi
  2684.         chmod (ptydev, 0666);
  2685. #endif /* !sgi */
  2686.     }
  2687.     exit(n);
  2688.     SIGNAL_RETURN;
  2689. }
  2690.  
  2691. /* ARGSUSED */
  2692. resize(screen, TermName, oldtc, newtc)
  2693. TScreen *screen;
  2694. char *TermName;
  2695. register char *oldtc, *newtc;
  2696. {
  2697. #ifndef USE_SYSV_ENVVARS
  2698.     register char *ptr1, *ptr2;
  2699.     register int i;
  2700.     register int li_first = 0;
  2701.     register char *temp;
  2702.  
  2703.     if ((ptr1 = strindex (oldtc, "co#")) == NULL){
  2704.         strcat (oldtc, "co#80:");
  2705.         ptr1 = strindex (oldtc, "co#");
  2706.     }
  2707.     if ((ptr2 = strindex (oldtc, "li#")) == NULL){
  2708.         strcat (oldtc, "li#24:");
  2709.         ptr2 = strindex (oldtc, "li#");
  2710.     }
  2711.     if(ptr1 > ptr2) {
  2712.         li_first++;
  2713.         temp = ptr1;
  2714.         ptr1 = ptr2;
  2715.         ptr2 = temp;
  2716.     }
  2717.     ptr1 += 3;
  2718.     ptr2 += 3;
  2719.     strncpy (newtc, oldtc, i = ptr1 - oldtc);
  2720.     newtc += i;
  2721.     sprintf (newtc, "%d", li_first ? screen->max_row + 1 :
  2722.      screen->max_col + 1);
  2723.     newtc += strlen(newtc);
  2724.     ptr1 = index (ptr1, ':');
  2725.     strncpy (newtc, ptr1, i = ptr2 - ptr1);
  2726.     newtc += i;
  2727.     sprintf (newtc, "%d", li_first ? screen->max_col + 1 :
  2728.      screen->max_row + 1);
  2729.     ptr2 = index (ptr2, ':');
  2730.     strcat (newtc, ptr2);
  2731. #endif /* USE_SYSV_ENVVARS */
  2732. }
  2733.  
  2734. /* ARGSUSED */
  2735. static SIGNAL_T reapchild (n)
  2736.     int n;
  2737. {
  2738. #ifdef USE_POSIX_WAIT
  2739.         pid_t pid;
  2740.  
  2741.     pid = waitpid(-1, NULL, WNOHANG);
  2742.     if (pid <= 0) {
  2743. #ifdef USE_SYSV_SIGNALS
  2744.         (void) signal(SIGCHLD, reapchild);
  2745. #endif /* USE_SYSV_SIGNALS */
  2746.         SIGNAL_RETURN;
  2747.     }
  2748. #else /* USE_POSIX_WAIT */
  2749. #if defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP))
  2750.     int status, pid;
  2751.  
  2752.     pid = wait(&status);
  2753.     if (pid == -1) {
  2754.         (void) signal(SIGCHLD, reapchild);
  2755.         SIGNAL_RETURN;
  2756.     }
  2757. #else    /* defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP)) */
  2758.     union wait status;
  2759.     register int pid;
  2760.     
  2761. #ifdef DEBUG
  2762.     if (debug) fputs ("Exiting\n", stderr);
  2763. #endif    /* DEBUG */
  2764.     pid  = wait3 (&status, WNOHANG, (struct rusage *)NULL);
  2765.     if (!pid) {
  2766. #ifdef USE_SYSV_SIGNALS
  2767.         (void) signal(SIGCHLD, reapchild);
  2768. #endif /* USE_SYSV_SIGNALS */
  2769.         SIGNAL_RETURN;
  2770.     }
  2771. #endif /* defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP) */
  2772. #endif /* USE_POSIX_WAIT else */
  2773.  
  2774. #ifdef PUCC_PTYD
  2775.         closepty(ttydev, ptydev, (resource.utmpInhibit ?  OPTY_NOP : OPTY_LOGIN), Ptyfd);
  2776. #endif /* PUCC_PTYD */
  2777.  
  2778.     if (pid != term->screen.pid) {
  2779. #ifdef USE_SYSV_SIGNALS
  2780.         (void) signal(SIGCHLD, reapchild);
  2781. #endif    /* USE_SYSV_SIGNALS */
  2782.         SIGNAL_RETURN;
  2783.     }
  2784.     
  2785.     /*
  2786.      * Use pid instead of process group (which would have to get before
  2787.      * the wait call above) so that we don't accidentally hose other
  2788.      * applications.  Otherwise, somebody could write a program which put
  2789.      * itself in somebody else's process group.  Also, we call Exit instead
  2790.      * of Cleanup so that we don't do a killpg on -1 by accident.  Some
  2791.      * operating systems seem to do very nasty things with that.
  2792.      */
  2793.     if (pid > 1) {
  2794.         kill_process_group (pid, SIGHUP);
  2795.     }
  2796.     Exit (0);
  2797.     SIGNAL_RETURN;
  2798. }
  2799.  
  2800. /* VARARGS1 */
  2801. consolepr(fmt,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
  2802. char *fmt;
  2803. {
  2804.     extern int errno;
  2805.     extern char *SysErrorMsg();
  2806.     int oerrno;
  2807.     int f;
  2808.      char buf[ BUFSIZ ];
  2809.  
  2810.     oerrno = errno;
  2811.      strcpy(buf, "xterm: ");
  2812.      sprintf(buf+strlen(buf), fmt, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
  2813.      strcat(buf, ": ");
  2814.      strcat(buf, SysErrorMsg (oerrno));
  2815.      strcat(buf, "\n");    
  2816.     f = open("/dev/console",O_WRONLY);
  2817.     write(f, buf, strlen(buf));
  2818.     close(f);
  2819. #ifdef TIOCNOTTY
  2820.     if ((f = open("/dev/tty", 2)) >= 0) {
  2821.         ioctl(f, TIOCNOTTY, (char *)NULL);
  2822.         close(f);
  2823.     }
  2824. #endif    /* TIOCNOTTY */
  2825. }
  2826.  
  2827.  
  2828. remove_termcap_entry (buf, str)
  2829.     char *buf;
  2830.     char *str;
  2831. {
  2832.     register char *strinbuf;
  2833.  
  2834.     strinbuf = strindex (buf, str);
  2835.     if (strinbuf) {
  2836.         register char *colonPtr = index (strinbuf+1, ':');
  2837.         if (colonPtr) {
  2838.             while (*colonPtr) {
  2839.                 *strinbuf++ = *colonPtr++;      /* copy down */
  2840.             }
  2841.             *strinbuf = '\0';
  2842.         } else {
  2843.             strinbuf[1] = '\0';
  2844.         }
  2845.     }
  2846.     return;
  2847. }
  2848.  
  2849. /*
  2850.  * parse_tty_modes accepts lines of the following form:
  2851.  *
  2852.  *         [SETTING] ...
  2853.  *
  2854.  * where setting consists of the words in the modelist followed by a character
  2855.  * or ^char.
  2856.  */
  2857. static int parse_tty_modes (s, modelist)
  2858.     char *s;
  2859.     struct _xttymodes *modelist;
  2860. {
  2861.     struct _xttymodes *mp;
  2862.     int c;
  2863.     int count = 0;
  2864.  
  2865.     while (1) {
  2866.     while (*s && isascii(*s) && isspace(*s)) s++;
  2867.     if (!*s) return count;
  2868.  
  2869.     for (mp = modelist; mp->name; mp++) {
  2870.         if (strncmp (s, mp->name, mp->len) == 0) break;
  2871.     }
  2872.     if (!mp->name) return -1;
  2873.  
  2874.     s += mp->len;
  2875.     while (*s && isascii(*s) && isspace(*s)) s++;
  2876.     if (!*s) return -1;
  2877.  
  2878.     if (*s == '^') {
  2879.         s++;
  2880.         c = ((*s == '?') ? 0177 : *s & 31);     /* keep control bits */
  2881.     } else {
  2882.         c = *s;
  2883.     }
  2884.     mp->value = c;
  2885.     mp->set = 1;
  2886.     count++;
  2887.     s++;
  2888.     }
  2889. }
  2890.  
  2891.  
  2892. int GetBytesAvailable (fd)
  2893.     int fd;
  2894. {
  2895. #ifdef FIONREAD
  2896.     static long arg;
  2897.     ioctl (fd, FIONREAD, (char *) &arg);
  2898.     return (int) arg;
  2899. #else
  2900.     struct pollfd pollfds[1];
  2901.  
  2902.     pollfds[0].fd = fd;
  2903.     pollfds[0].events = POLLIN;
  2904.     return poll (pollfds, 1, 0);
  2905. #endif
  2906. }
  2907.  
  2908. /* Utility function to try to hide system differences from
  2909.    everybody who used to call killpg() */
  2910.  
  2911. int
  2912. kill_process_group(pid, sig)
  2913.     int pid;
  2914.     int sig;
  2915. {
  2916. #ifndef X_NOT_POSIX
  2917.     return kill (-pid, sig);
  2918. #else
  2919. #if defined(SVR4) || defined(SYSV)
  2920.     return kill (-pid, sig);
  2921. #else
  2922.     return killpg (pid, sig);
  2923. #endif
  2924. #endif
  2925. }
  2926.