main.c revision 894e0ac8
1894e0ac8Smrg/* $XTermId: main.c,v 1.758 2014/05/26 00:01:25 tom Exp $ */ 20bd37d32Smrg 30bd37d32Smrg/* 4e0a2b6dfSmrg * Copyright 2002-2013,2014 by Thomas E. Dickey 50bd37d32Smrg * 60bd37d32Smrg * All Rights Reserved 70bd37d32Smrg * 80bd37d32Smrg * Permission is hereby granted, free of charge, to any person obtaining a 90bd37d32Smrg * copy of this software and associated documentation files (the 100bd37d32Smrg * "Software"), to deal in the Software without restriction, including 110bd37d32Smrg * without limitation the rights to use, copy, modify, merge, publish, 120bd37d32Smrg * distribute, sublicense, and/or sell copies of the Software, and to 130bd37d32Smrg * permit persons to whom the Software is furnished to do so, subject to 140bd37d32Smrg * the following conditions: 150bd37d32Smrg * 160bd37d32Smrg * The above copyright notice and this permission notice shall be included 170bd37d32Smrg * in all copies or substantial portions of the Software. 180bd37d32Smrg * 190bd37d32Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 200bd37d32Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 210bd37d32Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 220bd37d32Smrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 230bd37d32Smrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 240bd37d32Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 250bd37d32Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 260bd37d32Smrg * 270bd37d32Smrg * Except as contained in this notice, the name(s) of the above copyright 280bd37d32Smrg * holders shall not be used in advertising or otherwise to promote the 290bd37d32Smrg * sale, use or other dealings in this Software without prior written 300bd37d32Smrg * authorization. 310bd37d32Smrg * 320bd37d32Smrg * Copyright 1987, 1988 The Open Group 330bd37d32Smrg * 340bd37d32Smrg * Permission to use, copy, modify, distribute, and sell this software and its 350bd37d32Smrg * documentation for any purpose is hereby granted without fee, provided that 360bd37d32Smrg * the above copyright notice appear in all copies and that both that 370bd37d32Smrg * copyright notice and this permission notice appear in supporting 380bd37d32Smrg * documentation. 390bd37d32Smrg * 400bd37d32Smrg * The above copyright notice and this permission notice shall be included in 410bd37d32Smrg * all copies or substantial portions of the Software. 420bd37d32Smrg * 430bd37d32Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 440bd37d32Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 450bd37d32Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 460bd37d32Smrg * OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 470bd37d32Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 480bd37d32Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 490bd37d32Smrg * 500bd37d32Smrg * Except as contained in this notice, the name of The Open Group shall not be 510bd37d32Smrg * used in advertising or otherwise to promote the sale, use or other dealings 520bd37d32Smrg * in this Software without prior written authorization from The Open Group. 530bd37d32Smrg * 540bd37d32Smrg * Copyright 1987, 1988 by Digital Equipment Corporation, Maynard. 550bd37d32Smrg * 560bd37d32Smrg * All Rights Reserved 570bd37d32Smrg * 580bd37d32Smrg * Permission to use, copy, modify, and distribute this software and its 590bd37d32Smrg * documentation for any purpose and without fee is hereby granted, 600bd37d32Smrg * provided that the above copyright notice appear in all copies and that 610bd37d32Smrg * both that copyright notice and this permission notice appear in 620bd37d32Smrg * supporting documentation, and that the name of Digital not be used in 630bd37d32Smrg * advertising or publicity pertaining to distribution of the software 640bd37d32Smrg * without specific, written prior permission. 650bd37d32Smrg * 660bd37d32Smrg * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 670bd37d32Smrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 680bd37d32Smrg * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 690bd37d32Smrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 700bd37d32Smrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 710bd37d32Smrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 720bd37d32Smrg * SOFTWARE. 730bd37d32Smrg */ 74d522f475Smrg 75d522f475Smrg/* 76d522f475Smrg * W A R N I N G 77d522f475Smrg * 78d522f475Smrg * If you think you know what all of this code is doing, you are 79d522f475Smrg * probably very mistaken. There be serious and nasty dragons here. 80d522f475Smrg * 81d522f475Smrg * This client is *not* to be taken as an example of how to write X 82d522f475Smrg * Toolkit applications. It is in need of a substantial rewrite, 83d522f475Smrg * ideally to create a generic tty widget with several different parsing 84d522f475Smrg * widgets so that you can plug 'em together any way you want. Don't 85d522f475Smrg * hold your breath, though.... 86d522f475Smrg */ 87d522f475Smrg 88d522f475Smrg/* main.c */ 89d522f475Smrg 90d522f475Smrg#define RES_OFFSET(field) XtOffsetOf(XTERM_RESOURCE, field) 91d522f475Smrg 92d522f475Smrg#include <xterm.h> 930bd37d32Smrg#include <version.h> 94894e0ac8Smrg#include <graphics.h> 95d522f475Smrg 96d522f475Smrg#include <X11/cursorfont.h> 97d522f475Smrg#include <X11/Xlocale.h> 98d522f475Smrg 99d522f475Smrg#if OPT_TOOLBAR 100d522f475Smrg 101d522f475Smrg#if defined(HAVE_LIB_XAW) 102d522f475Smrg#include <X11/Xaw/Form.h> 103d522f475Smrg#elif defined(HAVE_LIB_XAW3D) 104d522f475Smrg#include <X11/Xaw3d/Form.h> 105d522f475Smrg#elif defined(HAVE_LIB_NEXTAW) 106d522f475Smrg#include <X11/neXtaw/Form.h> 107d522f475Smrg#elif defined(HAVE_LIB_XAWPLUS) 108d522f475Smrg#include <X11/XawPlus/Form.h> 109d522f475Smrg#endif 110d522f475Smrg 111d522f475Smrg#endif /* OPT_TOOLBAR */ 112d522f475Smrg 113d522f475Smrg#include <pwd.h> 114d522f475Smrg#include <ctype.h> 115d522f475Smrg 116d522f475Smrg#include <data.h> 117d522f475Smrg#include <error.h> 118d522f475Smrg#include <menu.h> 119d522f475Smrg#include <main.h> 120d522f475Smrg#include <xstrings.h> 121d522f475Smrg#include <xtermcap.h> 122d522f475Smrg#include <xterm_io.h> 123d522f475Smrg 124d522f475Smrg#if OPT_WIDE_CHARS 125d522f475Smrg#include <charclass.h> 126d522f475Smrg#endif 127d522f475Smrg 128d522f475Smrg#ifdef __osf__ 129d522f475Smrg#define USE_SYSV_SIGNALS 130d522f475Smrg#define WTMP 131d522f475Smrg#include <pty.h> /* openpty() */ 132d522f475Smrg#endif 133d522f475Smrg 134d522f475Smrg#ifdef __sgi 135d522f475Smrg#include <grp.h> /* initgroups() */ 136d522f475Smrg#endif 137d522f475Smrg 1380bd37d32Smrgstatic void Syntax(char *) GCC_NORETURN; 1390bd37d32Smrgstatic void HsSysError(int) GCC_NORETURN; 140d522f475Smrg 141d522f475Smrg#if defined(__SCO__) || defined(SVR4) || defined(_POSIX_SOURCE) 142d522f475Smrg#define USE_POSIX_SIGNALS 143d522f475Smrg#endif 144d522f475Smrg 145d522f475Smrg#if defined(SYSV) && !defined(SVR4) && !defined(ISC22) && !defined(ISC30) 146d522f475Smrg/* older SYSV systems cannot ignore SIGHUP. 147d522f475Smrg Shell hangs, or you get extra shells, or something like that */ 148d522f475Smrg#define USE_SYSV_SIGHUP 149d522f475Smrg#endif 150d522f475Smrg 151d522f475Smrg#if defined(sony) && defined(bsd43) && !defined(KANJI) 152d522f475Smrg#define KANJI 153d522f475Smrg#endif 154d522f475Smrg 155d522f475Smrg#ifdef linux 156d522f475Smrg#define USE_SYSV_PGRP 157d522f475Smrg#define USE_SYSV_SIGNALS 158d522f475Smrg#define WTMP 159d522f475Smrg#ifdef __GLIBC__ 160d522f475Smrg#if (__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)) 161d522f475Smrg#include <pty.h> 162d522f475Smrg#endif 163d522f475Smrg#endif 164d522f475Smrg#endif 165d522f475Smrg 166d522f475Smrg#ifdef __MVS__ 167d522f475Smrg#define USE_SYSV_PGRP 168d522f475Smrg#define USE_SYSV_SIGNALS 169d522f475Smrg#endif 170d522f475Smrg 171d522f475Smrg#ifdef __CYGWIN__ 172d522f475Smrg#define WTMP 173d522f475Smrg#endif 174d522f475Smrg 175d522f475Smrg#ifdef __SCO__ 176d522f475Smrg#ifndef _SVID3 177d522f475Smrg#define _SVID3 178d522f475Smrg#endif 179d522f475Smrg#endif 180d522f475Smrg 181d522f475Smrg#if defined(__GLIBC__) && !defined(linux) 182d522f475Smrg#define USE_SYSV_PGRP 183d522f475Smrg#define WTMP 184d522f475Smrg#endif 185d522f475Smrg 186d522f475Smrg#if defined(USE_TTY_GROUP) || defined(USE_UTMP_SETGID) 187d522f475Smrg#include <grp.h> 188d522f475Smrg#endif 189d522f475Smrg 190d522f475Smrg#ifndef TTY_GROUP_NAME 191d522f475Smrg#define TTY_GROUP_NAME "tty" 192d522f475Smrg#endif 193d522f475Smrg 194d522f475Smrg#include <sys/stat.h> 195d522f475Smrg 196d522f475Smrg#ifdef Lynx 197d522f475Smrg#ifndef BSDLY 198d522f475Smrg#define BSDLY 0 199d522f475Smrg#endif 200d522f475Smrg#ifndef VTDLY 201d522f475Smrg#define VTDLY 0 202d522f475Smrg#endif 203d522f475Smrg#ifndef FFDLY 204d522f475Smrg#define FFDLY 0 205d522f475Smrg#endif 206d522f475Smrg#endif 207d522f475Smrg 208d522f475Smrg#ifdef SYSV /* { */ 209d522f475Smrg 210d522f475Smrg#ifdef USE_USG_PTYS /* AT&T SYSV has no ptyio.h */ 211d522f475Smrg#include <sys/stropts.h> /* for I_PUSH */ 212d522f475Smrg#include <poll.h> /* for POLLIN */ 213d522f475Smrg#endif /* USE_USG_PTYS */ 214d522f475Smrg 215d522f475Smrg#define USE_SYSV_SIGNALS 216d522f475Smrg#define USE_SYSV_PGRP 217d522f475Smrg 218d522f475Smrg#if !defined(TIOCSWINSZ) || defined(__SCO__) || defined(__UNIXWARE__) 219d522f475Smrg#define USE_SYSV_ENVVARS /* COLUMNS/LINES vs. TERMCAP */ 220d522f475Smrg#endif 221d522f475Smrg 222d522f475Smrg/* 223d522f475Smrg * now get system-specific includes 224d522f475Smrg */ 225d522f475Smrg#ifdef macII 226d522f475Smrg#include <sys/ttychars.h> 227d522f475Smrg#undef USE_SYSV_ENVVARS 228d522f475Smrg#undef FIOCLEX 229d522f475Smrg#undef FIONCLEX 230d522f475Smrg#define setpgrp2 setpgrp 231d522f475Smrg#include <sgtty.h> 232d522f475Smrg#include <sys/resource.h> 233d522f475Smrg#endif 234d522f475Smrg 235d522f475Smrg#ifdef __hpux 236d522f475Smrg#include <sys/ptyio.h> 237d522f475Smrg#endif /* __hpux */ 238d522f475Smrg 239d522f475Smrg#ifdef __osf__ 240d522f475Smrg#undef USE_SYSV_PGRP 241d522f475Smrg#define setpgrp setpgid 242d522f475Smrg#endif 243d522f475Smrg 244d522f475Smrg#ifdef __sgi 245d522f475Smrg#include <sys/sysmacros.h> 246d522f475Smrg#endif /* __sgi */ 247d522f475Smrg 248d522f475Smrg#ifdef sun 249d522f475Smrg#include <sys/strredir.h> 250d522f475Smrg#endif 251d522f475Smrg 252e39b573cSmrg#else /* } !SYSV { */ /* BSD systems */ 253d522f475Smrg 254d522f475Smrg#ifdef __QNX__ 255d522f475Smrg 256d522f475Smrg#ifndef __QNXNTO__ 257d522f475Smrg#define ttyslot() 1 258d522f475Smrg#else 259d522f475Smrg#define USE_SYSV_PGRP 260d522f475Smrgextern __inline__ 261d522f475Smrgint 262d522f475Smrgttyslot(void) 263d522f475Smrg{ 264d522f475Smrg return 1; /* yuk */ 265d522f475Smrg} 266d522f475Smrg#endif 267d522f475Smrg 268d522f475Smrg#else 269d522f475Smrg 270d522f475Smrg#if defined(__INTERIX) || defined(__APPLE__) 271d522f475Smrg#define setpgrp setpgid 272d522f475Smrg#endif 273d522f475Smrg 274d522f475Smrg#ifndef linux 275d522f475Smrg#ifndef VMS 276d522f475Smrg#ifndef USE_POSIX_TERMIOS 277d522f475Smrg#ifndef USE_ANY_SYSV_TERMIO 278d522f475Smrg#include <sgtty.h> 279d522f475Smrg#endif 280d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 281d522f475Smrg#ifdef Lynx 282d522f475Smrg#include <resource.h> 283d522f475Smrg#else 284d522f475Smrg#include <sys/resource.h> 285d522f475Smrg#endif 286d522f475Smrg#endif /* !VMS */ 287d522f475Smrg#endif /* !linux */ 288d522f475Smrg 289d522f475Smrg#endif /* __QNX__ */ 290d522f475Smrg 291d522f475Smrg#endif /* } !SYSV */ 292d522f475Smrg 293d522f475Smrg/* Xpoll.h and <sys/param.h> on glibc 2.1 systems have colliding NBBY's */ 294d522f475Smrg#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))) 295d522f475Smrg#ifndef NOFILE 296d522f475Smrg#define NOFILE OPEN_MAX 297d522f475Smrg#endif 298d522f475Smrg#elif !(defined(VMS) || defined(WIN32) || defined(Lynx) || defined(__GNU__) || defined(__MVS__)) 299d522f475Smrg#include <sys/param.h> /* for NOFILE */ 300d522f475Smrg#endif 301d522f475Smrg 302d522f475Smrg#if defined(BSD) && (BSD >= 199103) 303d522f475Smrg#define WTMP 304d522f475Smrg#endif 305d522f475Smrg 306d522f475Smrg#include <stdio.h> 307d522f475Smrg 308d522f475Smrg#ifdef __hpux 309d522f475Smrg#include <sys/utsname.h> 310d522f475Smrg#endif /* __hpux */ 311d522f475Smrg 312d522f475Smrg#if defined(apollo) && (OSMAJORVERSION == 10) && (OSMINORVERSION < 4) 313d522f475Smrg#define ttyslot() 1 314d522f475Smrg#endif /* apollo */ 315d522f475Smrg 316d522f475Smrg#if defined(UTMPX_FOR_UTMP) 317d522f475Smrg#define UTMP_STR utmpx 318d522f475Smrg#else 319d522f475Smrg#define UTMP_STR utmp 320d522f475Smrg#endif 321d522f475Smrg 322d522f475Smrg#if defined(USE_UTEMPTER) 323d522f475Smrg#include <utempter.h> 324d522f475Smrg#endif 325d522f475Smrg 326d522f475Smrg#if defined(UTMPX_FOR_UTMP) 327d522f475Smrg 328d522f475Smrg#include <utmpx.h> 329d522f475Smrg 330d522f475Smrg#define call_endutent endutxent 331d522f475Smrg#define call_getutid getutxid 332d522f475Smrg#define call_pututline pututxline 333d522f475Smrg#define call_setutent setutxent 334d522f475Smrg#define call_updwtmp updwtmpx 335d522f475Smrg 336d522f475Smrg#elif defined(HAVE_UTMP) 337d522f475Smrg 338d522f475Smrg#include <utmp.h> 339d522f475Smrg 340d522f475Smrg#if defined(_CRAY) && (OSMAJORVERSION < 8) 341d522f475Smrgextern struct utmp *getutid __((struct utmp * _Id)); 342d522f475Smrg#endif 343d522f475Smrg 344d522f475Smrg#define call_endutent endutent 345d522f475Smrg#define call_getutid getutid 346d522f475Smrg#define call_pututline pututline 347d522f475Smrg#define call_setutent setutent 348d522f475Smrg#define call_updwtmp updwtmp 349d522f475Smrg 350d522f475Smrg#endif 351d522f475Smrg 352d522f475Smrg#if defined(USE_LASTLOG) && defined(HAVE_LASTLOG_H) 353d522f475Smrg#include <lastlog.h> /* caution: glibc includes utmp.h here */ 354d522f475Smrg#endif 355d522f475Smrg 356d522f475Smrg#ifndef USE_LASTLOGX 357d522f475Smrg#if defined(_NETBSD_SOURCE) && defined(_PATH_LASTLOGX) 358d522f475Smrg#define USE_LASTLOGX 1 359d522f475Smrg#endif 360d522f475Smrg#endif 361d522f475Smrg 362d522f475Smrg#ifdef PUCC_PTYD 363d522f475Smrg#include <local/openpty.h> 364d522f475Smrg#endif /* PUCC_PTYD */ 365d522f475Smrg 366d522f475Smrg#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) 367d522f475Smrg#include <util.h> /* openpty() */ 368d522f475Smrg#endif 369d522f475Smrg 370956cc18dSsnj#if defined(__FreeBSD__) || defined(__DragonFly__) 371d522f475Smrg#include <libutil.h> /* openpty() */ 372d522f475Smrg#endif 373d522f475Smrg 374d522f475Smrg#if !defined(UTMP_FILENAME) 375d522f475Smrg#if defined(UTMP_FILE) 376d522f475Smrg#define UTMP_FILENAME UTMP_FILE 377d522f475Smrg#elif defined(_PATH_UTMP) 378d522f475Smrg#define UTMP_FILENAME _PATH_UTMP 379d522f475Smrg#else 380d522f475Smrg#define UTMP_FILENAME "/etc/utmp" 381d522f475Smrg#endif 382d522f475Smrg#endif 383d522f475Smrg 384d522f475Smrg#ifndef LASTLOG_FILENAME 385d522f475Smrg#ifdef _PATH_LASTLOG 386d522f475Smrg#define LASTLOG_FILENAME _PATH_LASTLOG 387d522f475Smrg#else 388d522f475Smrg#define LASTLOG_FILENAME "/usr/adm/lastlog" /* only on BSD systems */ 389d522f475Smrg#endif 390d522f475Smrg#endif 391d522f475Smrg 392d522f475Smrg#if !defined(WTMP_FILENAME) 393d522f475Smrg#if defined(WTMP_FILE) 394d522f475Smrg#define WTMP_FILENAME WTMP_FILE 395d522f475Smrg#elif defined(_PATH_WTMP) 396d522f475Smrg#define WTMP_FILENAME _PATH_WTMP 397d522f475Smrg#elif defined(SYSV) 398d522f475Smrg#define WTMP_FILENAME "/etc/wtmp" 399d522f475Smrg#else 400d522f475Smrg#define WTMP_FILENAME "/usr/adm/wtmp" 401d522f475Smrg#endif 402d522f475Smrg#endif 403d522f475Smrg 404d522f475Smrg#include <signal.h> 405d522f475Smrg 406d522f475Smrg#if defined(__SCO__) || (defined(ISC) && !defined(_POSIX_SOURCE)) 407d522f475Smrg#undef SIGTSTP /* defined, but not the BSD way */ 408d522f475Smrg#endif 409d522f475Smrg 410d522f475Smrg#ifdef SIGTSTP 411d522f475Smrg#include <sys/wait.h> 412d522f475Smrg#endif 413d522f475Smrg 414d522f475Smrg#if defined(__SCO__) || defined(__UNIXWARE__) 415d522f475Smrg#undef ECHOKE 416d522f475Smrg#undef ECHOCTL 417d522f475Smrg#endif 418d522f475Smrg 419d522f475Smrg#if defined(HAVE_SYS_TTYDEFAULTS_H) && !defined(CEOF) 420d522f475Smrg#include <sys/ttydefaults.h> 421d522f475Smrg#endif 422d522f475Smrg 423d522f475Smrg#ifdef X_NOT_POSIX 424d522f475Smrgextern long lseek(); 425d522f475Smrg#if defined(USG) || defined(SVR4) 426d522f475Smrgextern unsigned sleep(); 427d522f475Smrg#else 428d522f475Smrgextern void sleep(); 429d522f475Smrg#endif 430d522f475Smrgextern char *ttyname(); 431d522f475Smrg#endif 432d522f475Smrg 433d522f475Smrg#if defined(SYSV) && defined(DECL_PTSNAME) 434d522f475Smrgextern char *ptsname(int); 435d522f475Smrg#endif 436d522f475Smrg 437d522f475Smrg#ifndef VMS 4380bd37d32Smrgstatic void reapchild(int /* n */ ); 439d522f475Smrgstatic int spawnXTerm(XtermWidget /* xw */ ); 44020d2c4d2Smrgstatic void remove_termcap_entry(char *, const char *); 441d522f475Smrg#ifdef USE_PTY_SEARCH 44220d2c4d2Smrgstatic int pty_search(int * /* pty */ ); 443d522f475Smrg#endif 444d522f475Smrg#endif /* ! VMS */ 445d522f475Smrg 446d522f475Smrgstatic int get_pty(int *pty, char *from); 44720d2c4d2Smrgstatic void resize_termcap(XtermWidget xw); 448e0a2b6dfSmrgstatic void set_owner(char *device, unsigned uid, unsigned gid, unsigned mode); 449d522f475Smrg 450d522f475Smrgstatic Bool added_utmp_entry = False; 451d522f475Smrg 452d522f475Smrg#ifdef HAVE_POSIX_SAVED_IDS 453d522f475Smrgstatic uid_t save_euid; 454d522f475Smrgstatic gid_t save_egid; 455d522f475Smrg#endif 456d522f475Smrg 457d522f475Smrgstatic uid_t save_ruid; 458d522f475Smrgstatic gid_t save_rgid; 459d522f475Smrg 460d522f475Smrg#if defined(USE_UTMP_SETGID) 461d522f475Smrgstatic int really_get_pty(int *pty, char *from); 462d522f475Smrg#endif 463d522f475Smrg 464d522f475Smrg#if defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 465d522f475Smrgstatic Bool xterm_exiting = False; 466d522f475Smrg#endif 467d522f475Smrg 468d522f475Smrgstatic char *explicit_shname = NULL; 469d522f475Smrg 470d522f475Smrg/* 471d522f475Smrg** Ordinarily it should be okay to omit the assignment in the following 472d522f475Smrg** statement. Apparently the c89 compiler on AIX 4.1.3 has a bug, or does 473d522f475Smrg** it? Without the assignment though the compiler will init command_to_exec 474d522f475Smrg** to 0xffffffff instead of NULL; and subsequent usage, e.g. in spawnXTerm() to 475d522f475Smrg** SEGV. 476d522f475Smrg*/ 477d522f475Smrgstatic char **command_to_exec = NULL; 478d522f475Smrg 479d522f475Smrg#if OPT_LUIT_PROG 480d522f475Smrgstatic char **command_to_exec_with_luit = NULL; 4810bd37d32Smrgstatic unsigned command_length_with_luit = 0; 482d522f475Smrg#endif 483d522f475Smrg 484d522f475Smrg#define TERMCAP_ERASE "kb" 485d522f475Smrg#define VAL_INITIAL_ERASE A2E(8) 486d522f475Smrg 487d522f475Smrg/* choose a nice default value for speed - if we make it too low, users who 488d522f475Smrg * mistakenly use $TERM set to vt100 will get padding delays. Setting it to a 489d522f475Smrg * higher value is not useful since legacy applications (termcap) that care 490d522f475Smrg * about padding generally store the code in a short, which does not have 491d522f475Smrg * enough bits for the extended values. 492d522f475Smrg */ 493d522f475Smrg#ifdef B38400 /* everyone should define this */ 494d522f475Smrg#define VAL_LINE_SPEED B38400 495d522f475Smrg#else /* ...but xterm's used this for a long time */ 496d522f475Smrg#define VAL_LINE_SPEED B9600 497d522f475Smrg#endif 498d522f475Smrg 499d522f475Smrg/* 500d522f475Smrg * Allow use of system default characters if defined and reasonable. 501d522f475Smrg * These are based on the BSD ttydefaults.h 502d522f475Smrg */ 503d522f475Smrg#ifndef CBRK 504d522f475Smrg#define CBRK 0xff /* was 0 */ 505d522f475Smrg#endif 506d522f475Smrg#ifndef CDISCARD 507d522f475Smrg#define CDISCARD CONTROL('O') 508d522f475Smrg#endif 509d522f475Smrg#ifndef CDSUSP 510d522f475Smrg#define CDSUSP CONTROL('Y') 511d522f475Smrg#endif 512d522f475Smrg#ifndef CEOF 513d522f475Smrg#define CEOF CONTROL('D') 514d522f475Smrg#endif 515d522f475Smrg#ifndef CEOL 516d522f475Smrg#define CEOL 0xff /* was 0 */ 517d522f475Smrg#endif 518d522f475Smrg#ifndef CERASE 519d522f475Smrg#define CERASE 0177 520d522f475Smrg#endif 521d522f475Smrg#ifndef CERASE2 522d522f475Smrg#define CERASE2 CONTROL('H') 523d522f475Smrg#endif 524d522f475Smrg#ifndef CFLUSH 525d522f475Smrg#define CFLUSH CONTROL('O') 526d522f475Smrg#endif 527d522f475Smrg#ifndef CINTR 528d522f475Smrg#define CINTR CONTROL('C') 529d522f475Smrg#endif 530d522f475Smrg#ifndef CKILL 531d522f475Smrg#define CKILL CONTROL('U') /* was '@' */ 532d522f475Smrg#endif 533d522f475Smrg#ifndef CLNEXT 534d522f475Smrg#define CLNEXT CONTROL('V') 535d522f475Smrg#endif 536d522f475Smrg#ifndef CNUL 537d522f475Smrg#define CNUL 0 538d522f475Smrg#endif 539d522f475Smrg#ifndef CQUIT 540d522f475Smrg#define CQUIT CONTROL('\\') 541d522f475Smrg#endif 542d522f475Smrg#ifndef CRPRNT 543d522f475Smrg#define CRPRNT CONTROL('R') 544d522f475Smrg#endif 545d522f475Smrg#ifndef CREPRINT 546d522f475Smrg#define CREPRINT CRPRNT 547d522f475Smrg#endif 548d522f475Smrg#ifndef CSTART 549d522f475Smrg#define CSTART CONTROL('Q') 550d522f475Smrg#endif 551d522f475Smrg#ifndef CSTATUS 552d522f475Smrg#define CSTATUS CONTROL('T') 553d522f475Smrg#endif 554d522f475Smrg#ifndef CSTOP 555d522f475Smrg#define CSTOP CONTROL('S') 556d522f475Smrg#endif 557d522f475Smrg#ifndef CSUSP 558d522f475Smrg#define CSUSP CONTROL('Z') 559d522f475Smrg#endif 560d522f475Smrg#ifndef CSWTCH 561d522f475Smrg#define CSWTCH 0 562d522f475Smrg#endif 563d522f475Smrg#ifndef CWERASE 564d522f475Smrg#define CWERASE CONTROL('W') 565d522f475Smrg#endif 566d522f475Smrg 567d522f475Smrg#ifdef USE_ANY_SYSV_TERMIO 568d522f475Smrg#define TERMIO_STRUCT struct termio 569d522f475Smrg#define ttySetAttr(fd, datap) ioctl(fd, TCSETA, datap) 570d522f475Smrg#define ttyGetAttr(fd, datap) ioctl(fd, TCGETA, datap) 571d522f475Smrg#define ttyFlush(fd) ioctl(fd, TCFLSH, 1) 572d522f475Smrg#elif defined(USE_POSIX_TERMIOS) 573d522f475Smrg#define TERMIO_STRUCT struct termios 574d522f475Smrg#define ttySetAttr(fd, datap) tcsetattr(fd, TCSANOW, datap) 575d522f475Smrg#define ttyGetAttr(fd, datap) tcgetattr(fd, datap) 576d522f475Smrg#define ttyFlush(fd) tcflush(fd, TCOFLUSH) 577d522f475Smrg#endif /* USE_ANY_SYSV_TERMIO */ 578d522f475Smrg 579d522f475Smrg#ifndef VMS 580d522f475Smrg#ifdef TERMIO_STRUCT 581d522f475Smrg/* The following structures are initialized in main() in order 582d522f475Smrg** to eliminate any assumptions about the internal order of their 583d522f475Smrg** contents. 584d522f475Smrg*/ 585d522f475Smrgstatic TERMIO_STRUCT d_tio; 586d522f475Smrg 587d522f475Smrg#ifdef HAS_LTCHARS 588d522f475Smrgstatic struct ltchars d_ltc; 589d522f475Smrg#endif /* HAS_LTCHARS */ 590d522f475Smrg 591d522f475Smrg#ifdef TIOCLSET 592d522f475Smrgstatic unsigned int d_lmode; 593d522f475Smrg#endif /* TIOCLSET */ 594d522f475Smrg 595d522f475Smrg#else /* !TERMIO_STRUCT */ 596d522f475Smrgstatic struct sgttyb d_sg = 597d522f475Smrg{ 598d522f475Smrg 0, 0, 0177, CKILL, (EVENP | ODDP | ECHO | XTABS | CRMOD) 599d522f475Smrg}; 600d522f475Smrgstatic struct tchars d_tc = 601d522f475Smrg{ 602d522f475Smrg CINTR, CQUIT, CSTART, 603d522f475Smrg CSTOP, CEOF, CBRK 604d522f475Smrg}; 605d522f475Smrgstatic struct ltchars d_ltc = 606d522f475Smrg{ 607d522f475Smrg CSUSP, CDSUSP, CRPRNT, 608d522f475Smrg CFLUSH, CWERASE, CLNEXT 609d522f475Smrg}; 610d522f475Smrgstatic int d_disipline = NTTYDISC; 611d522f475Smrgstatic long int d_lmode = LCRTBS | LCRTERA | LCRTKIL | LCTLECH; 612d522f475Smrg#ifdef sony 613d522f475Smrgstatic long int d_jmode = KM_SYSSJIS | KM_ASCII; 614d522f475Smrgstatic struct jtchars d_jtc = 615d522f475Smrg{ 616d522f475Smrg 'J', 'B' 617d522f475Smrg}; 618d522f475Smrg#endif /* sony */ 619d522f475Smrg#endif /* TERMIO_STRUCT */ 620d522f475Smrg#endif /* ! VMS */ 621d522f475Smrg 622d522f475Smrg/* 623d522f475Smrg * SYSV has the termio.c_cc[V] and ltchars; BSD has tchars and ltchars; 624d522f475Smrg * SVR4 has only termio.c_cc, but it includes everything from ltchars. 625d522f475Smrg * POSIX termios has termios.c_cc, which is similar to SVR4. 626d522f475Smrg */ 627d522f475Smrg#define TTYMODE(name) { name, sizeof(name)-1, 0, 0 } 628d522f475Smrgstatic Boolean override_tty_modes = False; 629d522f475Smrg/* *INDENT-OFF* */ 630d522f475Smrgstatic struct _xttymodes { 63120d2c4d2Smrg const char *name; 632d522f475Smrg size_t len; 633d522f475Smrg int set; 634d522f475Smrg int value; 635d522f475Smrg} ttymodelist[] = { 636d522f475Smrg TTYMODE("intr"), /* tchars.t_intrc ; VINTR */ 637d522f475Smrg#define XTTYMODE_intr 0 638d522f475Smrg TTYMODE("quit"), /* tchars.t_quitc ; VQUIT */ 639d522f475Smrg#define XTTYMODE_quit 1 640d522f475Smrg TTYMODE("erase"), /* sgttyb.sg_erase ; VERASE */ 641d522f475Smrg#define XTTYMODE_erase 2 642d522f475Smrg TTYMODE("kill"), /* sgttyb.sg_kill ; VKILL */ 643d522f475Smrg#define XTTYMODE_kill 3 644d522f475Smrg TTYMODE("eof"), /* tchars.t_eofc ; VEOF */ 645d522f475Smrg#define XTTYMODE_eof 4 646d522f475Smrg TTYMODE("eol"), /* VEOL */ 647d522f475Smrg#define XTTYMODE_eol 5 648d522f475Smrg TTYMODE("swtch"), /* VSWTCH */ 649d522f475Smrg#define XTTYMODE_swtch 6 650d522f475Smrg TTYMODE("start"), /* tchars.t_startc ; VSTART */ 651d522f475Smrg#define XTTYMODE_start 7 652d522f475Smrg TTYMODE("stop"), /* tchars.t_stopc ; VSTOP */ 653d522f475Smrg#define XTTYMODE_stop 8 654d522f475Smrg TTYMODE("brk"), /* tchars.t_brkc */ 655d522f475Smrg#define XTTYMODE_brk 9 656d522f475Smrg TTYMODE("susp"), /* ltchars.t_suspc ; VSUSP */ 657d522f475Smrg#define XTTYMODE_susp 10 658d522f475Smrg TTYMODE("dsusp"), /* ltchars.t_dsuspc ; VDSUSP */ 659d522f475Smrg#define XTTYMODE_dsusp 11 660d522f475Smrg TTYMODE("rprnt"), /* ltchars.t_rprntc ; VREPRINT */ 661d522f475Smrg#define XTTYMODE_rprnt 12 662d522f475Smrg TTYMODE("flush"), /* ltchars.t_flushc ; VDISCARD */ 663d522f475Smrg#define XTTYMODE_flush 13 664d522f475Smrg TTYMODE("weras"), /* ltchars.t_werasc ; VWERASE */ 665d522f475Smrg#define XTTYMODE_weras 14 666d522f475Smrg TTYMODE("lnext"), /* ltchars.t_lnextc ; VLNEXT */ 667d522f475Smrg#define XTTYMODE_lnext 15 668d522f475Smrg TTYMODE("status"), /* VSTATUS */ 669d522f475Smrg#define XTTYMODE_status 16 670d522f475Smrg TTYMODE("erase2"), /* VERASE2 */ 671d522f475Smrg#define XTTYMODE_erase2 17 672d522f475Smrg TTYMODE("eol2"), /* VEOL2 */ 673d522f475Smrg#define XTTYMODE_eol2 18 674d522f475Smrg { NULL, 0, 0, '\0' }, /* end of data */ 675d522f475Smrg}; 676d522f475Smrg 677d522f475Smrg#define validTtyChar(data, n) \ 678d522f475Smrg (known_ttyChars[n].sysMode >= 0 && \ 679d522f475Smrg known_ttyChars[n].sysMode < (int) XtNumber(data.c_cc)) 680d522f475Smrg 681d522f475Smrgstatic const struct { 682d522f475Smrg int sysMode; 683d522f475Smrg int myMode; 684d522f475Smrg int myDefault; 685d522f475Smrg} known_ttyChars[] = { 686d522f475Smrg#ifdef VINTR 687d522f475Smrg { VINTR, XTTYMODE_intr, CINTR }, 688d522f475Smrg#endif 689d522f475Smrg#ifdef VQUIT 690d522f475Smrg { VQUIT, XTTYMODE_quit, CQUIT }, 691d522f475Smrg#endif 692d522f475Smrg#ifdef VERASE 693d522f475Smrg { VERASE, XTTYMODE_erase, CERASE }, 694d522f475Smrg#endif 695d522f475Smrg#ifdef VKILL 696d522f475Smrg { VKILL, XTTYMODE_kill, CKILL }, 697d522f475Smrg#endif 698d522f475Smrg#ifdef VEOF 699d522f475Smrg { VEOF, XTTYMODE_eof, CEOF }, 700d522f475Smrg#endif 701d522f475Smrg#ifdef VEOL 702d522f475Smrg { VEOL, XTTYMODE_eol, CEOL }, 703d522f475Smrg#endif 704d522f475Smrg#ifdef VSWTCH 705d522f475Smrg { VSWTCH, XTTYMODE_swtch, CNUL }, 706d522f475Smrg#endif 707d522f475Smrg#ifdef VSTART 708d522f475Smrg { VSTART, XTTYMODE_start, CSTART }, 709d522f475Smrg#endif 710d522f475Smrg#ifdef VSTOP 711d522f475Smrg { VSTOP, XTTYMODE_stop, CSTOP }, 712d522f475Smrg#endif 713d522f475Smrg#ifdef VSUSP 714d522f475Smrg { VSUSP, XTTYMODE_susp, CSUSP }, 715d522f475Smrg#endif 716d522f475Smrg#ifdef VDSUSP 717d522f475Smrg { VDSUSP, XTTYMODE_dsusp, CDSUSP }, 718d522f475Smrg#endif 719d522f475Smrg#ifdef VREPRINT 720d522f475Smrg { VREPRINT, XTTYMODE_rprnt, CREPRINT }, 721d522f475Smrg#endif 722d522f475Smrg#ifdef VDISCARD 723d522f475Smrg { VDISCARD, XTTYMODE_flush, CDISCARD }, 724d522f475Smrg#endif 725d522f475Smrg#ifdef VWERASE 726d522f475Smrg { VWERASE, XTTYMODE_weras, CWERASE }, 727d522f475Smrg#endif 728d522f475Smrg#ifdef VLNEXT 729d522f475Smrg { VLNEXT, XTTYMODE_lnext, CLNEXT }, 730d522f475Smrg#endif 731d522f475Smrg#ifdef VSTATUS 732d522f475Smrg { VSTATUS, XTTYMODE_status, CSTATUS }, 733d522f475Smrg#endif 734d522f475Smrg#ifdef VERASE2 735d522f475Smrg { VERASE2, XTTYMODE_erase2, CERASE2 }, 736d522f475Smrg#endif 737d522f475Smrg#ifdef VEOL2 738d522f475Smrg { VEOL2, XTTYMODE_eol2, CNUL }, 739d522f475Smrg#endif 740d522f475Smrg}; 741d522f475Smrg/* *INDENT-ON* */ 742d522f475Smrg 7430bd37d32Smrg#define TMODE(ind,var) if (ttymodelist[ind].set) var = (cc_t) ttymodelist[ind].value 744d522f475Smrg 745d522f475Smrgstatic int parse_tty_modes(char *s, struct _xttymodes *modelist); 746d522f475Smrg 747d522f475Smrg#ifndef USE_UTEMPTER 748d522f475Smrg#ifdef USE_SYSV_UTMP 749d522f475Smrg#if (defined(AIXV3) && (OSMAJORVERSION < 4)) && !(defined(getutid)) 750d522f475Smrgextern struct utmp *getutid(); 751d522f475Smrg#endif /* AIXV3 */ 752d522f475Smrg 753d522f475Smrg#else /* not USE_SYSV_UTMP */ 754d522f475Smrgstatic char etc_utmp[] = UTMP_FILENAME; 755d522f475Smrg#endif /* USE_SYSV_UTMP */ 756d522f475Smrg 757d522f475Smrg#if defined(USE_LASTLOG) && defined(USE_STRUCT_LASTLOG) 758d522f475Smrgstatic char etc_lastlog[] = LASTLOG_FILENAME; 759d522f475Smrg#else 760d522f475Smrg#undef USE_LASTLOG 761d522f475Smrg#endif 762d522f475Smrg 763d522f475Smrg#ifdef WTMP 764d522f475Smrgstatic char etc_wtmp[] = WTMP_FILENAME; 765d522f475Smrg#endif 766d522f475Smrg#endif /* !USE_UTEMPTER */ 767d522f475Smrg 768d522f475Smrg/* 769d522f475Smrg * Some people with 4.3bsd /bin/login seem to like to use login -p -f user 770d522f475Smrg * to implement xterm -ls. They can turn on USE_LOGIN_DASH_P and turn off 771d522f475Smrg * WTMP and USE_LASTLOG. 772d522f475Smrg */ 773d522f475Smrg#ifdef USE_LOGIN_DASH_P 774d522f475Smrg#ifndef LOGIN_FILENAME 775d522f475Smrg#define LOGIN_FILENAME "/bin/login" 776d522f475Smrg#endif 777d522f475Smrgstatic char bin_login[] = LOGIN_FILENAME; 778d522f475Smrg#endif 779d522f475Smrg 780d522f475Smrgstatic char passedPty[PTYCHARLEN + 1]; /* name if pty if slave */ 781d522f475Smrg 782d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 783d522f475Smrgstatic int Console; 784d522f475Smrg#include <X11/Xmu/SysUtil.h> /* XmuGetHostname */ 785d522f475Smrg#define MIT_CONSOLE_LEN 12 786d522f475Smrg#define MIT_CONSOLE "MIT_CONSOLE_" 787d522f475Smrgstatic char mit_console_name[255 + MIT_CONSOLE_LEN + 1] = MIT_CONSOLE; 788d522f475Smrgstatic Atom mit_console; 789d522f475Smrg#endif /* TIOCCONS */ 790d522f475Smrg 791d522f475Smrg#ifndef USE_SYSV_UTMP 792d522f475Smrgstatic int tslot; 793d522f475Smrg#endif /* USE_SYSV_UTMP */ 794d522f475Smrgstatic sigjmp_buf env; 795d522f475Smrg 796d522f475Smrg#define SetUtmpHost(dst, screen) \ 797d522f475Smrg { \ 798d522f475Smrg char host[sizeof(dst) + 1]; \ 799d522f475Smrg strncpy(host, DisplayString(screen->display), sizeof(host)); \ 800d522f475Smrg TRACE(("DisplayString(%s)\n", host)); \ 801d522f475Smrg if (!resource.utmpDisplayId) { \ 802d522f475Smrg char *endptr = strrchr(host, ':'); \ 803d522f475Smrg if (endptr) { \ 804d522f475Smrg TRACE(("trimming display-id '%s'\n", host)); \ 805d522f475Smrg *endptr = '\0'; \ 806d522f475Smrg } \ 807d522f475Smrg } \ 808894e0ac8Smrg copy_filled(dst, host, sizeof(dst)); \ 809d522f475Smrg } 810d522f475Smrg 811d522f475Smrg#ifdef HAVE_UTMP_UT_SYSLEN 812d522f475Smrg# define SetUtmpSysLen(utmp) \ 813d522f475Smrg { \ 814d522f475Smrg utmp.ut_host[sizeof(utmp.ut_host)-1] = '\0'; \ 815d522f475Smrg utmp.ut_syslen = strlen(utmp.ut_host) + 1; \ 816d522f475Smrg } 817d522f475Smrg#endif 818d522f475Smrg 819d522f475Smrg/* used by VT (charproc.c) */ 820d522f475Smrg 821d522f475Smrgstatic XtResource application_resources[] = 822d522f475Smrg{ 823d522f475Smrg Sres("iconGeometry", "IconGeometry", icon_geometry, NULL), 824d522f475Smrg Sres(XtNtitle, XtCTitle, title, NULL), 8250bd37d32Smrg Sres(XtNiconHint, XtCIconHint, icon_hint, NULL), 826d522f475Smrg Sres(XtNiconName, XtCIconName, icon_name, NULL), 827d522f475Smrg Sres("termName", "TermName", term_name, NULL), 828d522f475Smrg Sres("ttyModes", "TtyModes", tty_modes, NULL), 829d522f475Smrg Bres("hold", "Hold", hold_screen, False), 830d522f475Smrg Bres("utmpInhibit", "UtmpInhibit", utmpInhibit, False), 831d522f475Smrg Bres("utmpDisplayId", "UtmpDisplayId", utmpDisplayId, True), 832d522f475Smrg Bres("messages", "Messages", messages, True), 833d522f475Smrg Ires("minBufSize", "MinBufSize", minBufSize, 4096), 834d522f475Smrg Ires("maxBufSize", "MaxBufSize", maxBufSize, 32768), 83520d2c4d2Smrg Sres("menuLocale", "MenuLocale", menuLocale, DEF_MENU_LOCALE), 836a1f3da82Smrg Sres("omitTranslation", "OmitTranslation", omitTranslation, NULL), 837d522f475Smrg Sres("keyboardType", "KeyboardType", keyboardType, "unknown"), 838e39b573cSmrg#if OPT_PRINT_ON_EXIT 839e39b573cSmrg Ires("printModeImmediate", "PrintModeImmediate", printModeNow, 0), 840e39b573cSmrg Ires("printOptsImmediate", "PrintOptsImmediate", printOptsNow, 9), 841e39b573cSmrg Sres("printFileImmediate", "PrintFileImmediate", printFileNow, NULL), 842e39b573cSmrg Ires("printModeOnXError", "PrintModeOnXError", printModeOnXError, 0), 843e39b573cSmrg Ires("printOptsOnXError", "PrintOptsOnXError", printOptsOnXError, 9), 844e39b573cSmrg Sres("printFileOnXError", "PrintFileOnXError", printFileOnXError, NULL), 845e39b573cSmrg#endif 846d522f475Smrg#if OPT_SUNPC_KBD 847d522f475Smrg Bres("sunKeyboard", "SunKeyboard", sunKeyboard, False), 848d522f475Smrg#endif 849d522f475Smrg#if OPT_HP_FUNC_KEYS 850d522f475Smrg Bres("hpFunctionKeys", "HpFunctionKeys", hpFunctionKeys, False), 851d522f475Smrg#endif 852d522f475Smrg#if OPT_SCO_FUNC_KEYS 853d522f475Smrg Bres("scoFunctionKeys", "ScoFunctionKeys", scoFunctionKeys, False), 854d522f475Smrg#endif 855d522f475Smrg#if OPT_SUN_FUNC_KEYS 856d522f475Smrg Bres("sunFunctionKeys", "SunFunctionKeys", sunFunctionKeys, False), 857d522f475Smrg#endif 858d522f475Smrg#if OPT_TCAP_FKEYS 859d522f475Smrg Bres("tcapFunctionKeys", "TcapFunctionKeys", termcapKeys, False), 860d522f475Smrg#endif 861d522f475Smrg#if OPT_INITIAL_ERASE 862d522f475Smrg Bres("ptyInitialErase", "PtyInitialErase", ptyInitialErase, DEF_INITIAL_ERASE), 863d522f475Smrg Bres("backarrowKeyIsErase", "BackarrowKeyIsErase", backarrow_is_erase, DEF_BACKARO_ERASE), 864d522f475Smrg#endif 865d522f475Smrg Bres("useInsertMode", "UseInsertMode", useInsertMode, False), 866d522f475Smrg#if OPT_ZICONBEEP 867d522f475Smrg Ires("zIconBeep", "ZIconBeep", zIconBeep, 0), 8680bd37d32Smrg Sres("zIconTitleFormat", "ZIconTitleFormat", zIconFormat, "*** %s"), 869d522f475Smrg#endif 870d522f475Smrg#if OPT_PTY_HANDSHAKE 871d522f475Smrg Bres("waitForMap", "WaitForMap", wait_for_map, False), 872d522f475Smrg Bres("ptyHandshake", "PtyHandshake", ptyHandshake, True), 873d522f475Smrg Bres("ptySttySize", "PtySttySize", ptySttySize, DEF_PTY_STTY_SIZE), 874d522f475Smrg#endif 875e0a2b6dfSmrg#if OPT_REPORT_COLORS 876e0a2b6dfSmrg Bres("reportColors", "ReportColors", reportColors, False), 877e0a2b6dfSmrg#endif 878e0a2b6dfSmrg#if OPT_REPORT_FONTS 879e0a2b6dfSmrg Bres("reportFonts", "ReportFonts", reportFonts, False), 880e0a2b6dfSmrg#endif 881d522f475Smrg#if OPT_SAME_NAME 882d522f475Smrg Bres("sameName", "SameName", sameName, True), 883d522f475Smrg#endif 884d522f475Smrg#if OPT_SESSION_MGT 885d522f475Smrg Bres("sessionMgt", "SessionMgt", sessionMgt, True), 886d522f475Smrg#endif 887d522f475Smrg#if OPT_TOOLBAR 888d522f475Smrg Bres(XtNtoolBar, XtCToolBar, toolBar, True), 889d522f475Smrg#endif 890956cc18dSsnj#if OPT_MAXIMIZE 891956cc18dSsnj Bres(XtNmaximized, XtCMaximized, maximized, False), 892a1f3da82Smrg Sres(XtNfullscreen, XtCFullscreen, fullscreen_s, "off"), 893956cc18dSsnj#endif 894d522f475Smrg}; 895d522f475Smrg 89620d2c4d2Smrgstatic String fallback_resources[] = 897d522f475Smrg{ 898e39b573cSmrg#if OPT_TOOLBAR 899e39b573cSmrg "*toolBar: false", 900e39b573cSmrg#endif 901d522f475Smrg "*SimpleMenu*menuLabel.vertSpace: 100", 902d522f475Smrg "*SimpleMenu*HorizontalMargins: 16", 903d522f475Smrg "*SimpleMenu*Sme.height: 16", 904d522f475Smrg "*SimpleMenu*Cursor: left_ptr", 905d522f475Smrg "*mainMenu.Label: Main Options (no app-defaults)", 906d522f475Smrg "*vtMenu.Label: VT Options (no app-defaults)", 907d522f475Smrg "*fontMenu.Label: VT Fonts (no app-defaults)", 908d522f475Smrg#if OPT_TEK4014 909d522f475Smrg "*tekMenu.Label: Tek Options (no app-defaults)", 910d522f475Smrg#endif 911d522f475Smrg NULL 912d522f475Smrg}; 913d522f475Smrg 914d522f475Smrg/* Command line options table. Only resources are entered here...there is a 915d522f475Smrg pass over the remaining options after XrmParseCommand is let loose. */ 916d522f475Smrg/* *INDENT-OFF* */ 917d522f475Smrgstatic XrmOptionDescRec optionDescList[] = { 91820d2c4d2Smrg{"-geometry", "*vt100.geometry",XrmoptionSepArg, (XPointer) NULL}, 91920d2c4d2Smrg{"-132", "*c132", XrmoptionNoArg, (XPointer) "on"}, 92020d2c4d2Smrg{"+132", "*c132", XrmoptionNoArg, (XPointer) "off"}, 92120d2c4d2Smrg{"-ah", "*alwaysHighlight", XrmoptionNoArg, (XPointer) "on"}, 92220d2c4d2Smrg{"+ah", "*alwaysHighlight", XrmoptionNoArg, (XPointer) "off"}, 92320d2c4d2Smrg{"-aw", "*autoWrap", XrmoptionNoArg, (XPointer) "on"}, 92420d2c4d2Smrg{"+aw", "*autoWrap", XrmoptionNoArg, (XPointer) "off"}, 925d522f475Smrg#ifndef NO_ACTIVE_ICON 92620d2c4d2Smrg{"-ai", "*activeIcon", XrmoptionNoArg, (XPointer) "off"}, 92720d2c4d2Smrg{"+ai", "*activeIcon", XrmoptionNoArg, (XPointer) "on"}, 928d522f475Smrg#endif /* NO_ACTIVE_ICON */ 92920d2c4d2Smrg{"-b", "*internalBorder",XrmoptionSepArg, (XPointer) NULL}, 93020d2c4d2Smrg{"-bc", "*cursorBlink", XrmoptionNoArg, (XPointer) "on"}, 93120d2c4d2Smrg{"+bc", "*cursorBlink", XrmoptionNoArg, (XPointer) "off"}, 93220d2c4d2Smrg{"-bcf", "*cursorOffTime",XrmoptionSepArg, (XPointer) NULL}, 93320d2c4d2Smrg{"-bcn", "*cursorOnTime",XrmoptionSepArg, (XPointer) NULL}, 93420d2c4d2Smrg{"-bdc", "*colorBDMode", XrmoptionNoArg, (XPointer) "off"}, 93520d2c4d2Smrg{"+bdc", "*colorBDMode", XrmoptionNoArg, (XPointer) "on"}, 93620d2c4d2Smrg{"-cb", "*cutToBeginningOfLine", XrmoptionNoArg, (XPointer) "off"}, 93720d2c4d2Smrg{"+cb", "*cutToBeginningOfLine", XrmoptionNoArg, (XPointer) "on"}, 93820d2c4d2Smrg{"-cc", "*charClass", XrmoptionSepArg, (XPointer) NULL}, 93920d2c4d2Smrg{"-cm", "*colorMode", XrmoptionNoArg, (XPointer) "off"}, 94020d2c4d2Smrg{"+cm", "*colorMode", XrmoptionNoArg, (XPointer) "on"}, 94120d2c4d2Smrg{"-cn", "*cutNewline", XrmoptionNoArg, (XPointer) "off"}, 94220d2c4d2Smrg{"+cn", "*cutNewline", XrmoptionNoArg, (XPointer) "on"}, 94320d2c4d2Smrg{"-cr", "*cursorColor", XrmoptionSepArg, (XPointer) NULL}, 94420d2c4d2Smrg{"-cu", "*curses", XrmoptionNoArg, (XPointer) "on"}, 94520d2c4d2Smrg{"+cu", "*curses", XrmoptionNoArg, (XPointer) "off"}, 94620d2c4d2Smrg{"-dc", "*dynamicColors",XrmoptionNoArg, (XPointer) "off"}, 94720d2c4d2Smrg{"+dc", "*dynamicColors",XrmoptionNoArg, (XPointer) "on"}, 94820d2c4d2Smrg{"-fb", "*boldFont", XrmoptionSepArg, (XPointer) NULL}, 94920d2c4d2Smrg{"-fbb", "*freeBoldBox", XrmoptionNoArg, (XPointer)"off"}, 95020d2c4d2Smrg{"+fbb", "*freeBoldBox", XrmoptionNoArg, (XPointer)"on"}, 95120d2c4d2Smrg{"-fbx", "*forceBoxChars", XrmoptionNoArg, (XPointer)"off"}, 95220d2c4d2Smrg{"+fbx", "*forceBoxChars", XrmoptionNoArg, (XPointer)"on"}, 953d522f475Smrg#ifndef NO_ACTIVE_ICON 95420d2c4d2Smrg{"-fi", "*iconFont", XrmoptionSepArg, (XPointer) NULL}, 955d522f475Smrg#endif /* NO_ACTIVE_ICON */ 956d522f475Smrg#if OPT_RENDERFONT 95720d2c4d2Smrg{"-fa", "*faceName", XrmoptionSepArg, (XPointer) NULL}, 95820d2c4d2Smrg{"-fd", "*faceNameDoublesize", XrmoptionSepArg, (XPointer) NULL}, 95920d2c4d2Smrg{"-fs", "*faceSize", XrmoptionSepArg, (XPointer) NULL}, 960d522f475Smrg#endif 961d522f475Smrg#if OPT_WIDE_CHARS 96220d2c4d2Smrg{"-fw", "*wideFont", XrmoptionSepArg, (XPointer) NULL}, 96320d2c4d2Smrg{"-fwb", "*wideBoldFont", XrmoptionSepArg, (XPointer) NULL}, 964d522f475Smrg#endif 965d522f475Smrg#if OPT_INPUT_METHOD 96620d2c4d2Smrg{"-fx", "*ximFont", XrmoptionSepArg, (XPointer) NULL}, 967d522f475Smrg#endif 968d522f475Smrg#if OPT_HIGHLIGHT_COLOR 96920d2c4d2Smrg{"-hc", "*highlightColor", XrmoptionSepArg, (XPointer) NULL}, 97020d2c4d2Smrg{"-hm", "*highlightColorMode", XrmoptionNoArg, (XPointer) "on"}, 97120d2c4d2Smrg{"+hm", "*highlightColorMode", XrmoptionNoArg, (XPointer) "off"}, 97220d2c4d2Smrg{"-selfg", "*highlightTextColor", XrmoptionSepArg, (XPointer) NULL}, 97320d2c4d2Smrg{"-selbg", "*highlightColor", XrmoptionSepArg, (XPointer) NULL}, 974d522f475Smrg#endif 975d522f475Smrg#if OPT_HP_FUNC_KEYS 97620d2c4d2Smrg{"-hf", "*hpFunctionKeys",XrmoptionNoArg, (XPointer) "on"}, 97720d2c4d2Smrg{"+hf", "*hpFunctionKeys",XrmoptionNoArg, (XPointer) "off"}, 978d522f475Smrg#endif 97920d2c4d2Smrg{"-hold", "*hold", XrmoptionNoArg, (XPointer) "on"}, 98020d2c4d2Smrg{"+hold", "*hold", XrmoptionNoArg, (XPointer) "off"}, 981d522f475Smrg#if OPT_INITIAL_ERASE 98220d2c4d2Smrg{"-ie", "*ptyInitialErase", XrmoptionNoArg, (XPointer) "on"}, 98320d2c4d2Smrg{"+ie", "*ptyInitialErase", XrmoptionNoArg, (XPointer) "off"}, 984d522f475Smrg#endif 98520d2c4d2Smrg{"-j", "*jumpScroll", XrmoptionNoArg, (XPointer) "on"}, 98620d2c4d2Smrg{"+j", "*jumpScroll", XrmoptionNoArg, (XPointer) "off"}, 987d522f475Smrg#if OPT_C1_PRINT 98820d2c4d2Smrg{"-k8", "*allowC1Printable", XrmoptionNoArg, (XPointer) "on"}, 98920d2c4d2Smrg{"+k8", "*allowC1Printable", XrmoptionNoArg, (XPointer) "off"}, 990d522f475Smrg#endif 99120d2c4d2Smrg{"-kt", "*keyboardType", XrmoptionSepArg, (XPointer) NULL}, 992d522f475Smrg/* parse logging options anyway for compatibility */ 99320d2c4d2Smrg{"-l", "*logging", XrmoptionNoArg, (XPointer) "on"}, 99420d2c4d2Smrg{"+l", "*logging", XrmoptionNoArg, (XPointer) "off"}, 99520d2c4d2Smrg{"-lf", "*logFile", XrmoptionSepArg, (XPointer) NULL}, 99620d2c4d2Smrg{"-ls", "*loginShell", XrmoptionNoArg, (XPointer) "on"}, 99720d2c4d2Smrg{"+ls", "*loginShell", XrmoptionNoArg, (XPointer) "off"}, 99820d2c4d2Smrg{"-mb", "*marginBell", XrmoptionNoArg, (XPointer) "on"}, 99920d2c4d2Smrg{"+mb", "*marginBell", XrmoptionNoArg, (XPointer) "off"}, 100020d2c4d2Smrg{"-mc", "*multiClickTime", XrmoptionSepArg, (XPointer) NULL}, 100120d2c4d2Smrg{"-mesg", "*messages", XrmoptionNoArg, (XPointer) "off"}, 100220d2c4d2Smrg{"+mesg", "*messages", XrmoptionNoArg, (XPointer) "on"}, 100320d2c4d2Smrg{"-ms", "*pointerColor",XrmoptionSepArg, (XPointer) NULL}, 100420d2c4d2Smrg{"-nb", "*nMarginBell", XrmoptionSepArg, (XPointer) NULL}, 100520d2c4d2Smrg{"-nul", "*underLine", XrmoptionNoArg, (XPointer) "off"}, 100620d2c4d2Smrg{"+nul", "*underLine", XrmoptionNoArg, (XPointer) "on"}, 100720d2c4d2Smrg{"-pc", "*boldColors", XrmoptionNoArg, (XPointer) "on"}, 100820d2c4d2Smrg{"+pc", "*boldColors", XrmoptionNoArg, (XPointer) "off"}, 100920d2c4d2Smrg{"-rw", "*reverseWrap", XrmoptionNoArg, (XPointer) "on"}, 101020d2c4d2Smrg{"+rw", "*reverseWrap", XrmoptionNoArg, (XPointer) "off"}, 101120d2c4d2Smrg{"-s", "*multiScroll", XrmoptionNoArg, (XPointer) "on"}, 101220d2c4d2Smrg{"+s", "*multiScroll", XrmoptionNoArg, (XPointer) "off"}, 101320d2c4d2Smrg{"-sb", "*scrollBar", XrmoptionNoArg, (XPointer) "on"}, 101420d2c4d2Smrg{"+sb", "*scrollBar", XrmoptionNoArg, (XPointer) "off"}, 1015e0a2b6dfSmrg#if OPT_REPORT_COLORS 1016e0a2b6dfSmrg{"-report-colors","*reportColors", XrmoptionNoArg, (XPointer) "on"}, 1017e0a2b6dfSmrg#endif 1018e0a2b6dfSmrg#if OPT_REPORT_FONTS 1019e0a2b6dfSmrg{"-report-fonts","*reportFonts", XrmoptionNoArg, (XPointer) "on"}, 1020e0a2b6dfSmrg#endif 1021d522f475Smrg#ifdef SCROLLBAR_RIGHT 102220d2c4d2Smrg{"-leftbar", "*rightScrollBar", XrmoptionNoArg, (XPointer) "off"}, 102320d2c4d2Smrg{"-rightbar", "*rightScrollBar", XrmoptionNoArg, (XPointer) "on"}, 102420d2c4d2Smrg#endif 102520d2c4d2Smrg{"-rvc", "*colorRVMode", XrmoptionNoArg, (XPointer) "off"}, 102620d2c4d2Smrg{"+rvc", "*colorRVMode", XrmoptionNoArg, (XPointer) "on"}, 102720d2c4d2Smrg{"-sf", "*sunFunctionKeys", XrmoptionNoArg, (XPointer) "on"}, 102820d2c4d2Smrg{"+sf", "*sunFunctionKeys", XrmoptionNoArg, (XPointer) "off"}, 10290bd37d32Smrg{"-sh", "*scaleHeight", XrmoptionSepArg, (XPointer) NULL}, 103020d2c4d2Smrg{"-si", "*scrollTtyOutput", XrmoptionNoArg, (XPointer) "off"}, 103120d2c4d2Smrg{"+si", "*scrollTtyOutput", XrmoptionNoArg, (XPointer) "on"}, 103220d2c4d2Smrg{"-sk", "*scrollKey", XrmoptionNoArg, (XPointer) "on"}, 103320d2c4d2Smrg{"+sk", "*scrollKey", XrmoptionNoArg, (XPointer) "off"}, 103420d2c4d2Smrg{"-sl", "*saveLines", XrmoptionSepArg, (XPointer) NULL}, 1035d522f475Smrg#if OPT_SUNPC_KBD 103620d2c4d2Smrg{"-sp", "*sunKeyboard", XrmoptionNoArg, (XPointer) "on"}, 103720d2c4d2Smrg{"+sp", "*sunKeyboard", XrmoptionNoArg, (XPointer) "off"}, 1038d522f475Smrg#endif 1039d522f475Smrg#if OPT_TEK4014 104020d2c4d2Smrg{"-t", "*tekStartup", XrmoptionNoArg, (XPointer) "on"}, 104120d2c4d2Smrg{"+t", "*tekStartup", XrmoptionNoArg, (XPointer) "off"}, 1042d522f475Smrg#endif 104320d2c4d2Smrg{"-ti", "*decTerminalID",XrmoptionSepArg, (XPointer) NULL}, 104420d2c4d2Smrg{"-tm", "*ttyModes", XrmoptionSepArg, (XPointer) NULL}, 104520d2c4d2Smrg{"-tn", "*termName", XrmoptionSepArg, (XPointer) NULL}, 1046d522f475Smrg#if OPT_WIDE_CHARS 104720d2c4d2Smrg{"-u8", "*utf8", XrmoptionNoArg, (XPointer) "2"}, 104820d2c4d2Smrg{"+u8", "*utf8", XrmoptionNoArg, (XPointer) "0"}, 1049d522f475Smrg#endif 1050d522f475Smrg#if OPT_LUIT_PROG 105120d2c4d2Smrg{"-lc", "*locale", XrmoptionNoArg, (XPointer) "on"}, 105220d2c4d2Smrg{"+lc", "*locale", XrmoptionNoArg, (XPointer) "off"}, 105320d2c4d2Smrg{"-lcc", "*localeFilter",XrmoptionSepArg, (XPointer) NULL}, 105420d2c4d2Smrg{"-en", "*locale", XrmoptionSepArg, (XPointer) NULL}, 105520d2c4d2Smrg#endif 105620d2c4d2Smrg{"-uc", "*cursorUnderLine", XrmoptionNoArg, (XPointer) "on"}, 105720d2c4d2Smrg{"+uc", "*cursorUnderLine", XrmoptionNoArg, (XPointer) "off"}, 105820d2c4d2Smrg{"-ulc", "*colorULMode", XrmoptionNoArg, (XPointer) "off"}, 105920d2c4d2Smrg{"+ulc", "*colorULMode", XrmoptionNoArg, (XPointer) "on"}, 106020d2c4d2Smrg{"-ulit", "*italicULMode", XrmoptionNoArg, (XPointer) "off"}, 106120d2c4d2Smrg{"+ulit", "*italicULMode", XrmoptionNoArg, (XPointer) "on"}, 106220d2c4d2Smrg{"-ut", "*utmpInhibit", XrmoptionNoArg, (XPointer) "on"}, 106320d2c4d2Smrg{"+ut", "*utmpInhibit", XrmoptionNoArg, (XPointer) "off"}, 106420d2c4d2Smrg{"-im", "*useInsertMode", XrmoptionNoArg, (XPointer) "on"}, 106520d2c4d2Smrg{"+im", "*useInsertMode", XrmoptionNoArg, (XPointer) "off"}, 106620d2c4d2Smrg{"-vb", "*visualBell", XrmoptionNoArg, (XPointer) "on"}, 106720d2c4d2Smrg{"+vb", "*visualBell", XrmoptionNoArg, (XPointer) "off"}, 106820d2c4d2Smrg{"-pob", "*popOnBell", XrmoptionNoArg, (XPointer) "on"}, 106920d2c4d2Smrg{"+pob", "*popOnBell", XrmoptionNoArg, (XPointer) "off"}, 1070d522f475Smrg#if OPT_WIDE_CHARS 107120d2c4d2Smrg{"-wc", "*wideChars", XrmoptionNoArg, (XPointer) "on"}, 107220d2c4d2Smrg{"+wc", "*wideChars", XrmoptionNoArg, (XPointer) "off"}, 107320d2c4d2Smrg{"-mk_width", "*mkWidth", XrmoptionNoArg, (XPointer) "on"}, 107420d2c4d2Smrg{"+mk_width", "*mkWidth", XrmoptionNoArg, (XPointer) "off"}, 107520d2c4d2Smrg{"-cjk_width", "*cjkWidth", XrmoptionNoArg, (XPointer) "on"}, 107620d2c4d2Smrg{"+cjk_width", "*cjkWidth", XrmoptionNoArg, (XPointer) "off"}, 107720d2c4d2Smrg#endif 107820d2c4d2Smrg{"-wf", "*waitForMap", XrmoptionNoArg, (XPointer) "on"}, 107920d2c4d2Smrg{"+wf", "*waitForMap", XrmoptionNoArg, (XPointer) "off"}, 1080d522f475Smrg#if OPT_ZICONBEEP 108120d2c4d2Smrg{"-ziconbeep", "*zIconBeep", XrmoptionSepArg, (XPointer) NULL}, 1082d522f475Smrg#endif 1083d522f475Smrg#if OPT_SAME_NAME 108420d2c4d2Smrg{"-samename", "*sameName", XrmoptionNoArg, (XPointer) "on"}, 108520d2c4d2Smrg{"+samename", "*sameName", XrmoptionNoArg, (XPointer) "off"}, 1086d522f475Smrg#endif 1087d522f475Smrg#if OPT_SESSION_MGT 108820d2c4d2Smrg{"-sm", "*sessionMgt", XrmoptionNoArg, (XPointer) "on"}, 108920d2c4d2Smrg{"+sm", "*sessionMgt", XrmoptionNoArg, (XPointer) "off"}, 1090d522f475Smrg#endif 1091d522f475Smrg#if OPT_TOOLBAR 109220d2c4d2Smrg{"-tb", "*"XtNtoolBar, XrmoptionNoArg, (XPointer) "on"}, 109320d2c4d2Smrg{"+tb", "*"XtNtoolBar, XrmoptionNoArg, (XPointer) "off"}, 1094d522f475Smrg#endif 1095956cc18dSsnj#if OPT_MAXIMIZE 109620d2c4d2Smrg{"-maximized", "*maximized", XrmoptionNoArg, (XPointer) "on"}, 109720d2c4d2Smrg{"+maximized", "*maximized", XrmoptionNoArg, (XPointer) "off"}, 1098a1f3da82Smrg{"-fullscreen", "*fullscreen", XrmoptionNoArg, (XPointer) "on"}, 1099a1f3da82Smrg{"+fullscreen", "*fullscreen", XrmoptionNoArg, (XPointer) "off"}, 1100956cc18dSsnj#endif 1101d522f475Smrg/* options that we process ourselves */ 110220d2c4d2Smrg{"-help", NULL, XrmoptionSkipNArgs, (XPointer) NULL}, 110320d2c4d2Smrg{"-version", NULL, XrmoptionSkipNArgs, (XPointer) NULL}, 110420d2c4d2Smrg{"-class", NULL, XrmoptionSkipArg, (XPointer) NULL}, 110520d2c4d2Smrg{"-e", NULL, XrmoptionSkipLine, (XPointer) NULL}, 110620d2c4d2Smrg{"-into", NULL, XrmoptionSkipArg, (XPointer) NULL}, 1107d522f475Smrg/* bogus old compatibility stuff for which there are 1108d522f475Smrg standard XtOpenApplication options now */ 110920d2c4d2Smrg{"%", "*tekGeometry", XrmoptionStickyArg, (XPointer) NULL}, 111020d2c4d2Smrg{"#", ".iconGeometry",XrmoptionStickyArg, (XPointer) NULL}, 111120d2c4d2Smrg{"-T", ".title", XrmoptionSepArg, (XPointer) NULL}, 111220d2c4d2Smrg{"-n", "*iconName", XrmoptionSepArg, (XPointer) NULL}, 111320d2c4d2Smrg{"-r", "*reverseVideo",XrmoptionNoArg, (XPointer) "on"}, 111420d2c4d2Smrg{"+r", "*reverseVideo",XrmoptionNoArg, (XPointer) "off"}, 111520d2c4d2Smrg{"-rv", "*reverseVideo",XrmoptionNoArg, (XPointer) "on"}, 111620d2c4d2Smrg{"+rv", "*reverseVideo",XrmoptionNoArg, (XPointer) "off"}, 111720d2c4d2Smrg{"-w", ".borderWidth", XrmoptionSepArg, (XPointer) NULL}, 1118d522f475Smrg}; 1119d522f475Smrg 1120d522f475Smrgstatic OptionHelp xtermOptions[] = { 1121d522f475Smrg{ "-version", "print the version number" }, 1122d522f475Smrg{ "-help", "print out this message" }, 1123d522f475Smrg{ "-display displayname", "X server to contact" }, 1124d522f475Smrg{ "-geometry geom", "size (in characters) and position" }, 1125d522f475Smrg{ "-/+rv", "turn on/off reverse video" }, 1126d522f475Smrg{ "-bg color", "background color" }, 1127d522f475Smrg{ "-fg color", "foreground color" }, 1128d522f475Smrg{ "-bd color", "border color" }, 1129d522f475Smrg{ "-bw number", "border width in pixels" }, 1130d522f475Smrg{ "-fn fontname", "normal text font" }, 1131d522f475Smrg{ "-fb fontname", "bold text font" }, 1132d522f475Smrg{ "-/+fbb", "turn on/off normal/bold font comparison inhibit"}, 1133d522f475Smrg{ "-/+fbx", "turn off/on linedrawing characters"}, 1134d522f475Smrg#if OPT_RENDERFONT 1135d522f475Smrg{ "-fa pattern", "FreeType font-selection pattern" }, 1136d522f475Smrg{ "-fd pattern", "FreeType Doublesize font-selection pattern" }, 1137d522f475Smrg{ "-fs size", "FreeType font-size" }, 1138d522f475Smrg#endif 1139d522f475Smrg#if OPT_WIDE_CHARS 1140d522f475Smrg{ "-fw fontname", "doublewidth text font" }, 1141d522f475Smrg{ "-fwb fontname", "doublewidth bold text font" }, 1142d522f475Smrg#endif 1143d522f475Smrg#if OPT_INPUT_METHOD 1144d522f475Smrg{ "-fx fontname", "XIM fontset" }, 1145d522f475Smrg#endif 1146d522f475Smrg{ "-iconic", "start iconic" }, 1147d522f475Smrg{ "-name string", "client instance, icon, and title strings" }, 1148d522f475Smrg{ "-class string", "class string (XTerm)" }, 1149d522f475Smrg{ "-title string", "title string" }, 1150d522f475Smrg{ "-xrm resourcestring", "additional resource specifications" }, 1151d522f475Smrg{ "-/+132", "turn on/off 80/132 column switching" }, 1152d522f475Smrg{ "-/+ah", "turn on/off always highlight" }, 1153d522f475Smrg#ifndef NO_ACTIVE_ICON 1154d522f475Smrg{ "-/+ai", "turn off/on active icon" }, 1155d522f475Smrg{ "-fi fontname", "icon font for active icon" }, 1156d522f475Smrg#endif /* NO_ACTIVE_ICON */ 1157d522f475Smrg{ "-b number", "internal border in pixels" }, 1158d522f475Smrg{ "-/+bc", "turn on/off text cursor blinking" }, 1159d522f475Smrg{ "-bcf milliseconds", "time text cursor is off when blinking"}, 1160d522f475Smrg{ "-bcn milliseconds", "time text cursor is on when blinking"}, 1161d522f475Smrg{ "-/+bdc", "turn off/on display of bold as color"}, 1162d522f475Smrg{ "-/+cb", "turn on/off cut-to-beginning-of-line inhibit" }, 1163d522f475Smrg{ "-cc classrange", "specify additional character classes" }, 1164d522f475Smrg{ "-/+cm", "turn off/on ANSI color mode" }, 1165d522f475Smrg{ "-/+cn", "turn on/off cut newline inhibit" }, 1166d522f475Smrg{ "-cr color", "text cursor color" }, 1167d522f475Smrg{ "-/+cu", "turn on/off curses emulation" }, 1168d522f475Smrg{ "-/+dc", "turn off/on dynamic color selection" }, 1169d522f475Smrg#if OPT_HIGHLIGHT_COLOR 1170d522f475Smrg{ "-/+hm", "turn on/off selection-color override" }, 1171d522f475Smrg{ "-selbg color", "selection background color" }, 1172d522f475Smrg{ "-selfg color", "selection foreground color" }, 11730bd37d32Smrg/* -hc is deprecated, not shown in help message */ 1174d522f475Smrg#endif 1175d522f475Smrg#if OPT_HP_FUNC_KEYS 1176d522f475Smrg{ "-/+hf", "turn on/off HP Function Key escape codes" }, 1177d522f475Smrg#endif 1178d522f475Smrg{ "-/+hold", "turn on/off logic that retains window after exit" }, 1179d522f475Smrg#if OPT_INITIAL_ERASE 1180d522f475Smrg{ "-/+ie", "turn on/off initialization of 'erase' from pty" }, 1181d522f475Smrg#endif 1182d522f475Smrg{ "-/+im", "use insert mode for TERMCAP" }, 1183d522f475Smrg{ "-/+j", "turn on/off jump scroll" }, 1184d522f475Smrg#if OPT_C1_PRINT 1185d522f475Smrg{ "-/+k8", "turn on/off C1-printable classification"}, 1186d522f475Smrg#endif 1187d522f475Smrg{ "-kt keyboardtype", "set keyboard type:" KEYBOARD_TYPES }, 1188d522f475Smrg#ifdef ALLOWLOGGING 1189d522f475Smrg{ "-/+l", "turn on/off logging" }, 1190d522f475Smrg{ "-lf filename", "logging filename" }, 1191d522f475Smrg#else 1192d522f475Smrg{ "-/+l", "turn on/off logging (not supported)" }, 1193d522f475Smrg{ "-lf filename", "logging filename (not supported)" }, 1194d522f475Smrg#endif 1195d522f475Smrg{ "-/+ls", "turn on/off login shell" }, 1196d522f475Smrg{ "-/+mb", "turn on/off margin bell" }, 1197d522f475Smrg{ "-mc milliseconds", "multiclick time in milliseconds" }, 1198d522f475Smrg{ "-/+mesg", "forbid/allow messages" }, 1199d522f475Smrg{ "-ms color", "pointer color" }, 1200d522f475Smrg{ "-nb number", "margin bell in characters from right end" }, 1201d522f475Smrg{ "-/+nul", "turn off/on display of underlining" }, 1202d522f475Smrg{ "-/+aw", "turn on/off auto wraparound" }, 1203d522f475Smrg{ "-/+pc", "turn on/off PC-style bold colors" }, 1204d522f475Smrg{ "-/+rw", "turn on/off reverse wraparound" }, 1205d522f475Smrg{ "-/+s", "turn on/off multiscroll" }, 1206d522f475Smrg{ "-/+sb", "turn on/off scrollbar" }, 1207e0a2b6dfSmrg#if OPT_REPORT_COLORS 1208e0a2b6dfSmrg{ "-report-colors", "report colors as they are allocated" }, 1209e0a2b6dfSmrg#endif 1210e0a2b6dfSmrg#if OPT_REPORT_FONTS 1211e0a2b6dfSmrg{ "-report-fonts", "report fonts as loaded to stdout" }, 1212e0a2b6dfSmrg#endif 1213d522f475Smrg#ifdef SCROLLBAR_RIGHT 1214d522f475Smrg{ "-rightbar", "force scrollbar right (default left)" }, 1215d522f475Smrg{ "-leftbar", "force scrollbar left" }, 1216d522f475Smrg#endif 1217d522f475Smrg{ "-/+rvc", "turn off/on display of reverse as color" }, 1218d522f475Smrg{ "-/+sf", "turn on/off Sun Function Key escape codes" }, 1219894e0ac8Smrg{ "-sh number", "scale line-height values by the given number" }, 1220d522f475Smrg{ "-/+si", "turn on/off scroll-on-tty-output inhibit" }, 1221d522f475Smrg{ "-/+sk", "turn on/off scroll-on-keypress" }, 1222d522f475Smrg{ "-sl number", "number of scrolled lines to save" }, 1223d522f475Smrg#if OPT_SUNPC_KBD 1224d522f475Smrg{ "-/+sp", "turn on/off Sun/PC Function/Keypad mapping" }, 1225d522f475Smrg#endif 1226d522f475Smrg#if OPT_TEK4014 1227d522f475Smrg{ "-/+t", "turn on/off Tek emulation window" }, 1228d522f475Smrg#endif 1229d522f475Smrg#if OPT_TOOLBAR 1230d522f475Smrg{ "-/+tb", "turn on/off toolbar" }, 1231d522f475Smrg#endif 1232d522f475Smrg{ "-ti termid", "terminal identifier" }, 1233d522f475Smrg{ "-tm string", "terminal mode keywords and characters" }, 1234d522f475Smrg{ "-tn name", "TERM environment variable name" }, 1235d522f475Smrg#if OPT_WIDE_CHARS 1236d522f475Smrg{ "-/+u8", "turn on/off UTF-8 mode (implies wide-characters)" }, 1237d522f475Smrg#endif 1238d522f475Smrg#if OPT_LUIT_PROG 1239d522f475Smrg{ "-/+lc", "turn on/off locale mode using luit" }, 1240d522f475Smrg{ "-lcc path", "filename of locale converter (" DEFLOCALEFILTER ")" }, 12410bd37d32Smrg/* -en is deprecated, not shown in help message */ 1242d522f475Smrg#endif 12432eaa94a1Schristos{ "-/+uc", "turn on/off underline cursor" }, 1244d522f475Smrg{ "-/+ulc", "turn off/on display of underline as color" }, 1245d522f475Smrg{ "-/+ulit", "turn off/on display of underline as italics" }, 1246d522f475Smrg#ifdef HAVE_UTMP 1247d522f475Smrg{ "-/+ut", "turn on/off utmp support" }, 1248d522f475Smrg#else 1249d522f475Smrg{ "-/+ut", "turn on/off utmp support (not available)" }, 1250d522f475Smrg#endif 1251d522f475Smrg{ "-/+vb", "turn on/off visual bell" }, 1252d522f475Smrg{ "-/+pob", "turn on/off pop on bell" }, 1253d522f475Smrg#if OPT_WIDE_CHARS 1254d522f475Smrg{ "-/+wc", "turn on/off wide-character mode" }, 1255d522f475Smrg{ "-/+mk_width", "turn on/off simple width convention" }, 1256d522f475Smrg{ "-/+cjk_width", "turn on/off legacy CJK width convention" }, 1257d522f475Smrg#endif 1258d522f475Smrg{ "-/+wf", "turn on/off wait for map before command exec" }, 1259d522f475Smrg{ "-e command args ...", "command to execute" }, 1260d522f475Smrg#if OPT_TEK4014 1261d522f475Smrg{ "%geom", "Tek window geometry" }, 1262d522f475Smrg#endif 1263d522f475Smrg{ "#geom", "icon window geometry" }, 1264d522f475Smrg{ "-T string", "title name for window" }, 1265d522f475Smrg{ "-n string", "icon name for window" }, 1266d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 1267d522f475Smrg{ "-C", "intercept console messages" }, 1268d522f475Smrg#else 1269d522f475Smrg{ "-C", "intercept console messages (not supported)" }, 1270d522f475Smrg#endif 1271d522f475Smrg{ "-Sccn", "slave mode on \"ttycc\", file descriptor \"n\"" }, 1272d522f475Smrg{ "-into windowId", "use the window id given to -into as the parent window rather than the default root window" }, 1273d522f475Smrg#if OPT_ZICONBEEP 1274d522f475Smrg{ "-ziconbeep percent", "beep and flag icon of window having hidden output" }, 1275d522f475Smrg#endif 1276d522f475Smrg#if OPT_SAME_NAME 1277d522f475Smrg{ "-/+samename", "turn on/off the no-flicker option for title and icon name" }, 1278d522f475Smrg#endif 1279d522f475Smrg#if OPT_SESSION_MGT 1280d522f475Smrg{ "-/+sm", "turn on/off the session-management support" }, 1281d522f475Smrg#endif 1282956cc18dSsnj#if OPT_MAXIMIZE 1283956cc18dSsnj{"-/+maximized", "turn on/off maxmize on startup" }, 1284a1f3da82Smrg{"-/+fullscreen", "turn on/off fullscreen on startup" }, 1285956cc18dSsnj#endif 1286d522f475Smrg{ NULL, NULL }}; 1287d522f475Smrg/* *INDENT-ON* */ 1288d522f475Smrg 128920d2c4d2Smrgstatic const char *message[] = 1290d522f475Smrg{ 1291d522f475Smrg "Fonts should be fixed width and, if both normal and bold are specified, should", 1292d522f475Smrg "have the same size. If only a normal font is specified, it will be used for", 1293d522f475Smrg "both normal and bold text (by doing overstriking). The -e option, if given,", 1294d522f475Smrg "must appear at the end of the command line, otherwise the user's default shell", 1295d522f475Smrg "will be started. Options that start with a plus sign (+) restore the default.", 1296d522f475Smrg NULL}; 1297d522f475Smrg 1298d522f475Smrg/* 1299d522f475Smrg * Decode a key-definition. This combines the termcap and ttyModes, for 1300d522f475Smrg * comparison. Note that octal escapes in ttyModes are done by the normal 1301d522f475Smrg * resource translation. Also, ttyModes allows '^-' as a synonym for disabled. 1302d522f475Smrg */ 1303d522f475Smrgstatic int 1304d522f475Smrgdecode_keyvalue(char **ptr, int termcap) 1305d522f475Smrg{ 1306d522f475Smrg char *string = *ptr; 1307d522f475Smrg int value = -1; 1308d522f475Smrg 130920d2c4d2Smrg TRACE(("decode_keyvalue '%s'\n", string)); 1310d522f475Smrg if (*string == '^') { 1311d522f475Smrg switch (*++string) { 1312d522f475Smrg case '?': 1313d522f475Smrg value = A2E(ANSI_DEL); 1314d522f475Smrg break; 1315d522f475Smrg case '-': 1316d522f475Smrg if (!termcap) { 1317d522f475Smrg errno = 0; 1318d522f475Smrg#if defined(_POSIX_VDISABLE) && defined(HAVE_UNISTD_H) 1319d522f475Smrg value = _POSIX_VDISABLE; 1320d522f475Smrg#endif 1321d522f475Smrg#if defined(_PC_VDISABLE) 1322d522f475Smrg if (value == -1) { 132320d2c4d2Smrg value = (int) fpathconf(0, _PC_VDISABLE); 1324d522f475Smrg if (value == -1) { 1325d522f475Smrg if (errno != 0) 1326d522f475Smrg break; /* skip this (error) */ 1327d522f475Smrg value = 0377; 1328d522f475Smrg } 1329d522f475Smrg } 1330d522f475Smrg#elif defined(VDISABLE) 1331d522f475Smrg if (value == -1) 1332d522f475Smrg value = VDISABLE; 1333d522f475Smrg#endif 1334d522f475Smrg break; 1335d522f475Smrg } 1336d522f475Smrg /* FALLTHRU */ 1337d522f475Smrg default: 1338d522f475Smrg value = CONTROL(*string); 1339d522f475Smrg break; 1340d522f475Smrg } 1341d522f475Smrg ++string; 1342d522f475Smrg } else if (termcap && (*string == '\\')) { 1343d522f475Smrg char *d; 134420d2c4d2Smrg int temp = (int) strtol(string + 1, &d, 8); 1345d522f475Smrg if (temp > 0 && d != string) { 1346d522f475Smrg value = temp; 1347d522f475Smrg string = d; 1348d522f475Smrg } 1349d522f475Smrg } else { 1350d522f475Smrg value = CharOf(*string); 1351d522f475Smrg ++string; 1352d522f475Smrg } 1353d522f475Smrg *ptr = string; 135420d2c4d2Smrg TRACE(("...decode_keyvalue %#x\n", value)); 1355d522f475Smrg return value; 1356d522f475Smrg} 1357d522f475Smrg 1358d522f475Smrgstatic int 13590bd37d32SmrgmatchArg(XrmOptionDescRec * table, const char *param) 13600bd37d32Smrg{ 13610bd37d32Smrg int result = -1; 13620bd37d32Smrg int n; 13630bd37d32Smrg int ch; 13640bd37d32Smrg 13650bd37d32Smrg for (n = 0; (ch = table->option[n]) != '\0'; ++n) { 13660bd37d32Smrg if (param[n] == ch) { 13670bd37d32Smrg result = n; 13680bd37d32Smrg } else { 13690bd37d32Smrg if (param[n] != '\0') 13700bd37d32Smrg result = -1; 13710bd37d32Smrg break; 13720bd37d32Smrg } 13730bd37d32Smrg } 13740bd37d32Smrg 13750bd37d32Smrg return result; 13760bd37d32Smrg} 13770bd37d32Smrg 13780bd37d32Smrg/* return the number of argv[] entries which constitute arguments of option */ 13790bd37d32Smrgstatic int 13800bd37d32SmrgcountArg(XrmOptionDescRec * item) 1381d522f475Smrg{ 13820bd37d32Smrg int result = 0; 13830bd37d32Smrg 13840bd37d32Smrg switch (item->argKind) { 13850bd37d32Smrg case XrmoptionNoArg: 13860bd37d32Smrg /* FALLTHRU */ 13870bd37d32Smrg case XrmoptionIsArg: 13880bd37d32Smrg /* FALLTHRU */ 13890bd37d32Smrg case XrmoptionStickyArg: 13900bd37d32Smrg break; 13910bd37d32Smrg case XrmoptionSepArg: 13920bd37d32Smrg /* FALLTHRU */ 13930bd37d32Smrg case XrmoptionResArg: 13940bd37d32Smrg /* FALLTHRU */ 13950bd37d32Smrg case XrmoptionSkipArg: 13960bd37d32Smrg result = 1; 13970bd37d32Smrg break; 13980bd37d32Smrg case XrmoptionSkipLine: 13990bd37d32Smrg break; 14000bd37d32Smrg case XrmoptionSkipNArgs: 14010bd37d32Smrg result = (int) (long) (item->value); 14020bd37d32Smrg break; 14030bd37d32Smrg } 14040bd37d32Smrg return result; 14050bd37d32Smrg} 14060bd37d32Smrg 14070bd37d32Smrg#define isOption(string) (Boolean)((string)[0] == '-' || (string)[0] == '+') 14080bd37d32Smrg 14090bd37d32Smrg/* 14100bd37d32Smrg * Parse the argument list, more/less as XtInitialize, etc., would do, so we 14110bd37d32Smrg * can find our own "-help" and "-version" options reliably. Improve on just 14120bd37d32Smrg * doing that, by detecting ambiguous options (things that happen to match the 14130bd37d32Smrg * abbreviated option we are examining), and making it smart enough to handle 14140bd37d32Smrg * "-d" as an abbreviation for "-display". Doing this requires checking the 14150bd37d32Smrg * standard table (something that the X libraries should do). 14160bd37d32Smrg */ 14170bd37d32Smrgstatic XrmOptionDescRec * 14180bd37d32SmrgparseArg(int *num, char **argv, char **valuep) 14190bd37d32Smrg{ 14200bd37d32Smrg /* table adapted from XtInitialize, used here to improve abbreviations */ 14210bd37d32Smrg /* *INDENT-OFF* */ 14220bd37d32Smrg#define DATA(option,kind) { option, NULL, kind, (XtPointer) NULL } 14230bd37d32Smrg static XrmOptionDescRec opTable[] = { 14240bd37d32Smrg DATA("+synchronous", XrmoptionNoArg), 14250bd37d32Smrg DATA("-background", XrmoptionSepArg), 14260bd37d32Smrg DATA("-bd", XrmoptionSepArg), 14270bd37d32Smrg DATA("-bg", XrmoptionSepArg), 14280bd37d32Smrg DATA("-bordercolor", XrmoptionSepArg), 14290bd37d32Smrg DATA("-borderwidth", XrmoptionSepArg), 14300bd37d32Smrg DATA("-bw", XrmoptionSepArg), 14310bd37d32Smrg DATA("-display", XrmoptionSepArg), 14320bd37d32Smrg DATA("-fg", XrmoptionSepArg), 14330bd37d32Smrg DATA("-fn", XrmoptionSepArg), 14340bd37d32Smrg DATA("-font", XrmoptionSepArg), 14350bd37d32Smrg DATA("-foreground", XrmoptionSepArg), 14360bd37d32Smrg DATA("-iconic", XrmoptionNoArg), 14370bd37d32Smrg DATA("-name", XrmoptionSepArg), 14380bd37d32Smrg DATA("-reverse", XrmoptionNoArg), 14390bd37d32Smrg DATA("-selectionTimeout", XrmoptionSepArg), 14400bd37d32Smrg DATA("-synchronous", XrmoptionNoArg), 14410bd37d32Smrg DATA("-title", XrmoptionSepArg), 14420bd37d32Smrg DATA("-xnllanguage", XrmoptionSepArg), 14430bd37d32Smrg DATA("-xrm", XrmoptionResArg), 14440bd37d32Smrg DATA("-xtsessionID", XrmoptionSepArg), 14450bd37d32Smrg /* These xterm options are processed after XtOpenApplication */ 14460bd37d32Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 14470bd37d32Smrg DATA("-C", XrmoptionNoArg), 14480bd37d32Smrg#endif /* TIOCCONS */ 14490bd37d32Smrg DATA("-S", XrmoptionStickyArg), 14500bd37d32Smrg DATA("-D", XrmoptionNoArg), 14510bd37d32Smrg }; 14520bd37d32Smrg#undef DATA 14530bd37d32Smrg /* *INDENT-ON* */ 14540bd37d32Smrg 14550bd37d32Smrg XrmOptionDescRec *result = 0; 14560bd37d32Smrg Cardinal inlist; 14570bd37d32Smrg Cardinal limit = XtNumber(optionDescList) + XtNumber(opTable); 14580bd37d32Smrg int atbest = -1; 14590bd37d32Smrg int best = -1; 14600bd37d32Smrg int test; 14610bd37d32Smrg Boolean exact = False; 14620bd37d32Smrg int ambiguous1 = -1; 14630bd37d32Smrg int ambiguous2 = -1; 14640bd37d32Smrg char *option; 14650bd37d32Smrg char *value; 14660bd37d32Smrg 14670bd37d32Smrg#define ITEM(n) ((Cardinal)(n) < XtNumber(optionDescList) \ 14680bd37d32Smrg ? &optionDescList[n] \ 14690bd37d32Smrg : &opTable[(Cardinal)(n) - XtNumber(optionDescList)]) 14700bd37d32Smrg 14710bd37d32Smrg if ((option = argv[*num]) != 0) { 14720bd37d32Smrg Boolean need_value; 14730bd37d32Smrg Boolean have_value = False; 14740bd37d32Smrg 14750bd37d32Smrg TRACE(("parseArg %s\n", option)); 14760bd37d32Smrg if ((value = argv[(*num) + 1]) != 0) { 1477e0a2b6dfSmrg have_value = (Boolean) !isOption(value); 14780bd37d32Smrg } 14790bd37d32Smrg for (inlist = 0; inlist < limit; ++inlist) { 14800bd37d32Smrg XrmOptionDescRec *check = ITEM(inlist); 14810bd37d32Smrg 14820bd37d32Smrg test = matchArg(check, option); 14830bd37d32Smrg if (test < 0) 14840bd37d32Smrg continue; 14850bd37d32Smrg 14860bd37d32Smrg /* check for exact match */ 14870bd37d32Smrg if ((test + 1) == (int) strlen(check->option)) { 14880bd37d32Smrg if (check->argKind == XrmoptionStickyArg) { 14890bd37d32Smrg if (strlen(option) > strlen(check->option)) { 14900bd37d32Smrg exact = True; 14910bd37d32Smrg atbest = (int) inlist; 14920bd37d32Smrg break; 14930bd37d32Smrg } 14940bd37d32Smrg } else if ((test + 1) == (int) strlen(option)) { 14950bd37d32Smrg exact = True; 14960bd37d32Smrg atbest = (int) inlist; 14970bd37d32Smrg break; 14980bd37d32Smrg } 14990bd37d32Smrg } 15000bd37d32Smrg 15010bd37d32Smrg need_value = (Boolean) (test > 0 && countArg(check) > 0); 15020bd37d32Smrg 15030bd37d32Smrg if (need_value && value != 0) { 15040bd37d32Smrg ; 15050bd37d32Smrg } else if (need_value ^ have_value) { 15060bd37d32Smrg TRACE(("...skipping, need %d vs have %d\n", need_value, have_value)); 15070bd37d32Smrg continue; 15080bd37d32Smrg } 15090bd37d32Smrg 15100bd37d32Smrg /* special-case for our own options - always allow abbreviation */ 15110bd37d32Smrg if (test > 0 15120bd37d32Smrg && ITEM(inlist)->argKind >= XrmoptionSkipArg) { 15130bd37d32Smrg atbest = (int) inlist; 1514e0a2b6dfSmrg if (ITEM(inlist)->argKind == XrmoptionSkipNArgs) { 1515e0a2b6dfSmrg /* in particular, silence a warning about ambiguity */ 1516e0a2b6dfSmrg exact = 1; 1517e0a2b6dfSmrg } 15180bd37d32Smrg break; 15190bd37d32Smrg } 15200bd37d32Smrg if (test > best) { 15210bd37d32Smrg best = test; 15220bd37d32Smrg atbest = (int) inlist; 15230bd37d32Smrg } else if (test == best) { 15240bd37d32Smrg if (atbest >= 0) { 15250bd37d32Smrg if (atbest > 0) { 15260bd37d32Smrg ambiguous1 = (int) inlist; 15270bd37d32Smrg ambiguous2 = (int) atbest; 15280bd37d32Smrg } 15290bd37d32Smrg atbest = -1; 15300bd37d32Smrg } 15310bd37d32Smrg } 15320bd37d32Smrg } 15330bd37d32Smrg } 15340bd37d32Smrg 15350bd37d32Smrg *valuep = 0; 15360bd37d32Smrg if (atbest >= 0) { 15370bd37d32Smrg result = ITEM(atbest); 15380bd37d32Smrg if (!exact) { 15390bd37d32Smrg if (ambiguous1 >= 0 && ambiguous2 >= 0) { 15400bd37d32Smrg xtermWarning("ambiguous option \"%s\" vs \"%s\"\n", 15410bd37d32Smrg ITEM(ambiguous1)->option, 15420bd37d32Smrg ITEM(ambiguous2)->option); 15430bd37d32Smrg } else if (strlen(option) > strlen(result->option)) { 15440bd37d32Smrg result = 0; 15450bd37d32Smrg } 15460bd37d32Smrg } 15470bd37d32Smrg if (result != 0) { 15480bd37d32Smrg TRACE(("...result %s\n", result->option)); 15490bd37d32Smrg /* expand abbreviations */ 15500bd37d32Smrg if (result->argKind != XrmoptionStickyArg) { 15510bd37d32Smrg if (strcmp(argv[*num], result->option)) { 15520bd37d32Smrg argv[*num] = x_strdup(result->option); 15530bd37d32Smrg } 15540bd37d32Smrg } 15550bd37d32Smrg 15560bd37d32Smrg /* adjust (*num) to skip option value */ 15570bd37d32Smrg (*num) += countArg(result); 15580bd37d32Smrg TRACE(("...next %s\n", NonNull(argv[*num]))); 15590bd37d32Smrg if (result->argKind == XrmoptionSkipArg) { 15600bd37d32Smrg *valuep = argv[*num]; 15610bd37d32Smrg TRACE(("...parameter %s\n", NonNull(*valuep))); 15620bd37d32Smrg } 15630bd37d32Smrg } 15640bd37d32Smrg } 15650bd37d32Smrg#undef ITEM 15660bd37d32Smrg return result; 1567d522f475Smrg} 1568d522f475Smrg 1569d522f475Smrgstatic void 1570d522f475SmrgSyntax(char *badOption) 1571d522f475Smrg{ 1572d522f475Smrg OptionHelp *opt; 1573d522f475Smrg OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList)); 1574d522f475Smrg int col; 1575d522f475Smrg 15760bd37d32Smrg TRACE(("Syntax error at %s\n", badOption)); 15770bd37d32Smrg xtermWarning("bad command line option \"%s\"\r\n\n", badOption); 1578d522f475Smrg 1579d522f475Smrg fprintf(stderr, "usage: %s", ProgramName); 1580956cc18dSsnj col = 8 + (int) strlen(ProgramName); 1581d522f475Smrg for (opt = list; opt->opt; opt++) { 1582956cc18dSsnj int len = 3 + (int) strlen(opt->opt); /* space [ string ] */ 1583d522f475Smrg if (col + len > 79) { 1584d522f475Smrg fprintf(stderr, "\r\n "); /* 3 spaces */ 1585d522f475Smrg col = 3; 1586d522f475Smrg } 1587d522f475Smrg fprintf(stderr, " [%s]", opt->opt); 1588d522f475Smrg col += len; 1589d522f475Smrg } 1590d522f475Smrg 1591d522f475Smrg fprintf(stderr, "\r\n\nType %s -help for a full description.\r\n\n", 1592d522f475Smrg ProgramName); 1593d522f475Smrg exit(1); 1594d522f475Smrg} 1595d522f475Smrg 1596d522f475Smrgstatic void 1597d522f475SmrgVersion(void) 1598d522f475Smrg{ 1599d522f475Smrg printf("%s\n", xtermVersion()); 1600d522f475Smrg fflush(stdout); 1601d522f475Smrg} 1602d522f475Smrg 1603d522f475Smrgstatic void 1604d522f475SmrgHelp(void) 1605d522f475Smrg{ 1606d522f475Smrg OptionHelp *opt; 1607d522f475Smrg OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList)); 160820d2c4d2Smrg const char **cpp; 1609d522f475Smrg 1610d522f475Smrg printf("%s usage:\n %s [-options ...] [-e command args]\n\n", 1611d522f475Smrg xtermVersion(), ProgramName); 1612d522f475Smrg printf("where options include:\n"); 1613d522f475Smrg for (opt = list; opt->opt; opt++) { 1614d522f475Smrg printf(" %-28s %s\n", opt->opt, opt->desc); 1615d522f475Smrg } 1616d522f475Smrg 1617d522f475Smrg putchar('\n'); 1618d522f475Smrg for (cpp = message; *cpp; cpp++) 1619d522f475Smrg puts(*cpp); 1620d522f475Smrg putchar('\n'); 1621d522f475Smrg fflush(stdout); 1622d522f475Smrg} 1623d522f475Smrg 1624d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 1625d522f475Smrg/* ARGSUSED */ 1626d522f475Smrgstatic Boolean 1627d522f475SmrgConvertConsoleSelection(Widget w GCC_UNUSED, 1628894e0ac8Smrg Atom *selection GCC_UNUSED, 1629894e0ac8Smrg Atom *target GCC_UNUSED, 1630894e0ac8Smrg Atom *type GCC_UNUSED, 1631d522f475Smrg XtPointer *value GCC_UNUSED, 1632d522f475Smrg unsigned long *length GCC_UNUSED, 1633d522f475Smrg int *format GCC_UNUSED) 1634d522f475Smrg{ 1635d522f475Smrg /* we don't save console output, so can't offer it */ 1636d522f475Smrg return False; 1637d522f475Smrg} 1638d522f475Smrg#endif /* TIOCCONS */ 1639d522f475Smrg 1640d522f475Smrg/* 1641d522f475Smrg * DeleteWindow(): Action proc to implement ICCCM delete_window. 1642d522f475Smrg */ 1643d522f475Smrg/* ARGSUSED */ 1644d522f475Smrgstatic void 1645d522f475SmrgDeleteWindow(Widget w, 1646894e0ac8Smrg XEvent *event GCC_UNUSED, 1647e0a2b6dfSmrg String *params GCC_UNUSED, 1648d522f475Smrg Cardinal *num_params GCC_UNUSED) 1649d522f475Smrg{ 1650d522f475Smrg#if OPT_TEK4014 1651d522f475Smrg if (w == toplevel) { 1652d522f475Smrg if (TEK4014_SHOWN(term)) 1653d522f475Smrg hide_vt_window(); 1654d522f475Smrg else 1655d522f475Smrg do_hangup(w, (XtPointer) 0, (XtPointer) 0); 165620d2c4d2Smrg } else if (TScreenOf(term)->Vshow) 1657d522f475Smrg hide_tek_window(); 1658d522f475Smrg else 1659d522f475Smrg#endif 1660d522f475Smrg do_hangup(w, (XtPointer) 0, (XtPointer) 0); 1661d522f475Smrg} 1662d522f475Smrg 1663d522f475Smrg/* ARGSUSED */ 1664d522f475Smrgstatic void 1665d522f475SmrgKeyboardMapping(Widget w GCC_UNUSED, 1666894e0ac8Smrg XEvent *event, 1667e0a2b6dfSmrg String *params GCC_UNUSED, 1668d522f475Smrg Cardinal *num_params GCC_UNUSED) 1669d522f475Smrg{ 1670d522f475Smrg switch (event->type) { 1671d522f475Smrg case MappingNotify: 1672d522f475Smrg XRefreshKeyboardMapping(&event->xmapping); 1673d522f475Smrg break; 1674d522f475Smrg } 1675d522f475Smrg} 1676d522f475Smrg 1677d522f475Smrgstatic XtActionsRec actionProcs[] = 1678d522f475Smrg{ 1679d522f475Smrg {"DeleteWindow", DeleteWindow}, 1680d522f475Smrg {"KeyboardMapping", KeyboardMapping}, 1681d522f475Smrg}; 1682d522f475Smrg 1683d522f475Smrg/* 1684d522f475Smrg * Some platforms use names such as /dev/tty01, others /dev/pts/1. Parse off 1685d522f475Smrg * the "tty01" or "pts/1" portion, and return that for use as an identifier for 1686d522f475Smrg * utmp. 1687d522f475Smrg */ 1688d522f475Smrgstatic char * 1689d522f475Smrgmy_pty_name(char *device) 1690d522f475Smrg{ 1691d522f475Smrg size_t len = strlen(device); 1692d522f475Smrg Bool name = False; 1693d522f475Smrg 1694d522f475Smrg while (len != 0) { 1695d522f475Smrg int ch = device[len - 1]; 1696d522f475Smrg if (isdigit(ch)) { 1697d522f475Smrg len--; 1698d522f475Smrg } else if (ch == '/') { 1699d522f475Smrg if (name) 1700d522f475Smrg break; 1701d522f475Smrg len--; 1702d522f475Smrg } else if (isalpha(ch)) { 1703d522f475Smrg name = True; 1704d522f475Smrg len--; 1705d522f475Smrg } else { 1706d522f475Smrg break; 1707d522f475Smrg } 1708d522f475Smrg } 1709d522f475Smrg TRACE(("my_pty_name(%s) -> '%s'\n", device, device + len)); 1710d522f475Smrg return device + len; 1711d522f475Smrg} 1712d522f475Smrg 1713d522f475Smrg/* 1714d522f475Smrg * If the name contains a '/', it is a "pts/1" case. Otherwise, return the 1715d522f475Smrg * last few characters for a utmp identifier. 1716d522f475Smrg */ 1717d522f475Smrgstatic char * 1718d522f475Smrgmy_pty_id(char *device) 1719d522f475Smrg{ 1720d522f475Smrg char *name = my_pty_name(device); 1721d522f475Smrg char *leaf = x_basename(name); 1722d522f475Smrg 1723d522f475Smrg if (name == leaf) { /* no '/' in the name */ 1724956cc18dSsnj int len = (int) strlen(leaf); 1725d522f475Smrg if (PTYCHARLEN < len) 1726d522f475Smrg leaf = leaf + (len - PTYCHARLEN); 1727d522f475Smrg } 1728d522f475Smrg TRACE(("my_pty_id (%s) -> '%s'\n", device, leaf)); 1729d522f475Smrg return leaf; 1730d522f475Smrg} 1731d522f475Smrg 1732d522f475Smrg/* 1733d522f475Smrg * Set the tty/pty identifier 1734d522f475Smrg */ 1735d522f475Smrgstatic void 1736d522f475Smrgset_pty_id(char *device, char *id) 1737d522f475Smrg{ 1738d522f475Smrg char *name = my_pty_name(device); 1739d522f475Smrg char *leaf = x_basename(name); 1740d522f475Smrg 1741d522f475Smrg if (name == leaf) { 1742d522f475Smrg strcpy(my_pty_id(device), id); 1743d522f475Smrg } else { 1744d522f475Smrg strcpy(leaf, id); 1745d522f475Smrg } 1746d522f475Smrg TRACE(("set_pty_id(%s) -> '%s'\n", id, device)); 1747d522f475Smrg} 1748d522f475Smrg 1749d522f475Smrg/* 1750d522f475Smrg * The original -S option accepts two characters to identify the pty, and a 1751d522f475Smrg * file-descriptor (assumed to be nonzero). That is not general enough, so we 1752d522f475Smrg * check first if the option contains a '/' to delimit the two fields, and if 1753d522f475Smrg * not, fall-thru to the original logic. 1754d522f475Smrg */ 1755d522f475Smrgstatic Bool 1756d522f475SmrgParseSccn(char *option) 1757d522f475Smrg{ 1758d522f475Smrg char *leaf = x_basename(option); 1759d522f475Smrg Bool code = False; 1760d522f475Smrg 1761d522f475Smrg if (leaf != option) { 1762d522f475Smrg if (leaf - option > 0 1763d522f475Smrg && isdigit(CharOf(*leaf)) 1764d522f475Smrg && sscanf(leaf, "%d", &am_slave) == 1) { 1765956cc18dSsnj size_t len = (size_t) (leaf - option - 1); 1766d522f475Smrg /* 1767d522f475Smrg * If we have a slash, we only care about the part after the slash, 1768d522f475Smrg * which is a file-descriptor. The part before the slash can be 1769d522f475Smrg * the /dev/pts/XXX value, but since we do not need to reopen it, 1770d522f475Smrg * it is useful mainly for display in a "ps -ef". 1771d522f475Smrg */ 1772d522f475Smrg strncpy(passedPty, option, len); 1773d522f475Smrg passedPty[len] = 0; 1774d522f475Smrg code = True; 1775d522f475Smrg } 1776d522f475Smrg } else { 1777d522f475Smrg code = (sscanf(option, "%c%c%d", 1778d522f475Smrg passedPty, passedPty + 1, &am_slave) == 3); 1779d522f475Smrg } 1780d522f475Smrg TRACE(("ParseSccn(%s) = '%s' %d (%s)\n", option, 1781d522f475Smrg passedPty, am_slave, code ? "OK" : "ERR")); 1782d522f475Smrg return code; 1783d522f475Smrg} 1784d522f475Smrg 1785d522f475Smrg#if defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 1786d522f475Smrg/* 1787d522f475Smrg * From "man utmp": 1788d522f475Smrg * xterm and other terminal emulators directly create a USER_PROCESS record 1789d522f475Smrg * and generate the ut_id by using the last two letters of /dev/ttyp%c or by 1790d522f475Smrg * using p%d for /dev/pts/%d. If they find a DEAD_PROCESS for this id, they 1791d522f475Smrg * recycle it, otherwise they create a new entry. If they can, they will mark 1792d522f475Smrg * it as DEAD_PROCESS on exiting and it is advised that they null ut_line, 1793d522f475Smrg * ut_time, ut_user and ut_host as well. 1794d522f475Smrg * 1795d522f475Smrg * Generally ut_id allows no more than 3 characters (plus null), even if the 1796d522f475Smrg * pty implementation allows more than 3 digits. 1797d522f475Smrg */ 1798d522f475Smrgstatic char * 1799d522f475Smrgmy_utmp_id(char *device) 1800d522f475Smrg{ 1801d522f475Smrg typedef struct UTMP_STR UTMP_STRUCT; 1802d522f475Smrg#define UTIDSIZE (sizeof(((UTMP_STRUCT *)NULL)->ut_id)) 1803d522f475Smrg static char result[UTIDSIZE + 1]; 1804d522f475Smrg 1805d522f475Smrg#if defined(__SCO__) || defined(__UNIXWARE__) 1806d522f475Smrg /* 1807d522f475Smrg * Legend does not support old-style pty's, has no related compatibility 1808d522f475Smrg * issues, and can use the available space in ut_id differently from the 1809d522f475Smrg * default convention. 1810d522f475Smrg * 1811d522f475Smrg * This scheme is intended to avoid conflicts both with other users of 1812d522f475Smrg * utmpx as well as between multiple xterms. First, Legend uses all of the 1813d522f475Smrg * characters of ut_id, and adds no terminating NUL is required (the 1814d522f475Smrg * default scheme may add a trailing NUL). Second, all xterm entries will 1815d522f475Smrg * start with the letter 'x' followed by three digits, which will be the 1816d522f475Smrg * last three digits of the device name, regardless of the format of the 1817d522f475Smrg * device name, with leading 0's added where necessary. For instance, an 1818d522f475Smrg * xterm on /dev/pts/3 will have a ut_id of x003; an xterm on /dev/pts123 1819d522f475Smrg * will have a ut_id of x123. Under the other convention, /dev/pts/3 would 1820d522f475Smrg * have a ut_id of p3 and /dev/pts123 would have a ut_id of p123. 1821d522f475Smrg */ 1822d522f475Smrg int len, n; 1823d522f475Smrg 1824d522f475Smrg len = strlen(device); 1825d522f475Smrg n = UTIDSIZE; 1826d522f475Smrg result[n] = '\0'; 1827d522f475Smrg while ((n > 0) && (len > 0) && isdigit(device[len - 1])) 1828d522f475Smrg result[--n] = device[--len]; 1829d522f475Smrg while (n > 0) 1830d522f475Smrg result[--n] = '0'; 1831d522f475Smrg result[0] = 'x'; 1832d522f475Smrg#else 1833d522f475Smrg char *name = my_pty_name(device); 1834d522f475Smrg char *leaf = x_basename(name); 1835d522f475Smrg size_t len = strlen(leaf); 1836d522f475Smrg 1837d522f475Smrg if ((UTIDSIZE - 1) < len) 1838d522f475Smrg leaf = leaf + (len - (UTIDSIZE - 1)); 1839d522f475Smrg sprintf(result, "p%s", leaf); 1840d522f475Smrg#endif 1841d522f475Smrg 1842d522f475Smrg TRACE(("my_utmp_id (%s) -> '%s'\n", device, result)); 1843d522f475Smrg return result; 1844d522f475Smrg} 1845d522f475Smrg#endif /* USE_SYSV_UTMP */ 1846d522f475Smrg 1847d522f475Smrg#ifdef USE_POSIX_SIGNALS 1848d522f475Smrg 1849d522f475Smrgtypedef void (*sigfunc) (int); 1850d522f475Smrg 1851d522f475Smrg/* make sure we sure we ignore SIGCHLD for the cases parent 1852d522f475Smrg has just been stopped and not actually killed */ 1853d522f475Smrg 1854d522f475Smrgstatic sigfunc 1855d522f475Smrgposix_signal(int signo, sigfunc func) 1856d522f475Smrg{ 1857d522f475Smrg struct sigaction act, oact; 1858d522f475Smrg 1859d522f475Smrg act.sa_handler = func; 1860d522f475Smrg sigemptyset(&act.sa_mask); 1861d522f475Smrg#ifdef SA_RESTART 1862d522f475Smrg act.sa_flags = SA_NOCLDSTOP | SA_RESTART; 1863d522f475Smrg#else 1864d522f475Smrg act.sa_flags = SA_NOCLDSTOP; 1865d522f475Smrg#endif 1866d522f475Smrg if (sigaction(signo, &act, &oact) < 0) 1867d522f475Smrg return (SIG_ERR); 1868d522f475Smrg return (oact.sa_handler); 1869d522f475Smrg} 1870d522f475Smrg 18710bd37d32Smrg#endif /* USE_POSIX_SIGNALS */ 1872d522f475Smrg 1873d522f475Smrg#if defined(DISABLE_SETUID) || defined(USE_UTMP_SETGID) 1874d522f475Smrgstatic void 1875d522f475SmrgdisableSetUid(void) 1876d522f475Smrg{ 1877d522f475Smrg TRACE(("process %d disableSetUid\n", (int) getpid())); 1878d522f475Smrg if (setuid(save_ruid) == -1) { 18790bd37d32Smrg xtermWarning("unable to reset uid\n"); 1880d522f475Smrg exit(1); 1881d522f475Smrg } 1882d522f475Smrg TRACE_IDS; 1883d522f475Smrg} 1884d522f475Smrg#else 1885d522f475Smrg#define disableSetUid() /* nothing */ 1886d522f475Smrg#endif /* DISABLE_SETUID */ 1887d522f475Smrg 1888d522f475Smrg#if defined(DISABLE_SETGID) || defined(USE_UTMP_SETGID) 1889d522f475Smrgstatic void 1890d522f475SmrgdisableSetGid(void) 1891d522f475Smrg{ 1892d522f475Smrg TRACE(("process %d disableSetGid\n", (int) getpid())); 1893d522f475Smrg if (setegid(save_rgid) == -1) { 18940bd37d32Smrg xtermWarning("unable to reset effective gid\n"); 1895d522f475Smrg exit(1); 1896d522f475Smrg } 1897d522f475Smrg TRACE_IDS; 1898d522f475Smrg} 1899d522f475Smrg#else 1900d522f475Smrg#define disableSetGid() /* nothing */ 1901d522f475Smrg#endif /* DISABLE_SETGID */ 1902d522f475Smrg 1903d522f475Smrg#if defined(HAVE_POSIX_SAVED_IDS) 1904d522f475Smrg#if (!defined(USE_UTEMPTER) || !defined(DISABLE_SETGID)) 1905d522f475Smrgstatic void 1906d522f475SmrgsetEffectiveGroup(gid_t group) 1907d522f475Smrg{ 1908d522f475Smrg TRACE(("process %d setEffectiveGroup(%d)\n", (int) getpid(), (int) group)); 1909d522f475Smrg if (setegid(group) == -1) { 1910d522f475Smrg#ifdef __MVS__ 1911d522f475Smrg if (!(errno == EMVSERR)) /* could happen if _BPX_SHAREAS=REUSE */ 1912d522f475Smrg#endif 1913d522f475Smrg { 19140bd37d32Smrg xtermPerror("setegid(%d)", (int) group); 1915d522f475Smrg } 1916d522f475Smrg } 1917d522f475Smrg TRACE_IDS; 1918d522f475Smrg} 1919d522f475Smrg#endif 1920d522f475Smrg 1921d522f475Smrg#if !defined(USE_UTMP_SETGID) && (!defined(USE_UTEMPTER) || !defined(DISABLE_SETUID)) 1922d522f475Smrgstatic void 1923d522f475SmrgsetEffectiveUser(uid_t user) 1924d522f475Smrg{ 1925d522f475Smrg TRACE(("process %d setEffectiveUser(%d)\n", (int) getpid(), (int) user)); 1926d522f475Smrg if (seteuid(user) == -1) { 1927d522f475Smrg#ifdef __MVS__ 1928d522f475Smrg if (!(errno == EMVSERR)) 1929d522f475Smrg#endif 1930d522f475Smrg { 19310bd37d32Smrg xtermPerror("seteuid(%d)", (int) user); 1932d522f475Smrg } 1933d522f475Smrg } 1934d522f475Smrg TRACE_IDS; 1935d522f475Smrg} 1936d522f475Smrg#endif 1937d522f475Smrg#endif /* HAVE_POSIX_SAVED_IDS */ 1938d522f475Smrg 1939d522f475Smrgint 1940d522f475Smrgmain(int argc, char *argv[]ENVP_ARG) 1941d522f475Smrg{ 1942a1f3da82Smrg#if OPT_MAXIMIZE 1943a1f3da82Smrg#define DATA(name) { #name, es##name } 1944a1f3da82Smrg static FlagList tblFullscreen[] = 1945a1f3da82Smrg { 1946a1f3da82Smrg DATA(Always), 1947a1f3da82Smrg DATA(Never) 1948a1f3da82Smrg }; 1949a1f3da82Smrg#undef DATA 1950a1f3da82Smrg#endif 1951a1f3da82Smrg 1952d522f475Smrg Widget form_top, menu_top; 1953d522f475Smrg Dimension menu_high; 1954d522f475Smrg TScreen *screen; 1955d522f475Smrg int mode; 1956e0a2b6dfSmrg char *my_class = x_strdup(DEFCLASS); 1957d522f475Smrg Window winToEmbedInto = None; 1958d522f475Smrg 1959d522f475Smrg ProgramName = argv[0]; 1960d522f475Smrg 1961d522f475Smrg#ifdef HAVE_POSIX_SAVED_IDS 1962d522f475Smrg save_euid = geteuid(); 1963d522f475Smrg save_egid = getegid(); 1964d522f475Smrg#endif 1965d522f475Smrg 1966d522f475Smrg save_ruid = getuid(); 1967d522f475Smrg save_rgid = getgid(); 1968d522f475Smrg 1969d522f475Smrg#if defined(DISABLE_SETUID) || defined(DISABLE_SETGID) 1970d522f475Smrg#if defined(DISABLE_SETUID) 1971d522f475Smrg disableSetUid(); 1972d522f475Smrg#endif 1973d522f475Smrg#if defined(DISABLE_SETGID) 1974d522f475Smrg disableSetGid(); 1975d522f475Smrg#endif 1976d522f475Smrg TRACE_IDS; 1977d522f475Smrg#endif 1978d522f475Smrg 1979d522f475Smrg /* extra length in case longer tty name like /dev/ttyq255 */ 1980d522f475Smrg ttydev = TypeMallocN(char, sizeof(TTYDEV) + 80); 1981d522f475Smrg#ifdef USE_PTY_DEVICE 1982d522f475Smrg ptydev = TypeMallocN(char, sizeof(PTYDEV) + 80); 1983d522f475Smrg if (!ttydev || !ptydev) 1984d522f475Smrg#else 1985d522f475Smrg if (!ttydev) 1986d522f475Smrg#endif 1987d522f475Smrg { 19880bd37d32Smrg xtermWarning("unable to allocate memory for ttydev or ptydev\n"); 1989d522f475Smrg exit(1); 1990d522f475Smrg } 1991d522f475Smrg strcpy(ttydev, TTYDEV); 1992d522f475Smrg#ifdef USE_PTY_DEVICE 1993d522f475Smrg strcpy(ptydev, PTYDEV); 1994d522f475Smrg#endif 1995d522f475Smrg 1996d522f475Smrg#if defined(USE_UTMP_SETGID) 1997d522f475Smrg get_pty(NULL, NULL); 1998d522f475Smrg disableSetUid(); 1999d522f475Smrg disableSetGid(); 2000d522f475Smrg TRACE_IDS; 2001d522f475Smrg#define get_pty(pty, from) really_get_pty(pty, from) 2002d522f475Smrg#endif 2003d522f475Smrg 2004d522f475Smrg /* Do these first, since we may not be able to open the display */ 2005d522f475Smrg TRACE_OPTS(xtermOptions, optionDescList, XtNumber(optionDescList)); 2006d522f475Smrg TRACE_ARGV("Before XtOpenApplication", argv); 2007d522f475Smrg if (argc > 1) { 20080bd37d32Smrg XrmOptionDescRec *option_ptr; 20090bd37d32Smrg char *option_value; 2010d522f475Smrg int n; 2011e39b573cSmrg Bool quit = False; 2012d522f475Smrg 2013d522f475Smrg for (n = 1; n < argc; n++) { 20140bd37d32Smrg if ((option_ptr = parseArg(&n, argv, &option_value)) == 0) { 20150bd37d32Smrg if (argv[n] == 0) { 20160bd37d32Smrg break; 20170bd37d32Smrg } else if (isOption(argv[n])) { 20180bd37d32Smrg Syntax(argv[n]); 20190bd37d32Smrg } else if (explicit_shname != 0) { 20200bd37d32Smrg xtermWarning("Explicit shell already was %s\n", explicit_shname); 20210bd37d32Smrg Syntax(argv[n]); 20220bd37d32Smrg } 20230bd37d32Smrg explicit_shname = xtermFindShell(argv[n], True); 20240bd37d32Smrg if (explicit_shname == 0) 20250bd37d32Smrg exit(0); 20260bd37d32Smrg TRACE(("...explicit shell %s\n", explicit_shname)); 20270bd37d32Smrg } else if (!strcmp(option_ptr->option, "-e")) { 20280bd37d32Smrg command_to_exec = (argv + n + 1); 20290bd37d32Smrg if (!command_to_exec[0]) 20300bd37d32Smrg Syntax(argv[n]); 20310bd37d32Smrg break; 20320bd37d32Smrg } else if (!strcmp(option_ptr->option, "-version")) { 2033d522f475Smrg Version(); 2034e39b573cSmrg quit = True; 20350bd37d32Smrg } else if (!strcmp(option_ptr->option, "-help")) { 2036d522f475Smrg Help(); 2037e39b573cSmrg quit = True; 20380bd37d32Smrg } else if (!strcmp(option_ptr->option, "-class")) { 2039e0a2b6dfSmrg free(my_class); 20400bd37d32Smrg if ((my_class = x_strdup(option_value)) == 0) { 2041d522f475Smrg Help(); 2042e39b573cSmrg quit = True; 2043d522f475Smrg } 20440bd37d32Smrg } else if (!strcmp(option_ptr->option, "-into")) { 20450bd37d32Smrg char *endPtr; 20460bd37d32Smrg winToEmbedInto = (Window) strtol(option_value, &endPtr, 0); 2047d522f475Smrg } 2048d522f475Smrg } 2049d522f475Smrg if (quit) 2050d522f475Smrg exit(0); 20510bd37d32Smrg /* 20520bd37d32Smrg * If there is anything left unparsed, and we're not using "-e", 20530bd37d32Smrg * then give up. 20540bd37d32Smrg */ 20550bd37d32Smrg if (n < argc && !command_to_exec) { 20560bd37d32Smrg Syntax(argv[n]); 20570bd37d32Smrg } 2058d522f475Smrg } 2059d522f475Smrg 20600bd37d32Smrg /* This dumped core on HP-UX 9.05 with X11R5 */ 2061d522f475Smrg#if OPT_I18N_SUPPORT 2062d522f475Smrg XtSetLanguageProc(NULL, NULL, NULL); 2063d522f475Smrg#endif 2064d522f475Smrg 2065d522f475Smrg#ifdef TERMIO_STRUCT /* { */ 2066d522f475Smrg /* Initialization is done here rather than above in order 2067d522f475Smrg * to prevent any assumptions about the order of the contents 2068d522f475Smrg * of the various terminal structures (which may change from 2069d522f475Smrg * implementation to implementation). 2070d522f475Smrg */ 2071d522f475Smrg memset(&d_tio, 0, sizeof(d_tio)); 2072d522f475Smrg d_tio.c_iflag = ICRNL | IXON; 2073d522f475Smrg#ifdef TAB3 2074d522f475Smrg d_tio.c_oflag = OPOST | ONLCR | TAB3; 2075d522f475Smrg#else 2076d522f475Smrg#ifdef ONLCR 2077d522f475Smrg d_tio.c_oflag = OPOST | ONLCR; 2078d522f475Smrg#else 2079d522f475Smrg d_tio.c_oflag = OPOST; 2080d522f475Smrg#endif 2081d522f475Smrg#endif 2082d522f475Smrg { 2083d522f475Smrg Cardinal nn; 2084d522f475Smrg 2085d522f475Smrg /* fill in default-values */ 2086d522f475Smrg for (nn = 0; nn < XtNumber(known_ttyChars); ++nn) { 2087d522f475Smrg if (validTtyChar(d_tio, nn)) { 2088d522f475Smrg d_tio.c_cc[known_ttyChars[nn].sysMode] = 20890bd37d32Smrg (cc_t) known_ttyChars[nn].myDefault; 2090d522f475Smrg } 2091d522f475Smrg } 2092d522f475Smrg } 2093d522f475Smrg#if defined(macII) || defined(ATT) || defined(CRAY) /* { */ 2094d522f475Smrg d_tio.c_cflag = VAL_LINE_SPEED | CS8 | CREAD | PARENB | HUPCL; 2095d522f475Smrg d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK; 2096d522f475Smrg#ifdef ECHOKE 2097d522f475Smrg d_tio.c_lflag |= ECHOKE | IEXTEN; 2098d522f475Smrg#endif 2099d522f475Smrg#ifdef ECHOCTL 2100d522f475Smrg d_tio.c_lflag |= ECHOCTL | IEXTEN; 2101d522f475Smrg#endif 2102d522f475Smrg#ifndef USE_TERMIOS /* { */ 2103d522f475Smrg d_tio.c_line = 0; 2104d522f475Smrg#endif /* } */ 2105d522f475Smrg#ifdef HAS_LTCHARS /* { */ 2106d522f475Smrg d_ltc.t_suspc = CSUSP; /* t_suspc */ 2107d522f475Smrg d_ltc.t_dsuspc = CDSUSP; /* t_dsuspc */ 2108d522f475Smrg d_ltc.t_rprntc = CRPRNT; 2109d522f475Smrg d_ltc.t_flushc = CFLUSH; 2110d522f475Smrg d_ltc.t_werasc = CWERASE; 2111d522f475Smrg d_ltc.t_lnextc = CLNEXT; 2112d522f475Smrg#endif /* } HAS_LTCHARS */ 2113d522f475Smrg#ifdef TIOCLSET /* { */ 2114d522f475Smrg d_lmode = 0; 2115d522f475Smrg#endif /* } TIOCLSET */ 2116d522f475Smrg#else /* }{ else !macII, ATT, CRAY */ 2117d522f475Smrg#ifndef USE_POSIX_TERMIOS 2118d522f475Smrg#ifdef BAUD_0 /* { */ 2119d522f475Smrg d_tio.c_cflag = CS8 | CREAD | PARENB | HUPCL; 2120d522f475Smrg#else /* }{ !BAUD_0 */ 2121d522f475Smrg d_tio.c_cflag = VAL_LINE_SPEED | CS8 | CREAD | PARENB | HUPCL; 2122d522f475Smrg#endif /* } !BAUD_0 */ 2123d522f475Smrg#else /* USE_POSIX_TERMIOS */ 2124d522f475Smrg d_tio.c_cflag = CS8 | CREAD | PARENB | HUPCL; 2125d522f475Smrg cfsetispeed(&d_tio, VAL_LINE_SPEED); 2126d522f475Smrg cfsetospeed(&d_tio, VAL_LINE_SPEED); 2127d522f475Smrg#endif 2128d522f475Smrg d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK; 2129d522f475Smrg#ifdef ECHOKE 2130d522f475Smrg d_tio.c_lflag |= ECHOKE | IEXTEN; 2131d522f475Smrg#endif 2132d522f475Smrg#ifdef ECHOCTL 2133d522f475Smrg d_tio.c_lflag |= ECHOCTL | IEXTEN; 2134d522f475Smrg#endif 2135d522f475Smrg#ifndef USE_POSIX_TERMIOS 2136d522f475Smrg#ifdef NTTYDISC 2137d522f475Smrg d_tio.c_line = NTTYDISC; 2138d522f475Smrg#else 2139d522f475Smrg d_tio.c_line = 0; 2140d522f475Smrg#endif 2141d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 2142d522f475Smrg#ifdef __sgi 2143d522f475Smrg d_tio.c_cflag &= ~(HUPCL | PARENB); 2144d522f475Smrg d_tio.c_iflag |= BRKINT | ISTRIP | IGNPAR; 2145d522f475Smrg#endif 2146d522f475Smrg#ifdef __MVS__ 2147d522f475Smrg d_tio.c_cflag &= ~(HUPCL | PARENB); 2148d522f475Smrg#endif 2149d522f475Smrg { 2150d522f475Smrg Cardinal nn; 2151d522f475Smrg int i; 2152d522f475Smrg 2153d522f475Smrg /* try to inherit tty settings */ 2154d522f475Smrg for (i = 0; i <= 2; i++) { 2155d522f475Smrg TERMIO_STRUCT deftio; 2156d522f475Smrg if (ttyGetAttr(i, &deftio) == 0) { 2157d522f475Smrg for (nn = 0; nn < XtNumber(known_ttyChars); ++nn) { 2158d522f475Smrg if (validTtyChar(d_tio, nn)) { 2159d522f475Smrg d_tio.c_cc[known_ttyChars[nn].sysMode] = 2160d522f475Smrg deftio.c_cc[known_ttyChars[nn].sysMode]; 2161d522f475Smrg } 2162d522f475Smrg } 2163d522f475Smrg break; 2164d522f475Smrg } 2165d522f475Smrg } 2166d522f475Smrg } 2167d522f475Smrg#if defined(USE_TERMIOS) || defined(USE_POSIX_TERMIOS) /* { */ 2168d522f475Smrg d_tio.c_cc[VMIN] = 1; 2169d522f475Smrg d_tio.c_cc[VTIME] = 0; 2170d522f475Smrg#endif /* } */ 2171d522f475Smrg#ifdef HAS_LTCHARS /* { */ 2172d522f475Smrg d_ltc.t_suspc = CharOf('\000'); /* t_suspc */ 2173d522f475Smrg d_ltc.t_dsuspc = CharOf('\000'); /* t_dsuspc */ 2174d522f475Smrg d_ltc.t_rprntc = CharOf('\377'); /* reserved... */ 2175d522f475Smrg d_ltc.t_flushc = CharOf('\377'); 2176d522f475Smrg d_ltc.t_werasc = CharOf('\377'); 2177d522f475Smrg d_ltc.t_lnextc = CharOf('\377'); 2178d522f475Smrg#endif /* } HAS_LTCHARS */ 2179d522f475Smrg 2180d522f475Smrg#ifdef TIOCLSET /* { */ 2181d522f475Smrg d_lmode = 0; 2182d522f475Smrg#endif /* } TIOCLSET */ 2183d522f475Smrg#endif /* } macII, ATT, CRAY */ 2184d522f475Smrg#endif /* } TERMIO_STRUCT */ 2185d522f475Smrg 2186d522f475Smrg /* Init the Toolkit. */ 2187d522f475Smrg { 2188d522f475Smrg#if defined(HAVE_POSIX_SAVED_IDS) && !defined(USE_UTMP_SETGID) && !defined(USE_UTEMPTER) 2189d522f475Smrg setEffectiveGroup(save_rgid); 2190d522f475Smrg setEffectiveUser(save_ruid); 2191d522f475Smrg TRACE_IDS; 2192d522f475Smrg#endif 2193e0a2b6dfSmrg init_colored_cursor(); 2194d522f475Smrg 21950bd37d32Smrg toplevel = xtermOpenApplication(&app_con, 21960bd37d32Smrg my_class, 21970bd37d32Smrg optionDescList, 21980bd37d32Smrg XtNumber(optionDescList), 21990bd37d32Smrg &argc, (String *) argv, 22000bd37d32Smrg fallback_resources, 22010bd37d32Smrg sessionShellWidgetClass, 22020bd37d32Smrg NULL, 0); 2203d522f475Smrg 2204d522f475Smrg XtGetApplicationResources(toplevel, (XtPointer) &resource, 2205d522f475Smrg application_resources, 2206d522f475Smrg XtNumber(application_resources), NULL, 0); 2207d522f475Smrg TRACE_XRES(); 2208a1f3da82Smrg#if OPT_MAXIMIZE 2209a1f3da82Smrg resource.fullscreen = extendedBoolean(resource.fullscreen_s, 2210a1f3da82Smrg tblFullscreen, 2211a1f3da82Smrg XtNumber(tblFullscreen)); 2212a1f3da82Smrg#endif 2213e39b573cSmrg VTInitTranslations(); 2214d522f475Smrg#if OPT_PTY_HANDSHAKE 2215d522f475Smrg resource.wait_for_map0 = resource.wait_for_map; 2216d522f475Smrg#endif 2217d522f475Smrg 2218d522f475Smrg#if defined(HAVE_POSIX_SAVED_IDS) && !defined(USE_UTMP_SETGID) 2219d522f475Smrg#if !defined(DISABLE_SETUID) || !defined(DISABLE_SETGID) 2220d522f475Smrg#if !defined(DISABLE_SETUID) 2221d522f475Smrg setEffectiveUser(save_euid); 2222d522f475Smrg#endif 2223d522f475Smrg#if !defined(DISABLE_SETGID) 2224d522f475Smrg setEffectiveGroup(save_egid); 2225d522f475Smrg#endif 2226d522f475Smrg TRACE_IDS; 2227d522f475Smrg#endif 2228d522f475Smrg#endif 2229d522f475Smrg } 2230d522f475Smrg 2231d522f475Smrg /* 2232d522f475Smrg * ICCCM delete_window. 2233d522f475Smrg */ 2234d522f475Smrg XtAppAddActions(app_con, actionProcs, XtNumber(actionProcs)); 2235d522f475Smrg 2236d522f475Smrg /* 2237d522f475Smrg * fill in terminal modes 2238d522f475Smrg */ 2239d522f475Smrg if (resource.tty_modes) { 2240d522f475Smrg int n = parse_tty_modes(resource.tty_modes, ttymodelist); 2241d522f475Smrg if (n < 0) { 22420bd37d32Smrg xtermWarning("bad tty modes \"%s\"\n", resource.tty_modes); 2243d522f475Smrg } else if (n > 0) { 2244d522f475Smrg override_tty_modes = True; 2245d522f475Smrg } 2246d522f475Smrg } 22470bd37d32Smrg initZIconBeep(); 2248d522f475Smrg hold_screen = resource.hold_screen ? 1 : 0; 2249d522f475Smrg if (resource.icon_geometry != NULL) { 2250d522f475Smrg int scr, junk; 2251d522f475Smrg int ix, iy; 2252d522f475Smrg Arg args[2]; 2253d522f475Smrg 2254d522f475Smrg for (scr = 0; /* yyuucchh */ 2255d522f475Smrg XtScreen(toplevel) != ScreenOfDisplay(XtDisplay(toplevel), scr); 2256d522f475Smrg scr++) ; 2257d522f475Smrg 2258d522f475Smrg args[0].name = XtNiconX; 2259d522f475Smrg args[1].name = XtNiconY; 2260d522f475Smrg XGeometry(XtDisplay(toplevel), scr, resource.icon_geometry, "", 2261d522f475Smrg 0, 0, 0, 0, 0, &ix, &iy, &junk, &junk); 2262d522f475Smrg args[0].value = (XtArgVal) ix; 2263d522f475Smrg args[1].value = (XtArgVal) iy; 2264d522f475Smrg XtSetValues(toplevel, args, 2); 2265d522f475Smrg } 2266d522f475Smrg 2267d522f475Smrg XtSetValues(toplevel, ourTopLevelShellArgs, 2268d522f475Smrg number_ourTopLevelShellArgs); 2269d522f475Smrg 2270d522f475Smrg#if OPT_WIDE_CHARS 2271d522f475Smrg /* seems as good a place as any */ 2272d522f475Smrg init_classtab(); 2273d522f475Smrg#endif 2274d522f475Smrg 2275d522f475Smrg /* Parse the rest of the command line */ 2276d522f475Smrg TRACE_ARGV("After XtOpenApplication", argv); 2277d522f475Smrg for (argc--, argv++; argc > 0; argc--, argv++) { 22780bd37d32Smrg if (!isOption(*argv)) { 2279d522f475Smrg#ifdef VMS 2280d522f475Smrg Syntax(*argv); 2281d522f475Smrg#else 2282d522f475Smrg if (argc > 1) 2283d522f475Smrg Syntax(*argv); 2284d522f475Smrg continue; 2285d522f475Smrg#endif 22860bd37d32Smrg } 2287d522f475Smrg 2288d522f475Smrg TRACE(("parsing %s\n", argv[0])); 2289d522f475Smrg switch (argv[0][1]) { 2290d522f475Smrg case 'C': 2291d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 2292d522f475Smrg#ifndef __sgi 2293d522f475Smrg { 2294d522f475Smrg struct stat sbuf; 2295d522f475Smrg 2296d522f475Smrg /* Must be owner and have read/write permission. 2297d522f475Smrg xdm cooperates to give the console the right user. */ 2298d522f475Smrg if (!stat("/dev/console", &sbuf) && 2299d522f475Smrg (sbuf.st_uid == save_ruid) && 2300d522f475Smrg !access("/dev/console", R_OK | W_OK)) { 2301d522f475Smrg Console = True; 2302d522f475Smrg } else 2303d522f475Smrg Console = False; 2304d522f475Smrg } 2305d522f475Smrg#else /* __sgi */ 2306d522f475Smrg Console = True; 2307d522f475Smrg#endif /* __sgi */ 2308d522f475Smrg#endif /* TIOCCONS */ 2309d522f475Smrg continue; 2310d522f475Smrg case 'S': 2311d522f475Smrg if (!ParseSccn(*argv + 2)) 2312d522f475Smrg Syntax(*argv); 2313d522f475Smrg continue; 2314d522f475Smrg#ifdef DEBUG 2315d522f475Smrg case 'D': 2316d522f475Smrg debug = True; 2317d522f475Smrg continue; 2318d522f475Smrg#endif /* DEBUG */ 23190bd37d32Smrg case 'c': 23200bd37d32Smrg if (strcmp(argv[0], "-class")) 2321d522f475Smrg Syntax(*argv); 23220bd37d32Smrg argc--, argv++; 2323d522f475Smrg continue; 2324d522f475Smrg case 'e': 23250bd37d32Smrg if (strcmp(argv[0], "-e")) 2326d522f475Smrg Syntax(*argv); 23270bd37d32Smrg command_to_exec = (argv + 1); 2328d522f475Smrg break; 2329d522f475Smrg case 'i': 23300bd37d32Smrg if (strcmp(argv[0], "-into")) 2331d522f475Smrg Syntax(*argv); 23320bd37d32Smrg argc--, argv++; 2333d522f475Smrg continue; 2334d522f475Smrg 2335d522f475Smrg default: 2336d522f475Smrg Syntax(*argv); 2337d522f475Smrg } 2338d522f475Smrg break; 2339d522f475Smrg } 2340d522f475Smrg 2341d522f475Smrg SetupMenus(toplevel, &form_top, &menu_top, &menu_high); 2342d522f475Smrg 2343d522f475Smrg term = (XtermWidget) XtVaCreateManagedWidget("vt100", xtermWidgetClass, 2344d522f475Smrg form_top, 2345d522f475Smrg#if OPT_TOOLBAR 2346d522f475Smrg XtNmenuBar, menu_top, 2347d522f475Smrg XtNresizable, True, 2348d522f475Smrg XtNfromVert, menu_top, 2349d522f475Smrg XtNleft, XawChainLeft, 2350d522f475Smrg XtNright, XawChainRight, 2351d522f475Smrg XtNtop, XawChainTop, 2352d522f475Smrg XtNbottom, XawChainBottom, 2353d522f475Smrg XtNmenuHeight, menu_high, 2354d522f475Smrg#endif 2355d522f475Smrg (XtPointer) 0); 2356d522f475Smrg decode_keyboard_type(term, &resource); 2357d522f475Smrg 2358d522f475Smrg screen = TScreenOf(term); 2359d522f475Smrg screen->inhibit = 0; 2360d522f475Smrg 2361d522f475Smrg#ifdef ALLOWLOGGING 2362d522f475Smrg if (term->misc.logInhibit) 2363d522f475Smrg screen->inhibit |= I_LOG; 2364d522f475Smrg#endif 2365d522f475Smrg if (term->misc.signalInhibit) 2366d522f475Smrg screen->inhibit |= I_SIGNAL; 2367d522f475Smrg#if OPT_TEK4014 2368d522f475Smrg if (term->misc.tekInhibit) 2369d522f475Smrg screen->inhibit |= I_TEK; 2370d522f475Smrg#endif 2371d522f475Smrg 2372d522f475Smrg /* 2373d522f475Smrg * We might start by showing the tek4014 window. 2374d522f475Smrg */ 2375d522f475Smrg#if OPT_TEK4014 2376d522f475Smrg if (screen->inhibit & I_TEK) 2377d522f475Smrg TEK4014_ACTIVE(term) = False; 2378d522f475Smrg 2379d522f475Smrg if (TEK4014_ACTIVE(term) && !TekInit()) 2380d522f475Smrg SysError(ERROR_INIT); 2381d522f475Smrg#endif 2382d522f475Smrg 2383d522f475Smrg /* 2384d522f475Smrg * Start the toolbar at this point, after the first window has been setup. 2385d522f475Smrg */ 2386d522f475Smrg#if OPT_TOOLBAR 2387d522f475Smrg ShowToolbar(resource.toolBar); 2388d522f475Smrg#endif 2389d522f475Smrg 23900bd37d32Smrg xtermOpenSession(); 2391d522f475Smrg 2392d522f475Smrg /* 2393d522f475Smrg * Set title and icon name if not specified 2394d522f475Smrg */ 2395d522f475Smrg if (command_to_exec) { 2396d522f475Smrg Arg args[2]; 2397d522f475Smrg 2398d522f475Smrg if (!resource.title) { 2399d522f475Smrg if (command_to_exec) { 2400d522f475Smrg resource.title = x_basename(command_to_exec[0]); 2401d522f475Smrg } /* else not reached */ 2402d522f475Smrg } 2403d522f475Smrg 2404d522f475Smrg if (!resource.icon_name) 2405d522f475Smrg resource.icon_name = resource.title; 2406d522f475Smrg XtSetArg(args[0], XtNtitle, resource.title); 2407d522f475Smrg XtSetArg(args[1], XtNiconName, resource.icon_name); 2408d522f475Smrg 24090bd37d32Smrg TRACE(("setting:\n\ttitle \"%s\"\n\ticon \"%s\"\n\thint \"%s\"\n\tbased on command \"%s\"\n", 2410d522f475Smrg resource.title, 2411d522f475Smrg resource.icon_name, 24120bd37d32Smrg NonNull(resource.icon_hint), 2413d522f475Smrg *command_to_exec)); 2414d522f475Smrg 2415d522f475Smrg XtSetValues(toplevel, args, 2); 2416d522f475Smrg } 2417d522f475Smrg#if OPT_LUIT_PROG 2418d522f475Smrg if (term->misc.callfilter) { 24190bd37d32Smrg char **split_filter = x_splitargs(term->misc.localefilter); 24200bd37d32Smrg unsigned count_split = x_countargv(split_filter); 24210bd37d32Smrg unsigned count_exec = x_countargv(command_to_exec); 24220bd37d32Smrg unsigned count_using = (unsigned) (term->misc.use_encoding ? 2 : 0); 24230bd37d32Smrg 24240bd37d32Smrg command_to_exec_with_luit = TypeCallocN(char *, 24250bd37d32Smrg (count_split 24260bd37d32Smrg + count_exec 24270bd37d32Smrg + count_using 24280bd37d32Smrg + 8)); 24290bd37d32Smrg if (command_to_exec_with_luit == NULL) 24300bd37d32Smrg SysError(ERROR_LUMALLOC); 24310bd37d32Smrg 24320bd37d32Smrg x_appendargv(command_to_exec_with_luit, split_filter); 24330bd37d32Smrg if (count_using) { 24340bd37d32Smrg char *encoding_opt[4]; 24350bd37d32Smrg encoding_opt[0] = x_strdup("-encoding"); 24360bd37d32Smrg encoding_opt[1] = term->misc.locale_str; 24370bd37d32Smrg encoding_opt[2] = 0; 24380bd37d32Smrg x_appendargv(command_to_exec_with_luit, encoding_opt); 24390bd37d32Smrg } 24400bd37d32Smrg command_length_with_luit = x_countargv(command_to_exec_with_luit); 24410bd37d32Smrg if (count_exec) { 24420bd37d32Smrg char *delimiter[2]; 24430bd37d32Smrg delimiter[0] = x_strdup("--"); 24440bd37d32Smrg delimiter[1] = 0; 24450bd37d32Smrg x_appendargv(command_to_exec_with_luit, delimiter); 24460bd37d32Smrg x_appendargv(command_to_exec_with_luit, command_to_exec); 2447d522f475Smrg } 24480bd37d32Smrg TRACE_ARGV("luit command", command_to_exec_with_luit); 24490bd37d32Smrg xtermSetenv("XTERM_FILTER", *command_to_exec_with_luit); 2450d522f475Smrg } 2451d522f475Smrg#endif 2452d522f475Smrg 24530bd37d32Smrg if_DEBUG({ 2454d522f475Smrg /* Set up stderr properly. Opening this log file cannot be 2455d522f475Smrg done securely by a privileged xterm process (although we try), 2456d522f475Smrg so the debug feature is disabled by default. */ 2457e39b573cSmrg char dbglogfile[TIMESTAMP_LEN + 20]; 2458d522f475Smrg int i = -1; 24590bd37d32Smrg timestamp_filename(dbglogfile, "xterm.debug.log."); 24600bd37d32Smrg if (creat_as(save_ruid, save_rgid, False, dbglogfile, 0600) > 0) { 24610bd37d32Smrg i = open(dbglogfile, O_WRONLY | O_TRUNC); 2462d522f475Smrg } 2463d522f475Smrg if (i >= 0) { 2464d522f475Smrg dup2(i, 2); 2465d522f475Smrg 2466d522f475Smrg /* mark this file as close on exec */ 2467d522f475Smrg (void) fcntl(i, F_SETFD, 1); 2468d522f475Smrg } 24690bd37d32Smrg }); 2470d522f475Smrg 2471d522f475Smrg spawnXTerm(term); 2472d522f475Smrg 2473d522f475Smrg#ifndef VMS 2474d522f475Smrg /* Child process is out there, let's catch its termination */ 2475d522f475Smrg 2476d522f475Smrg#ifdef USE_POSIX_SIGNALS 2477d522f475Smrg (void) posix_signal(SIGCHLD, reapchild); 2478d522f475Smrg#else 2479d522f475Smrg (void) signal(SIGCHLD, reapchild); 2480d522f475Smrg#endif 2481d522f475Smrg /* Realize procs have now been executed */ 2482d522f475Smrg 2483d522f475Smrg if (am_slave >= 0) { /* Write window id so master end can read and use */ 2484d522f475Smrg char buf[80]; 2485d522f475Smrg 2486d522f475Smrg buf[0] = '\0'; 2487d522f475Smrg sprintf(buf, "%lx\n", XtWindow(SHELL_OF(CURRENT_EMU()))); 248820d2c4d2Smrg IGNORE_RC(write(screen->respond, buf, strlen(buf))); 2489d522f475Smrg } 2490d522f475Smrg#ifdef AIXV3 2491d522f475Smrg#if (OSMAJORVERSION < 4) 2492d522f475Smrg /* In AIXV3, xterms started from /dev/console have CLOCAL set. 2493d522f475Smrg * This means we need to clear CLOCAL so that SIGHUP gets sent 2494d522f475Smrg * to the slave-pty process when xterm exits. 2495d522f475Smrg */ 2496d522f475Smrg 2497d522f475Smrg { 2498d522f475Smrg TERMIO_STRUCT tio; 2499d522f475Smrg 2500d522f475Smrg if (ttyGetAttr(screen->respond, &tio) == -1) 2501d522f475Smrg SysError(ERROR_TIOCGETP); 2502d522f475Smrg 2503d522f475Smrg tio.c_cflag &= ~(CLOCAL); 2504d522f475Smrg 2505d522f475Smrg if (ttySetAttr(screen->respond, &tio) == -1) 2506d522f475Smrg SysError(ERROR_TIOCSETP); 2507d522f475Smrg } 2508d522f475Smrg#endif 2509d522f475Smrg#endif 2510d522f475Smrg#if defined(USE_ANY_SYSV_TERMIO) || defined(__MVS__) 2511d522f475Smrg if (0 > (mode = fcntl(screen->respond, F_GETFL, 0))) 2512d522f475Smrg SysError(ERROR_F_GETFL); 2513d522f475Smrg#ifdef O_NDELAY 2514d522f475Smrg mode |= O_NDELAY; 2515d522f475Smrg#else 2516d522f475Smrg mode |= O_NONBLOCK; 2517d522f475Smrg#endif /* O_NDELAY */ 2518d522f475Smrg if (fcntl(screen->respond, F_SETFL, mode)) 2519d522f475Smrg SysError(ERROR_F_SETFL); 2520d522f475Smrg#else /* !USE_ANY_SYSV_TERMIO */ 2521d522f475Smrg mode = 1; 2522d522f475Smrg if (ioctl(screen->respond, FIONBIO, (char *) &mode) == -1) 2523d522f475Smrg SysError(ERROR_FIONBIO); 2524d522f475Smrg#endif /* USE_ANY_SYSV_TERMIO, etc */ 2525d522f475Smrg 2526d522f475Smrg /* The erase character is used to delete the current completion */ 2527d522f475Smrg#if OPT_DABBREV 2528d522f475Smrg#ifdef TERMIO_STRUCT 2529d522f475Smrg screen->dabbrev_erase_char = d_tio.c_cc[VERASE]; 2530d522f475Smrg#else 2531d522f475Smrg screen->dabbrev_erase_char = d_sg.sg_erase; 2532d522f475Smrg#endif 2533d522f475Smrg TRACE(("set dabbrev erase_char %#x\n", screen->dabbrev_erase_char)); 2534d522f475Smrg#endif 2535d522f475Smrg 2536d522f475Smrg FD_ZERO(&pty_mask); 2537d522f475Smrg FD_ZERO(&X_mask); 2538d522f475Smrg FD_ZERO(&Select_mask); 2539d522f475Smrg FD_SET(screen->respond, &pty_mask); 2540d522f475Smrg FD_SET(ConnectionNumber(screen->display), &X_mask); 2541d522f475Smrg FD_SET(screen->respond, &Select_mask); 2542d522f475Smrg FD_SET(ConnectionNumber(screen->display), &Select_mask); 2543d522f475Smrg max_plus1 = ((screen->respond < ConnectionNumber(screen->display)) 2544d522f475Smrg ? (1 + ConnectionNumber(screen->display)) 2545d522f475Smrg : (1 + screen->respond)); 2546d522f475Smrg 2547d522f475Smrg#endif /* !VMS */ 25480bd37d32Smrg if_DEBUG({ 25490bd37d32Smrg TRACE(("debugging on pid %d\n", (int) getpid())); 25500bd37d32Smrg }); 2551d522f475Smrg XSetErrorHandler(xerror); 2552d522f475Smrg XSetIOErrorHandler(xioerror); 2553e39b573cSmrg IceSetIOErrorHandler(ice_error); 2554d522f475Smrg 2555d522f475Smrg initPtyData(&VTbuffer); 2556d522f475Smrg#ifdef ALLOWLOGGING 2557d522f475Smrg if (term->misc.log_on) { 255820d2c4d2Smrg StartLog(term); 2559d522f475Smrg } 2560d522f475Smrg#endif 2561d522f475Smrg 25620bd37d32Smrg xtermEmbedWindow(winToEmbedInto); 2563d522f475Smrg#if OPT_COLOR_RES 2564a1f3da82Smrg TRACE(("checking reverseVideo before rv %s fg %s, bg %s\n", 2565a1f3da82Smrg term->misc.re_verse0 ? "reverse" : "normal", 256620d2c4d2Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_FG].resource), 256720d2c4d2Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_BG].resource))); 2568d522f475Smrg 2569a1f3da82Smrg if (term->misc.re_verse0) { 2570a1f3da82Smrg if (isDefaultForeground(TScreenOf(term)->Tcolors[TEXT_FG].resource) 2571a1f3da82Smrg && isDefaultBackground(TScreenOf(term)->Tcolors[TEXT_BG].resource)) { 2572a1f3da82Smrg TScreenOf(term)->Tcolors[TEXT_FG].resource = x_strdup(XtDefaultBackground); 2573a1f3da82Smrg TScreenOf(term)->Tcolors[TEXT_BG].resource = x_strdup(XtDefaultForeground); 2574a1f3da82Smrg } else { 2575a1f3da82Smrg ReverseVideo(term); 2576a1f3da82Smrg } 2577a1f3da82Smrg term->misc.re_verse = True; 2578a1f3da82Smrg update_reversevideo(); 2579a1f3da82Smrg TRACE(("updated reverseVideo after rv %s fg %s, bg %s\n", 2580a1f3da82Smrg term->misc.re_verse ? "reverse" : "normal", 2581a1f3da82Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_FG].resource), 2582a1f3da82Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_BG].resource))); 2583a1f3da82Smrg } 2584d522f475Smrg#endif /* OPT_COLOR_RES */ 2585d522f475Smrg 2586956cc18dSsnj#if OPT_MAXIMIZE 2587956cc18dSsnj if (resource.maximized) 2588956cc18dSsnj RequestMaximize(term, True); 2589956cc18dSsnj#endif 2590d522f475Smrg for (;;) { 2591d522f475Smrg#if OPT_TEK4014 2592d522f475Smrg if (TEK4014_ACTIVE(term)) 2593d522f475Smrg TekRun(); 2594d522f475Smrg else 2595d522f475Smrg#endif 2596956cc18dSsnj VTRun(term); 2597d522f475Smrg } 2598d522f475Smrg} 2599d522f475Smrg 2600956cc18dSsnj#if defined(__osf__) || (defined(__GLIBC__) && !defined(USE_USG_PTYS)) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) 2601d522f475Smrg#define USE_OPENPTY 1 2602d522f475Smrgstatic int opened_tty = -1; 2603d522f475Smrg#endif 2604d522f475Smrg 2605d522f475Smrg/* 2606d522f475Smrg * This function opens up a pty master and stuffs its value into pty. 2607d522f475Smrg * 2608d522f475Smrg * If it finds one, it returns a value of 0. If it does not find one, 2609d522f475Smrg * it returns a value of !0. This routine is designed to be re-entrant, 2610d522f475Smrg * so that if a pty master is found and later, we find that the slave 2611d522f475Smrg * has problems, we can re-enter this function and get another one. 2612d522f475Smrg */ 2613d522f475Smrgstatic int 2614d522f475Smrgget_pty(int *pty, char *from GCC_UNUSED) 2615d522f475Smrg{ 2616d522f475Smrg int result = 1; 2617d522f475Smrg 26180bd37d32Smrg#if defined(USE_OPENPTY) 26190bd37d32Smrg result = openpty(pty, &opened_tty, ttydev, NULL, NULL); 26200bd37d32Smrg#elif defined(HAVE_POSIX_OPENPT) && defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT_PTY_ISATTY) 26210bd37d32Smrg if ((*pty = posix_openpt(O_RDWR)) >= 0) { 26220bd37d32Smrg char *name = ptsname(*pty); 26230bd37d32Smrg if (name != 0) { 26240bd37d32Smrg strcpy(ttydev, name); 26250bd37d32Smrg result = 0; 26260bd37d32Smrg } 26270bd37d32Smrg } 26280bd37d32Smrg#ifdef USE_PTY_SEARCH 26290bd37d32Smrg if (result) { 26300bd37d32Smrg result = pty_search(pty); 26310bd37d32Smrg } 26320bd37d32Smrg#endif 26330bd37d32Smrg#elif defined(PUCC_PTYD) 2634d522f475Smrg result = ((*pty = openrpty(ttydev, ptydev, 2635d522f475Smrg (resource.utmpInhibit ? OPTY_NOP : OPTY_LOGIN), 2636d522f475Smrg save_ruid, from)) < 0); 2637d522f475Smrg#elif defined(__QNXNTO__) 2638d522f475Smrg result = pty_search(pty); 2639d522f475Smrg#else 2640d522f475Smrg#if defined(USE_USG_PTYS) || defined(__CYGWIN__) 2641d522f475Smrg#ifdef __GLIBC__ /* if __GLIBC__ and USE_USG_PTYS, we know glibc >= 2.1 */ 2642d522f475Smrg /* GNU libc 2 allows us to abstract away from having to know the 2643d522f475Smrg master pty device name. */ 2644d522f475Smrg if ((*pty = getpt()) >= 0) { 2645d522f475Smrg char *name = ptsname(*pty); 2646d522f475Smrg if (name != 0) { /* if filesystem is trashed, this may be null */ 2647d522f475Smrg strcpy(ttydev, name); 2648d522f475Smrg result = 0; 2649d522f475Smrg } 2650d522f475Smrg } 2651d522f475Smrg#elif defined(__MVS__) 2652d522f475Smrg result = pty_search(pty); 2653d522f475Smrg#else 26540bd37d32Smrg result = ((*pty = open("/dev/ptmx", O_RDWR)) < 0); 2655d522f475Smrg#endif 26560bd37d32Smrg#if defined(SVR4) || defined(__SCO__) 26570bd37d32Smrg if (!result) 26580bd37d32Smrg strcpy(ttydev, ptsname(*pty)); 2659d522f475Smrg#endif 2660d522f475Smrg 2661d522f475Smrg#elif defined(AIXV3) 2662d522f475Smrg 2663d522f475Smrg if ((*pty = open("/dev/ptc", O_RDWR)) >= 0) { 2664d522f475Smrg strcpy(ttydev, ttyname(*pty)); 2665d522f475Smrg result = 0; 2666d522f475Smrg } 2667d522f475Smrg#elif defined(__convex__) 2668d522f475Smrg 2669d522f475Smrg char *pty_name; 2670d522f475Smrg extern char *getpty(void); 2671d522f475Smrg 2672d522f475Smrg while ((pty_name = getpty()) != NULL) { 2673d522f475Smrg if ((*pty = open(pty_name, O_RDWR)) >= 0) { 2674d522f475Smrg strcpy(ptydev, pty_name); 2675d522f475Smrg strcpy(ttydev, pty_name); 2676d522f475Smrg *x_basename(ttydev) = 't'; 2677d522f475Smrg result = 0; 2678d522f475Smrg break; 2679d522f475Smrg } 2680d522f475Smrg } 2681d522f475Smrg 2682d522f475Smrg#elif defined(sequent) 2683d522f475Smrg 2684d522f475Smrg result = ((*pty = getpseudotty(&ttydev, &ptydev)) < 0); 2685d522f475Smrg 2686d522f475Smrg#elif defined(__sgi) && (OSMAJORVERSION >= 4) 2687d522f475Smrg 2688d522f475Smrg char *tty_name; 2689d522f475Smrg 2690d522f475Smrg tty_name = _getpty(pty, O_RDWR, 0622, 0); 2691d522f475Smrg if (tty_name != 0) { 2692d522f475Smrg strcpy(ttydev, tty_name); 2693d522f475Smrg result = 0; 2694d522f475Smrg } 2695d522f475Smrg#elif (defined(__sgi) && (OSMAJORVERSION < 4)) || (defined(umips) && defined (SYSTYPE_SYSV)) 2696d522f475Smrg 2697d522f475Smrg struct stat fstat_buf; 2698d522f475Smrg 2699d522f475Smrg *pty = open("/dev/ptc", O_RDWR); 2700d522f475Smrg if (*pty >= 0 && (fstat(*pty, &fstat_buf)) >= 0) { 2701d522f475Smrg result = 0; 2702d522f475Smrg sprintf(ttydev, "/dev/ttyq%d", minor(fstat_buf.st_rdev)); 2703d522f475Smrg } 2704d522f475Smrg#elif defined(__hpux) 2705d522f475Smrg 2706d522f475Smrg /* 2707d522f475Smrg * Use the clone device if it works, otherwise use pty_search logic. 2708d522f475Smrg */ 2709d522f475Smrg if ((*pty = open("/dev/ptym/clone", O_RDWR)) >= 0) { 2710d522f475Smrg char *name = ptsname(*pty); 2711d522f475Smrg if (name != 0) { 2712d522f475Smrg strcpy(ttydev, name); 2713d522f475Smrg result = 0; 2714d522f475Smrg } else { /* permissions, or other unexpected problem */ 2715d522f475Smrg close(*pty); 2716d522f475Smrg *pty = -1; 2717d522f475Smrg result = pty_search(pty); 2718d522f475Smrg } 2719d522f475Smrg } else { 2720d522f475Smrg result = pty_search(pty); 2721d522f475Smrg } 2722d522f475Smrg 2723d522f475Smrg#else 2724d522f475Smrg 2725d522f475Smrg result = pty_search(pty); 2726d522f475Smrg 2727d522f475Smrg#endif 2728d522f475Smrg#endif 2729d522f475Smrg 2730d522f475Smrg TRACE(("get_pty(ttydev=%s, ptydev=%s) %s fd=%d\n", 2731d522f475Smrg ttydev != 0 ? ttydev : "?", 2732d522f475Smrg ptydev != 0 ? ptydev : "?", 2733d522f475Smrg result ? "FAIL" : "OK", 2734d522f475Smrg pty != 0 ? *pty : -1)); 2735d522f475Smrg return result; 2736d522f475Smrg} 2737d522f475Smrg 2738d522f475Smrgstatic void 2739e0a2b6dfSmrgset_pty_permissions(uid_t uid, unsigned gid, unsigned mode) 2740d522f475Smrg{ 2741d522f475Smrg#ifdef USE_TTY_GROUP 2742d522f475Smrg struct group *ttygrp; 2743d522f475Smrg 2744d522f475Smrg if ((ttygrp = getgrnam(TTY_GROUP_NAME)) != 0) { 2745d522f475Smrg gid = ttygrp->gr_gid; 2746d522f475Smrg mode &= 0660U; 2747d522f475Smrg } 2748d522f475Smrg endgrent(); 2749d522f475Smrg#endif /* USE_TTY_GROUP */ 2750d522f475Smrg 2751d522f475Smrg TRACE_IDS; 2752d522f475Smrg set_owner(ttydev, uid, gid, mode); 2753d522f475Smrg} 2754d522f475Smrg 2755d522f475Smrg#ifdef get_pty /* USE_UTMP_SETGID */ 2756d522f475Smrg#undef get_pty 2757d522f475Smrg/* 2758d522f475Smrg * Call the real get_pty() before relinquishing root-setuid, caching the 2759d522f475Smrg * result. 2760d522f475Smrg */ 2761d522f475Smrgstatic int 2762d522f475Smrgget_pty(int *pty, char *from) 2763d522f475Smrg{ 2764d522f475Smrg static int m_pty = -1; 2765d522f475Smrg int result = -1; 2766d522f475Smrg 2767d522f475Smrg if (pty == NULL) { 2768d522f475Smrg result = really_get_pty(&m_pty, from); 2769d522f475Smrg 2770d522f475Smrg seteuid(0); 2771d522f475Smrg set_pty_permissions(save_ruid, save_rgid, 0600U); 2772d522f475Smrg seteuid(save_ruid); 2773d522f475Smrg TRACE_IDS; 2774d522f475Smrg 2775d522f475Smrg#ifdef USE_OPENPTY 2776d522f475Smrg if (opened_tty >= 0) { 2777d522f475Smrg close(opened_tty); 2778d522f475Smrg opened_tty = -1; 2779d522f475Smrg } 2780d522f475Smrg#endif 2781d522f475Smrg } else if (m_pty != -1) { 2782d522f475Smrg *pty = m_pty; 2783d522f475Smrg result = 0; 2784d522f475Smrg } else { 2785d522f475Smrg result = -1; 2786d522f475Smrg } 27870bd37d32Smrg TRACE(("get_pty(ttydev=%s, ptydev=%s) %s fd=%d (utmp setgid)\n", 27880bd37d32Smrg ttydev != 0 ? ttydev : "?", 27890bd37d32Smrg ptydev != 0 ? ptydev : "?", 27900bd37d32Smrg result ? "FAIL" : "OK", 27910bd37d32Smrg pty != 0 ? *pty : -1)); 2792d522f475Smrg return result; 2793d522f475Smrg} 2794d522f475Smrg#endif 2795d522f475Smrg 2796d522f475Smrg/* 2797d522f475Smrg * Called from get_pty to iterate over likely pseudo terminals 2798d522f475Smrg * we might allocate. Used on those systems that do not have 2799d522f475Smrg * a functional interface for allocating a pty. 2800d522f475Smrg * Returns 0 if found a pty, 1 if fails. 2801d522f475Smrg */ 2802d522f475Smrg#ifdef USE_PTY_SEARCH 2803d522f475Smrgstatic int 2804d522f475Smrgpty_search(int *pty) 2805d522f475Smrg{ 2806d522f475Smrg static int devindex = 0, letter = 0; 2807d522f475Smrg 2808d522f475Smrg#if defined(CRAY) || defined(__MVS__) 2809d522f475Smrg while (devindex < MAXPTTYS) { 2810d522f475Smrg sprintf(ttydev, TTYFORMAT, devindex); 2811d522f475Smrg sprintf(ptydev, PTYFORMAT, devindex); 2812d522f475Smrg devindex++; 2813d522f475Smrg 2814d522f475Smrg TRACE(("pty_search(ttydev=%s, ptydev=%s)\n", ttydev, ptydev)); 2815d522f475Smrg if ((*pty = open(ptydev, O_RDWR)) >= 0) { 2816d522f475Smrg return 0; 2817d522f475Smrg } 2818d522f475Smrg } 2819d522f475Smrg#else /* CRAY || __MVS__ */ 2820d522f475Smrg while (PTYCHAR1[letter]) { 2821d522f475Smrg ttydev[strlen(ttydev) - 2] = 2822d522f475Smrg ptydev[strlen(ptydev) - 2] = PTYCHAR1[letter]; 2823d522f475Smrg 2824d522f475Smrg while (PTYCHAR2[devindex]) { 2825d522f475Smrg ttydev[strlen(ttydev) - 1] = 2826d522f475Smrg ptydev[strlen(ptydev) - 1] = PTYCHAR2[devindex]; 2827d522f475Smrg devindex++; 2828d522f475Smrg 2829d522f475Smrg TRACE(("pty_search(ttydev=%s, ptydev=%s)\n", ttydev, ptydev)); 2830d522f475Smrg if ((*pty = open(ptydev, O_RDWR)) >= 0) { 2831d522f475Smrg#ifdef sun 2832d522f475Smrg /* Need to check the process group of the pty. 2833d522f475Smrg * If it exists, then the slave pty is in use, 2834d522f475Smrg * and we need to get another one. 2835d522f475Smrg */ 2836d522f475Smrg int pgrp_rtn; 2837d522f475Smrg if (ioctl(*pty, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) { 2838d522f475Smrg close(*pty); 2839d522f475Smrg continue; 2840d522f475Smrg } 2841d522f475Smrg#endif /* sun */ 2842d522f475Smrg return 0; 2843d522f475Smrg } 2844d522f475Smrg } 2845d522f475Smrg devindex = 0; 2846d522f475Smrg letter++; 2847d522f475Smrg } 2848d522f475Smrg#endif /* CRAY else */ 2849d522f475Smrg /* 2850d522f475Smrg * We were unable to allocate a pty master! Return an error 2851d522f475Smrg * condition and let our caller terminate cleanly. 2852d522f475Smrg */ 2853d522f475Smrg return 1; 2854d522f475Smrg} 2855d522f475Smrg#endif /* USE_PTY_SEARCH */ 2856d522f475Smrg 2857d522f475Smrg/* 2858d522f475Smrg * The only difference in /etc/termcap between 4014 and 4015 is that 2859d522f475Smrg * the latter has support for switching character sets. We support the 2860d522f475Smrg * 4015 protocol, but ignore the character switches. Therefore, we 2861d522f475Smrg * choose 4014 over 4015. 2862d522f475Smrg * 2863d522f475Smrg * Features of the 4014 over the 4012: larger (19") screen, 12-bit 2864d522f475Smrg * graphics addressing (compatible with 4012 10-bit addressing), 2865d522f475Smrg * special point plot mode, incremental plot mode (not implemented in 2866d522f475Smrg * later Tektronix terminals), and 4 character sizes. 2867d522f475Smrg * All of these are supported by xterm. 2868d522f475Smrg */ 2869d522f475Smrg 2870d522f475Smrg#if OPT_TEK4014 287120d2c4d2Smrgstatic const char *tekterm[] = 2872d522f475Smrg{ 2873d522f475Smrg "tek4014", 2874d522f475Smrg "tek4015", /* 4014 with APL character set support */ 2875d522f475Smrg "tek4012", /* 4010 with lower case */ 2876d522f475Smrg "tek4013", /* 4012 with APL character set support */ 2877d522f475Smrg "tek4010", /* small screen, upper-case only */ 2878d522f475Smrg "dumb", 2879d522f475Smrg 0 2880d522f475Smrg}; 2881d522f475Smrg#endif 2882d522f475Smrg 2883d522f475Smrg/* The VT102 is a VT100 with the Advanced Video Option included standard. 2884d522f475Smrg * It also adds Escape sequences for insert/delete character/line. 2885d522f475Smrg * The VT220 adds 8-bit character sets, selective erase. 2886d522f475Smrg * The VT320 adds a 25th status line, terminal state interrogation. 2887d522f475Smrg * The VT420 has up to 48 lines on the screen. 2888d522f475Smrg */ 2889d522f475Smrg 289020d2c4d2Smrgstatic const char *vtterm[] = 2891d522f475Smrg{ 2892d522f475Smrg#ifdef USE_X11TERM 2893d522f475Smrg "x11term", /* for people who want special term name */ 2894d522f475Smrg#endif 2895d522f475Smrg DFT_TERMTYPE, /* for people who want special term name */ 2896d522f475Smrg "xterm", /* the prefered name, should be fastest */ 2897d522f475Smrg "vt102", 2898d522f475Smrg "vt100", 2899d522f475Smrg "ansi", 2900d522f475Smrg "dumb", 2901d522f475Smrg 0 2902d522f475Smrg}; 2903d522f475Smrg 2904d522f475Smrg/* ARGSUSED */ 29050bd37d32Smrgstatic void 2906d522f475Smrghungtty(int i GCC_UNUSED) 2907d522f475Smrg{ 29080bd37d32Smrg DEBUG_MSG("handle:hungtty\n"); 2909d522f475Smrg siglongjmp(env, 1); 2910d522f475Smrg} 2911d522f475Smrg 2912d522f475Smrg#if OPT_PTY_HANDSHAKE 2913d522f475Smrg#define NO_FDS {-1, -1} 2914d522f475Smrg 2915d522f475Smrgstatic int cp_pipe[2] = NO_FDS; /* this pipe is used for child to parent transfer */ 2916d522f475Smrgstatic int pc_pipe[2] = NO_FDS; /* this pipe is used for parent to child transfer */ 2917d522f475Smrg 2918d522f475Smrgtypedef enum { /* c == child, p == parent */ 2919d522f475Smrg PTY_BAD, /* c->p: can't open pty slave for some reason */ 2920d522f475Smrg PTY_FATALERROR, /* c->p: we had a fatal error with the pty */ 2921d522f475Smrg PTY_GOOD, /* c->p: we have a good pty, let's go on */ 2922d522f475Smrg PTY_NEW, /* p->c: here is a new pty slave, try this */ 2923d522f475Smrg PTY_NOMORE, /* p->c; no more pty's, terminate */ 2924d522f475Smrg UTMP_ADDED, /* c->p: utmp entry has been added */ 2925d522f475Smrg UTMP_TTYSLOT, /* c->p: here is my ttyslot */ 2926d522f475Smrg PTY_EXEC /* p->c: window has been mapped the first time */ 2927d522f475Smrg} status_t; 2928d522f475Smrg 2929d522f475Smrgtypedef struct { 2930d522f475Smrg status_t status; 2931d522f475Smrg int error; 2932d522f475Smrg int fatal_error; 2933d522f475Smrg int tty_slot; 2934d522f475Smrg int rows; 2935d522f475Smrg int cols; 2936d522f475Smrg char buffer[1024]; 2937d522f475Smrg} handshake_t; 2938d522f475Smrg 2939d522f475Smrg#if OPT_TRACE 2940d522f475Smrgstatic void 2941d522f475Smrgtrace_handshake(const char *tag, handshake_t * data) 2942d522f475Smrg{ 2943d522f475Smrg const char *status = "?"; 2944d522f475Smrg switch (data->status) { 2945d522f475Smrg case PTY_BAD: 2946d522f475Smrg status = "PTY_BAD"; 2947d522f475Smrg break; 2948d522f475Smrg case PTY_FATALERROR: 2949d522f475Smrg status = "PTY_FATALERROR"; 2950d522f475Smrg break; 2951d522f475Smrg case PTY_GOOD: 2952d522f475Smrg status = "PTY_GOOD"; 2953d522f475Smrg break; 2954d522f475Smrg case PTY_NEW: 2955d522f475Smrg status = "PTY_NEW"; 2956d522f475Smrg break; 2957d522f475Smrg case PTY_NOMORE: 2958d522f475Smrg status = "PTY_NOMORE"; 2959d522f475Smrg break; 2960d522f475Smrg case UTMP_ADDED: 2961d522f475Smrg status = "UTMP_ADDED"; 2962d522f475Smrg break; 2963d522f475Smrg case UTMP_TTYSLOT: 2964d522f475Smrg status = "UTMP_TTYSLOT"; 2965d522f475Smrg break; 2966d522f475Smrg case PTY_EXEC: 2967d522f475Smrg status = "PTY_EXEC"; 2968d522f475Smrg break; 2969d522f475Smrg } 2970d522f475Smrg TRACE(("handshake %s %s errno=%d, error=%d device \"%s\"\n", 2971d522f475Smrg tag, 2972d522f475Smrg status, 2973d522f475Smrg data->error, 2974d522f475Smrg data->fatal_error, 2975d522f475Smrg data->buffer)); 2976d522f475Smrg} 2977d522f475Smrg#define TRACE_HANDSHAKE(tag, data) trace_handshake(tag, data) 2978d522f475Smrg#else 2979d522f475Smrg#define TRACE_HANDSHAKE(tag, data) /* nothing */ 2980d522f475Smrg#endif 2981d522f475Smrg 2982d522f475Smrg/* HsSysError() 2983d522f475Smrg * 2984d522f475Smrg * This routine does the equivalent of a SysError but it handshakes 2985d522f475Smrg * over the errno and error exit to the master process so that it can 2986d522f475Smrg * display our error message and exit with our exit code so that the 2987d522f475Smrg * user can see it. 2988d522f475Smrg */ 2989d522f475Smrg 2990d522f475Smrgstatic void 2991d522f475SmrgHsSysError(int error) 2992d522f475Smrg{ 2993d522f475Smrg handshake_t handshake; 2994d522f475Smrg 2995d522f475Smrg memset(&handshake, 0, sizeof(handshake)); 2996d522f475Smrg handshake.status = PTY_FATALERROR; 2997d522f475Smrg handshake.error = errno; 2998d522f475Smrg handshake.fatal_error = error; 29990bd37d32Smrg strncpy(handshake.buffer, ttydev, sizeof(handshake.buffer)); 3000d522f475Smrg 3001d522f475Smrg if (resource.ptyHandshake && (cp_pipe[1] >= 0)) { 3002d522f475Smrg TRACE(("HsSysError errno=%d, error=%d device \"%s\"\n", 3003d522f475Smrg handshake.error, 3004d522f475Smrg handshake.fatal_error, 3005d522f475Smrg handshake.buffer)); 3006d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 300720d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], 300820d2c4d2Smrg (const char *) &handshake, 300920d2c4d2Smrg sizeof(handshake))); 3010d522f475Smrg } else { 30110bd37d32Smrg xtermWarning("fatal pty error errno=%d, error=%d device \"%s\"\n", 30120bd37d32Smrg handshake.error, 30130bd37d32Smrg handshake.fatal_error, 30140bd37d32Smrg handshake.buffer); 3015d522f475Smrg fprintf(stderr, "%s\n", SysErrorMsg(handshake.error)); 3016d522f475Smrg fprintf(stderr, "Reason: %s\n", SysReasonMsg(handshake.fatal_error)); 3017d522f475Smrg } 3018d522f475Smrg exit(error); 3019d522f475Smrg} 3020d522f475Smrg 3021d522f475Smrgvoid 3022d522f475Smrgfirst_map_occurred(void) 3023d522f475Smrg{ 3024d522f475Smrg if (resource.wait_for_map) { 3025d522f475Smrg handshake_t handshake; 3026d522f475Smrg TScreen *screen = TScreenOf(term); 3027d522f475Smrg 3028d522f475Smrg memset(&handshake, 0, sizeof(handshake)); 3029d522f475Smrg handshake.status = PTY_EXEC; 3030d522f475Smrg handshake.rows = screen->max_row; 3031d522f475Smrg handshake.cols = screen->max_col; 3032d522f475Smrg 3033d522f475Smrg if (pc_pipe[1] >= 0) { 3034d522f475Smrg TRACE(("first_map_occurred: %dx%d\n", handshake.rows, handshake.cols)); 3035d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 303620d2c4d2Smrg IGNORE_RC(write(pc_pipe[1], 303720d2c4d2Smrg (const char *) &handshake, 303820d2c4d2Smrg sizeof(handshake))); 3039d522f475Smrg close(cp_pipe[0]); 3040d522f475Smrg close(pc_pipe[1]); 3041d522f475Smrg } 3042d522f475Smrg resource.wait_for_map = False; 3043d522f475Smrg } 3044d522f475Smrg} 3045d522f475Smrg#else 3046d522f475Smrg/* 3047d522f475Smrg * temporary hack to get xterm working on att ptys 3048d522f475Smrg */ 3049d522f475Smrgstatic void 3050d522f475SmrgHsSysError(int error) 3051d522f475Smrg{ 30520bd37d32Smrg xtermWarning("fatal pty error %d (errno=%d) on tty %s\n", 30530bd37d32Smrg error, errno, ttydev); 3054d522f475Smrg exit(error); 3055d522f475Smrg} 3056d522f475Smrg#endif /* OPT_PTY_HANDSHAKE else !OPT_PTY_HANDSHAKE */ 3057d522f475Smrg 3058d522f475Smrg#ifndef VMS 3059d522f475Smrgstatic void 3060e0a2b6dfSmrgset_owner(char *device, unsigned uid, unsigned gid, unsigned mode) 3061d522f475Smrg{ 3062d522f475Smrg int why; 3063d522f475Smrg 3064d522f475Smrg TRACE_IDS; 306520d2c4d2Smrg TRACE(("set_owner(%s, uid=%d, gid=%d, mode=%#o\n", 30660bd37d32Smrg device, (int) uid, (int) gid, (unsigned) mode)); 3067d522f475Smrg 3068d522f475Smrg if (chown(device, uid, gid) < 0) { 3069d522f475Smrg why = errno; 3070d522f475Smrg if (why != ENOENT 3071d522f475Smrg && save_ruid == 0) { 30720bd37d32Smrg xtermPerror("Cannot chown %s to %ld,%ld", 30730bd37d32Smrg device, (long) uid, (long) gid); 3074d522f475Smrg } 3075d522f475Smrg TRACE(("...chown failed: %s\n", strerror(why))); 3076e39b573cSmrg } else if (chmod(device, mode) < 0) { 3077d522f475Smrg why = errno; 3078d522f475Smrg if (why != ENOENT) { 3079d522f475Smrg struct stat sb; 3080d522f475Smrg if (stat(device, &sb) < 0) { 30810bd37d32Smrg xtermPerror("Cannot chmod %s to %03o", 30820bd37d32Smrg device, (unsigned) mode); 3083d522f475Smrg } else if (mode != (sb.st_mode & 0777U)) { 30840bd37d32Smrg xtermPerror("Cannot chmod %s to %03lo currently %03lo", 30850bd37d32Smrg device, 30860bd37d32Smrg (unsigned long) mode, 30870bd37d32Smrg (unsigned long) (sb.st_mode & 0777U)); 3088d522f475Smrg TRACE(("...stat uid=%d, gid=%d, mode=%#o\n", 30890bd37d32Smrg (int) sb.st_uid, (int) sb.st_gid, (unsigned) sb.st_mode)); 3090d522f475Smrg } 3091d522f475Smrg } 3092d522f475Smrg TRACE(("...chmod failed: %s\n", strerror(why))); 3093d522f475Smrg } 3094d522f475Smrg} 3095d522f475Smrg 3096894e0ac8Smrg/* 3097894e0ac8Smrg * utmp data may not be null-terminated; even if it is, there may be garbage 3098894e0ac8Smrg * after the null. This fills the unused part of the result with nulls. 3099894e0ac8Smrg */ 3100894e0ac8Smrgstatic void 3101894e0ac8Smrgcopy_filled(char *target, const char *source, size_t len) 3102894e0ac8Smrg{ 3103894e0ac8Smrg size_t used = 0; 3104894e0ac8Smrg while (used < len) { 3105894e0ac8Smrg if ((target[used] = source[used]) == 0) 3106894e0ac8Smrg break; 3107894e0ac8Smrg ++used; 3108894e0ac8Smrg } 3109894e0ac8Smrg while (used < len) { 3110894e0ac8Smrg target[used++] = '\0'; 3111894e0ac8Smrg } 3112894e0ac8Smrg} 3113894e0ac8Smrg 3114d522f475Smrg#if defined(HAVE_UTMP) && defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 3115d522f475Smrg/* 3116d522f475Smrg * getutid() only looks at ut_type and ut_id. 3117d522f475Smrg * But we'll also check ut_line in find_utmp(). 3118d522f475Smrg */ 3119d522f475Smrgstatic void 3120d522f475Smrginit_utmp(int type, struct UTMP_STR *tofind) 3121d522f475Smrg{ 3122d522f475Smrg memset(tofind, 0, sizeof(*tofind)); 3123d522f475Smrg tofind->ut_type = type; 3124894e0ac8Smrg copy_filled(tofind->ut_id, my_utmp_id(ttydev), sizeof(tofind->ut_id)); 3125894e0ac8Smrg copy_filled(tofind->ut_line, my_pty_name(ttydev), sizeof(tofind->ut_line)); 3126d522f475Smrg} 3127d522f475Smrg 3128d522f475Smrg/* 3129d522f475Smrg * We could use getutline() if we didn't support old systems. 3130d522f475Smrg */ 3131d522f475Smrgstatic struct UTMP_STR * 3132d522f475Smrgfind_utmp(struct UTMP_STR *tofind) 3133d522f475Smrg{ 3134d522f475Smrg struct UTMP_STR *result; 31350bd37d32Smrg struct UTMP_STR limited; 3136d522f475Smrg struct UTMP_STR working; 3137d522f475Smrg 3138d522f475Smrg for (;;) { 3139d522f475Smrg memset(&working, 0, sizeof(working)); 3140d522f475Smrg working.ut_type = tofind->ut_type; 3141894e0ac8Smrg copy_filled(working.ut_id, tofind->ut_id, sizeof(tofind->ut_id)); 3142d522f475Smrg#if defined(__digital__) && defined(__unix__) && (defined(OSMAJORVERSION) && OSMAJORVERSION < 5) 3143d522f475Smrg working.ut_type = 0; 3144d522f475Smrg#endif 3145d522f475Smrg if ((result = call_getutid(&working)) == 0) 3146d522f475Smrg break; 3147894e0ac8Smrg copy_filled(limited.ut_line, result->ut_line, sizeof(result->ut_line)); 31480bd37d32Smrg if (!memcmp(limited.ut_line, tofind->ut_line, sizeof(limited.ut_line))) 3149d522f475Smrg break; 3150d522f475Smrg /* 3151d522f475Smrg * Solaris, IRIX64 and HPUX manpages say to fill the static area 3152d522f475Smrg * pointed to by the return-value to zeros if searching for multiple 3153d522f475Smrg * occurrences. Otherwise it will continue to return the same value. 3154d522f475Smrg */ 3155d522f475Smrg memset(result, 0, sizeof(*result)); 3156d522f475Smrg } 3157d522f475Smrg return result; 3158d522f475Smrg} 3159d522f475Smrg#endif /* HAVE_UTMP... */ 3160d522f475Smrg 3161d522f475Smrg#define close_fd(fd) close(fd), fd = -1 3162d522f475Smrg 316320d2c4d2Smrg#if defined(TIOCNOTTY) && (!defined(__GLIBC__) || (__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))) 316420d2c4d2Smrg#define USE_NO_DEV_TTY 1 316520d2c4d2Smrg#else 316620d2c4d2Smrg#define USE_NO_DEV_TTY 0 316720d2c4d2Smrg#endif 316820d2c4d2Smrg 3169e0a2b6dfSmrgstatic int 3170e0a2b6dfSmrgsame_leaf(char *a, char *b) 3171e0a2b6dfSmrg{ 3172e0a2b6dfSmrg char *p = x_basename(a); 3173e0a2b6dfSmrg char *q = x_basename(b); 3174e0a2b6dfSmrg return !strcmp(p, q); 3175e0a2b6dfSmrg} 3176e0a2b6dfSmrg 3177e0a2b6dfSmrg/* 3178e0a2b6dfSmrg * "good enough" (inode wouldn't port to Cygwin) 3179e0a2b6dfSmrg */ 3180e0a2b6dfSmrgstatic int 3181e0a2b6dfSmrgsame_file(const char *a, const char *b) 3182e0a2b6dfSmrg{ 3183e0a2b6dfSmrg struct stat asb; 3184e0a2b6dfSmrg struct stat bsb; 3185e0a2b6dfSmrg int result = 0; 3186e0a2b6dfSmrg 3187e0a2b6dfSmrg if ((stat(a, &asb) == 0) 3188e0a2b6dfSmrg && (stat(b, &bsb) == 0) 3189e0a2b6dfSmrg && ((asb.st_mode & S_IFMT) == S_IFREG) 3190e0a2b6dfSmrg && ((bsb.st_mode & S_IFMT) == S_IFREG) 3191e0a2b6dfSmrg && (asb.st_mtime == bsb.st_mtime) 3192e0a2b6dfSmrg && (asb.st_size == bsb.st_size)) { 3193e0a2b6dfSmrg result = 1; 3194e0a2b6dfSmrg } 3195e0a2b6dfSmrg return result; 3196e0a2b6dfSmrg} 3197e0a2b6dfSmrg 3198e0a2b6dfSmrg/* 3199e0a2b6dfSmrg * Only set $SHELL for paths found in the standard location. 3200e0a2b6dfSmrg */ 3201e0a2b6dfSmrgstatic Boolean 3202e0a2b6dfSmrgvalidShell(const char *pathname) 3203e0a2b6dfSmrg{ 3204e0a2b6dfSmrg Boolean result = False; 3205e0a2b6dfSmrg const char *ok_shells = "/etc/shells"; 3206e0a2b6dfSmrg char *blob; 3207e0a2b6dfSmrg struct stat sb; 3208e0a2b6dfSmrg size_t rc; 3209e0a2b6dfSmrg FILE *fp; 3210e0a2b6dfSmrg 3211e0a2b6dfSmrg if (validProgram(pathname) 3212e0a2b6dfSmrg && stat(ok_shells, &sb) == 0 3213e0a2b6dfSmrg && (sb.st_mode & S_IFMT) == S_IFREG 3214e0a2b6dfSmrg && (sb.st_size != 0) 3215e0a2b6dfSmrg && (blob = calloc((size_t) sb.st_size + 2, sizeof(char))) != 0) { 3216e0a2b6dfSmrg if ((fp = fopen(ok_shells, "r")) != 0) { 3217e0a2b6dfSmrg rc = fread(blob, sizeof(char), (size_t) sb.st_size, fp); 3218e0a2b6dfSmrg if (rc == (size_t) sb.st_size) { 3219e0a2b6dfSmrg char *p = blob; 3220e0a2b6dfSmrg char *q, *r; 3221e0a2b6dfSmrg blob[rc] = '\0'; 3222e0a2b6dfSmrg while (!result && (q = strtok(p, "\n")) != 0) { 3223e0a2b6dfSmrg if ((r = x_strtrim(q)) != 0) { 3224e0a2b6dfSmrg TRACE(("...test \"%s\"\n", q)); 3225e0a2b6dfSmrg if (!strcmp(q, pathname)) { 3226e0a2b6dfSmrg result = True; 3227e0a2b6dfSmrg } else if (same_leaf(q, (char *) pathname) && 3228e0a2b6dfSmrg same_file(q, pathname)) { 3229e0a2b6dfSmrg result = True; 3230e0a2b6dfSmrg } 3231e0a2b6dfSmrg free(r); 3232e0a2b6dfSmrg } 3233e0a2b6dfSmrg p = 0; 3234e0a2b6dfSmrg } 3235e0a2b6dfSmrg } 3236e0a2b6dfSmrg fclose(fp); 3237e0a2b6dfSmrg } 3238e0a2b6dfSmrg free(blob); 3239e0a2b6dfSmrg } 3240e0a2b6dfSmrg TRACE(("validShell %s ->%d\n", NonNull(pathname), result)); 3241e0a2b6dfSmrg return result; 3242e0a2b6dfSmrg} 3243e0a2b6dfSmrg 3244e0a2b6dfSmrgstatic char * 3245e0a2b6dfSmrgresetShell(char *oldPath) 3246e0a2b6dfSmrg{ 3247e0a2b6dfSmrg char *newPath = x_strdup("/bin/sh"); 3248e0a2b6dfSmrg char *envPath = getenv("SHELL"); 3249e0a2b6dfSmrg if (oldPath != 0) 3250e0a2b6dfSmrg free(oldPath); 3251e0a2b6dfSmrg if (!IsEmpty(envPath)) 3252e0a2b6dfSmrg xtermSetenv("SHELL", newPath); 3253e0a2b6dfSmrg return newPath; 3254e0a2b6dfSmrg} 3255e0a2b6dfSmrg 3256d522f475Smrg/* 3257d522f475Smrg * Inits pty and tty and forks a login process. 3258d522f475Smrg * Does not close fd Xsocket. 3259d522f475Smrg * If slave, the pty named in passedPty is already open for use 3260d522f475Smrg */ 3261d522f475Smrgstatic int 3262d522f475SmrgspawnXTerm(XtermWidget xw) 3263d522f475Smrg{ 3264d522f475Smrg TScreen *screen = TScreenOf(xw); 3265d522f475Smrg Cardinal nn; 3266d522f475Smrg#if OPT_PTY_HANDSHAKE 3267d522f475Smrg Bool got_handshake_size = False; 3268d522f475Smrg handshake_t handshake; 3269d522f475Smrg int done; 3270d522f475Smrg#endif 3271d522f475Smrg#if OPT_INITIAL_ERASE 3272d522f475Smrg int initial_erase = VAL_INITIAL_ERASE; 3273d522f475Smrg Bool setInitialErase; 3274d522f475Smrg#endif 3275d522f475Smrg int rc = 0; 3276d522f475Smrg int ttyfd = -1; 3277d522f475Smrg Bool ok_termcap; 3278d522f475Smrg char *newtc; 3279d522f475Smrg 3280d522f475Smrg#ifdef TERMIO_STRUCT 3281d522f475Smrg TERMIO_STRUCT tio; 3282d522f475Smrg#ifdef __MVS__ 3283d522f475Smrg TERMIO_STRUCT gio; 3284d522f475Smrg#endif /* __MVS__ */ 3285d522f475Smrg#ifdef TIOCLSET 3286d522f475Smrg unsigned lmode; 3287d522f475Smrg#endif /* TIOCLSET */ 3288d522f475Smrg#ifdef HAS_LTCHARS 3289d522f475Smrg struct ltchars ltc; 3290d522f475Smrg#endif /* HAS_LTCHARS */ 3291d522f475Smrg#else /* !TERMIO_STRUCT */ 3292d522f475Smrg int ldisc = 0; 3293d522f475Smrg int discipline; 3294d522f475Smrg unsigned lmode; 3295d522f475Smrg struct tchars tc; 3296d522f475Smrg struct ltchars ltc; 3297d522f475Smrg struct sgttyb sg; 3298d522f475Smrg#ifdef sony 3299d522f475Smrg int jmode; 3300d522f475Smrg struct jtchars jtc; 3301d522f475Smrg#endif /* sony */ 3302d522f475Smrg#endif /* TERMIO_STRUCT */ 3303d522f475Smrg 33040bd37d32Smrg char *shell_path = 0; 33050bd37d32Smrg char *shname, *shname_minus; 330620d2c4d2Smrg int i; 330720d2c4d2Smrg#if USE_NO_DEV_TTY 330820d2c4d2Smrg int no_dev_tty = False; 330920d2c4d2Smrg#endif 331020d2c4d2Smrg const char **envnew; /* new environment */ 3311d522f475Smrg char buf[64]; 3312d522f475Smrg char *TermName = NULL; 3313d522f475Smrg#ifdef TTYSIZE_STRUCT 3314d522f475Smrg TTYSIZE_STRUCT ts; 3315d522f475Smrg#endif 33160bd37d32Smrg struct passwd pw; 3317d522f475Smrg char *login_name = NULL; 3318d522f475Smrg#ifndef USE_UTEMPTER 3319d522f475Smrg#ifdef HAVE_UTMP 3320d522f475Smrg struct UTMP_STR utmp; 3321d522f475Smrg#ifdef USE_SYSV_UTMP 3322d522f475Smrg struct UTMP_STR *utret = NULL; 3323d522f475Smrg#endif 3324d522f475Smrg#ifdef USE_LASTLOG 3325d522f475Smrg struct lastlog lastlog; 3326d522f475Smrg#endif 3327d522f475Smrg#ifdef USE_LASTLOGX 3328d522f475Smrg struct lastlogx lastlogx; 3329d522f475Smrg#endif /* USE_LASTLOG */ 3330d522f475Smrg#endif /* HAVE_UTMP */ 3331d522f475Smrg#endif /* !USE_UTEMPTER */ 3332d522f475Smrg 3333e39b573cSmrg#if OPT_TRACE 3334e39b573cSmrg unsigned long xterm_parent = (unsigned long) getpid(); 3335e39b573cSmrg#endif 3336e39b573cSmrg 3337d522f475Smrg /* Noisy compilers (suppress some unused-variable warnings) */ 3338d522f475Smrg (void) rc; 3339d522f475Smrg#if defined(HAVE_UTMP) && defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 3340d522f475Smrg (void) utret; 3341d522f475Smrg#endif 3342d522f475Smrg 3343d522f475Smrg screen->uid = save_ruid; 3344d522f475Smrg screen->gid = save_rgid; 3345d522f475Smrg 3346d522f475Smrg#ifdef SIGTTOU 3347d522f475Smrg /* so that TIOCSWINSZ || TIOCSIZE doesn't block */ 3348d522f475Smrg signal(SIGTTOU, SIG_IGN); 3349d522f475Smrg#endif 3350d522f475Smrg 3351d522f475Smrg#if OPT_PTY_HANDSHAKE 3352d522f475Smrg memset(&handshake, 0, sizeof(handshake)); 3353d522f475Smrg#endif 3354d522f475Smrg 3355d522f475Smrg if (am_slave >= 0) { 3356d522f475Smrg screen->respond = am_slave; 3357d522f475Smrg set_pty_id(ttydev, passedPty); 3358d522f475Smrg#ifdef USE_PTY_DEVICE 3359d522f475Smrg set_pty_id(ptydev, passedPty); 3360d522f475Smrg#endif 3361d522f475Smrg if (xtermResetIds(screen) < 0) 3362d522f475Smrg exit(1); 3363d522f475Smrg } else { 3364d522f475Smrg Bool tty_got_hung; 3365d522f475Smrg 3366d522f475Smrg /* 3367d522f475Smrg * Sometimes /dev/tty hangs on open (as in the case of a pty 3368d522f475Smrg * that has gone away). Simply make up some reasonable 3369d522f475Smrg * defaults. 3370d522f475Smrg */ 3371d522f475Smrg 3372d522f475Smrg signal(SIGALRM, hungtty); 3373d522f475Smrg alarm(2); /* alarm(1) might return too soon */ 3374d522f475Smrg if (!sigsetjmp(env, 1)) { 3375d522f475Smrg ttyfd = open("/dev/tty", O_RDWR); 3376d522f475Smrg alarm(0); 3377d522f475Smrg tty_got_hung = False; 3378d522f475Smrg } else { 3379d522f475Smrg tty_got_hung = True; 3380d522f475Smrg ttyfd = -1; 3381d522f475Smrg errno = ENXIO; 3382d522f475Smrg } 33830bd37d32Smrg memset(&pw, 0, sizeof(pw)); 3384d522f475Smrg#if OPT_PTY_HANDSHAKE 3385d522f475Smrg got_handshake_size = False; 3386d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 3387d522f475Smrg#if OPT_INITIAL_ERASE 3388d522f475Smrg initial_erase = VAL_INITIAL_ERASE; 3389d522f475Smrg#endif 3390d522f475Smrg signal(SIGALRM, SIG_DFL); 3391d522f475Smrg 3392d522f475Smrg /* 3393d522f475Smrg * Check results and ignore current control terminal if 3394d522f475Smrg * necessary. ENXIO is what is normally returned if there is 3395d522f475Smrg * no controlling terminal, but some systems (e.g. SunOS 4.0) 3396d522f475Smrg * seem to return EIO. Solaris 2.3 is said to return EINVAL. 33970bd37d32Smrg * Cygwin returns ENOENT. FreeBSD can return ENOENT, especially 33980bd37d32Smrg * if xterm is run within a jail. 3399d522f475Smrg */ 340020d2c4d2Smrg#if USE_NO_DEV_TTY 3401d522f475Smrg no_dev_tty = False; 340220d2c4d2Smrg#endif 3403d522f475Smrg if (ttyfd < 0) { 3404d522f475Smrg if (tty_got_hung || errno == ENXIO || errno == EIO || 34050bd37d32Smrg errno == ENOENT || 3406d522f475Smrg#ifdef ENODEV 3407d522f475Smrg errno == ENODEV || 3408d522f475Smrg#endif 3409d522f475Smrg errno == EINVAL || errno == ENOTTY || errno == EACCES) { 341020d2c4d2Smrg#if USE_NO_DEV_TTY 3411d522f475Smrg no_dev_tty = True; 341220d2c4d2Smrg#endif 3413d522f475Smrg#ifdef HAS_LTCHARS 3414d522f475Smrg ltc = d_ltc; 3415d522f475Smrg#endif /* HAS_LTCHARS */ 3416d522f475Smrg#ifdef TIOCLSET 3417d522f475Smrg lmode = d_lmode; 3418d522f475Smrg#endif /* TIOCLSET */ 3419d522f475Smrg#ifdef TERMIO_STRUCT 3420d522f475Smrg tio = d_tio; 3421d522f475Smrg#else /* !TERMIO_STRUCT */ 3422d522f475Smrg sg = d_sg; 3423d522f475Smrg tc = d_tc; 3424d522f475Smrg discipline = d_disipline; 3425d522f475Smrg#ifdef sony 3426d522f475Smrg jmode = d_jmode; 3427d522f475Smrg jtc = d_jtc; 3428d522f475Smrg#endif /* sony */ 3429d522f475Smrg#endif /* TERMIO_STRUCT */ 3430d522f475Smrg } else { 3431d522f475Smrg SysError(ERROR_OPDEVTTY); 3432d522f475Smrg } 3433d522f475Smrg } else { 3434d522f475Smrg 3435d522f475Smrg /* Get a copy of the current terminal's state, 3436d522f475Smrg * if we can. Some systems (e.g., SVR4 and MacII) 3437d522f475Smrg * may not have a controlling terminal at this point 3438d522f475Smrg * if started directly from xdm or xinit, 3439d522f475Smrg * in which case we just use the defaults as above. 3440d522f475Smrg */ 3441d522f475Smrg#ifdef HAS_LTCHARS 3442d522f475Smrg if (ioctl(ttyfd, TIOCGLTC, <c) == -1) 3443d522f475Smrg ltc = d_ltc; 3444d522f475Smrg#endif /* HAS_LTCHARS */ 3445d522f475Smrg#ifdef TIOCLSET 3446d522f475Smrg if (ioctl(ttyfd, TIOCLGET, &lmode) == -1) 3447d522f475Smrg lmode = d_lmode; 3448d522f475Smrg#endif /* TIOCLSET */ 3449d522f475Smrg#ifdef TERMIO_STRUCT 345020d2c4d2Smrg rc = ttyGetAttr(ttyfd, &tio); 345120d2c4d2Smrg if (rc == -1) 3452d522f475Smrg tio = d_tio; 3453d522f475Smrg#else /* !TERMIO_STRUCT */ 345420d2c4d2Smrg rc = ioctl(ttyfd, TIOCGETP, (char *) &sg); 345520d2c4d2Smrg if (rc == -1) 3456d522f475Smrg sg = d_sg; 3457d522f475Smrg if (ioctl(ttyfd, TIOCGETC, (char *) &tc) == -1) 3458d522f475Smrg tc = d_tc; 3459d522f475Smrg if (ioctl(ttyfd, TIOCGETD, (char *) &discipline) == -1) 3460d522f475Smrg discipline = d_disipline; 3461d522f475Smrg#ifdef sony 3462d522f475Smrg if (ioctl(ttyfd, TIOCKGET, (char *) &jmode) == -1) 3463d522f475Smrg jmode = d_jmode; 3464d522f475Smrg if (ioctl(ttyfd, TIOCKGETC, (char *) &jtc) == -1) 3465d522f475Smrg jtc = d_jtc; 3466d522f475Smrg#endif /* sony */ 3467d522f475Smrg#endif /* TERMIO_STRUCT */ 3468d522f475Smrg 3469d522f475Smrg /* 3470d522f475Smrg * If ptyInitialErase is set, we want to get the pty's 3471d522f475Smrg * erase value. Just in case that will fail, first get 3472d522f475Smrg * the value from /dev/tty, so we will have something 3473d522f475Smrg * at least. 3474d522f475Smrg */ 3475d522f475Smrg#if OPT_INITIAL_ERASE 3476d522f475Smrg if (resource.ptyInitialErase) { 3477d522f475Smrg#ifdef TERMIO_STRUCT 3478d522f475Smrg initial_erase = tio.c_cc[VERASE]; 3479d522f475Smrg#else /* !TERMIO_STRUCT */ 3480d522f475Smrg initial_erase = sg.sg_erase; 3481d522f475Smrg#endif /* TERMIO_STRUCT */ 3482d522f475Smrg TRACE(("%s initial_erase:%d (from /dev/tty)\n", 3483d522f475Smrg rc == 0 ? "OK" : "FAIL", 3484d522f475Smrg initial_erase)); 3485d522f475Smrg } 3486d522f475Smrg#endif 3487d522f475Smrg#ifdef __MVS__ 3488d522f475Smrg if (ttyGetAttr(ttyfd, &gio) == 0) { 3489d522f475Smrg gio.c_cflag &= ~(HUPCL | PARENB); 3490d522f475Smrg ttySetAttr(ttyfd, &gio); 3491d522f475Smrg } 3492d522f475Smrg#endif /* __MVS__ */ 3493d522f475Smrg 3494d522f475Smrg close_fd(ttyfd); 3495d522f475Smrg } 3496d522f475Smrg 3497d522f475Smrg if (get_pty(&screen->respond, XDisplayString(screen->display))) { 3498d522f475Smrg SysError(ERROR_PTYS); 3499d522f475Smrg } 35000bd37d32Smrg TRACE_TTYSIZE(screen->respond, "after get_pty"); 3501d522f475Smrg#if OPT_INITIAL_ERASE 3502d522f475Smrg if (resource.ptyInitialErase) { 3503d522f475Smrg#ifdef TERMIO_STRUCT 3504d522f475Smrg TERMIO_STRUCT my_tio; 350520d2c4d2Smrg rc = ttyGetAttr(screen->respond, &my_tio); 350620d2c4d2Smrg if (rc == 0) 3507d522f475Smrg initial_erase = my_tio.c_cc[VERASE]; 3508d522f475Smrg#else /* !TERMIO_STRUCT */ 3509d522f475Smrg struct sgttyb my_sg; 351020d2c4d2Smrg rc = ioctl(screen->respond, TIOCGETP, (char *) &my_sg); 351120d2c4d2Smrg if (rc == 0) 3512d522f475Smrg initial_erase = my_sg.sg_erase; 3513d522f475Smrg#endif /* TERMIO_STRUCT */ 3514d522f475Smrg TRACE(("%s initial_erase:%d (from pty)\n", 3515d522f475Smrg (rc == 0) ? "OK" : "FAIL", 3516d522f475Smrg initial_erase)); 3517d522f475Smrg } 3518d522f475Smrg#endif /* OPT_INITIAL_ERASE */ 3519d522f475Smrg } 3520d522f475Smrg 3521d522f475Smrg /* avoid double MapWindow requests */ 3522d522f475Smrg XtSetMappedWhenManaged(SHELL_OF(CURRENT_EMU()), False); 3523d522f475Smrg 3524d522f475Smrg wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", 3525d522f475Smrg False); 3526d522f475Smrg 3527d522f475Smrg if (!TEK4014_ACTIVE(xw)) 3528956cc18dSsnj VTInit(xw); /* realize now so know window size for tty driver */ 3529d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 3530d522f475Smrg if (Console) { 3531d522f475Smrg /* 3532d522f475Smrg * Inform any running xconsole program 3533d522f475Smrg * that we are going to steal the console. 3534d522f475Smrg */ 3535d522f475Smrg XmuGetHostname(mit_console_name + MIT_CONSOLE_LEN, 255); 3536d522f475Smrg mit_console = XInternAtom(screen->display, mit_console_name, False); 3537d522f475Smrg /* the user told us to be the console, so we can use CurrentTime */ 3538d522f475Smrg XtOwnSelection(SHELL_OF(CURRENT_EMU()), 3539d522f475Smrg mit_console, CurrentTime, 3540d522f475Smrg ConvertConsoleSelection, NULL, NULL); 3541d522f475Smrg } 3542d522f475Smrg#endif 3543d522f475Smrg#if OPT_TEK4014 3544d522f475Smrg if (TEK4014_ACTIVE(xw)) { 3545d522f475Smrg envnew = tekterm; 3546d522f475Smrg } else 3547d522f475Smrg#endif 3548d522f475Smrg { 3549d522f475Smrg envnew = vtterm; 3550d522f475Smrg } 3551d522f475Smrg 3552d522f475Smrg /* 3553d522f475Smrg * This used to exit if no termcap entry was found for the specified 3554d522f475Smrg * terminal name. That's a little unfriendly, so instead we'll allow 3555d522f475Smrg * the program to proceed (but not to set $TERMCAP) if the termcap 3556d522f475Smrg * entry is not found. 3557d522f475Smrg */ 3558d522f475Smrg ok_termcap = True; 355920d2c4d2Smrg if (!get_termcap(xw, TermName = resource.term_name)) { 356020d2c4d2Smrg const char *last = NULL; 356120d2c4d2Smrg char *next; 356220d2c4d2Smrg 356320d2c4d2Smrg TermName = x_strdup(*envnew); 3564d522f475Smrg ok_termcap = False; 3565d522f475Smrg while (*envnew != NULL) { 356620d2c4d2Smrg if (last == NULL || strcmp(last, *envnew)) { 356720d2c4d2Smrg next = x_strdup(*envnew); 356820d2c4d2Smrg if (get_termcap(xw, next)) { 356920d2c4d2Smrg free(TermName); 357020d2c4d2Smrg TermName = next; 35710bd37d32Smrg ok_termcap = True + 1; 357220d2c4d2Smrg break; 357320d2c4d2Smrg } else { 357420d2c4d2Smrg free(next); 357520d2c4d2Smrg } 3576d522f475Smrg } 3577d522f475Smrg last = *envnew; 3578d522f475Smrg envnew++; 3579d522f475Smrg } 3580d522f475Smrg } 3581d522f475Smrg if (ok_termcap) { 3582a1f3da82Smrg resource.term_name = TermName; 358320d2c4d2Smrg resize_termcap(xw); 3584d522f475Smrg } 3585d522f475Smrg 3586d522f475Smrg /* 3587d522f475Smrg * Check if ptyInitialErase is not set. If so, we rely on the termcap 3588d522f475Smrg * (or terminfo) to tell us what the erase mode should be set to. 3589d522f475Smrg */ 3590d522f475Smrg#if OPT_INITIAL_ERASE 3591d522f475Smrg TRACE(("resource ptyInitialErase is %sset\n", 3592d522f475Smrg resource.ptyInitialErase ? "" : "not ")); 3593d522f475Smrg setInitialErase = False; 3594d522f475Smrg if (override_tty_modes && ttymodelist[XTTYMODE_erase].set) { 3595d522f475Smrg initial_erase = ttymodelist[XTTYMODE_erase].value; 3596d522f475Smrg setInitialErase = True; 3597d522f475Smrg } else if (resource.ptyInitialErase) { 3598a1f3da82Smrg /* EMPTY */ ; 3599d522f475Smrg } else if (ok_termcap) { 360020d2c4d2Smrg char *s = get_tcap_erase(xw); 3601d522f475Smrg TRACE(("...extracting initial_erase value from termcap\n")); 3602d522f475Smrg if (s != 0) { 360320d2c4d2Smrg char *save = s; 3604d522f475Smrg initial_erase = decode_keyvalue(&s, True); 3605d522f475Smrg setInitialErase = True; 360620d2c4d2Smrg free(save); 3607d522f475Smrg } 3608d522f475Smrg } 3609d522f475Smrg TRACE(("...initial_erase:%d\n", initial_erase)); 3610d522f475Smrg 3611d522f475Smrg TRACE(("resource backarrowKeyIsErase is %sset\n", 3612d522f475Smrg resource.backarrow_is_erase ? "" : "not ")); 3613d522f475Smrg if (resource.backarrow_is_erase) { /* see input.c */ 3614d522f475Smrg if (initial_erase == ANSI_DEL) { 361520d2c4d2Smrg UIntClr(xw->keyboard.flags, MODE_DECBKM); 3616d522f475Smrg } else { 3617d522f475Smrg xw->keyboard.flags |= MODE_DECBKM; 3618d522f475Smrg xw->keyboard.reset_DECBKM = 1; 3619d522f475Smrg } 3620d522f475Smrg TRACE(("...sets DECBKM %s\n", 3621d522f475Smrg (xw->keyboard.flags & MODE_DECBKM) ? "on" : "off")); 3622d522f475Smrg } else { 3623d522f475Smrg xw->keyboard.reset_DECBKM = 2; 3624d522f475Smrg } 3625d522f475Smrg#endif /* OPT_INITIAL_ERASE */ 3626d522f475Smrg 3627d522f475Smrg#ifdef TTYSIZE_STRUCT 3628d522f475Smrg /* tell tty how big window is */ 3629d522f475Smrg#if OPT_TEK4014 3630d522f475Smrg if (TEK4014_ACTIVE(xw)) { 3631d522f475Smrg TTYSIZE_ROWS(ts) = 38; 3632d522f475Smrg TTYSIZE_COLS(ts) = 81; 3633d522f475Smrg#if defined(USE_STRUCT_WINSIZE) 363420d2c4d2Smrg ts.ws_xpixel = TFullWidth(TekScreenOf(tekWidget)); 363520d2c4d2Smrg ts.ws_ypixel = TFullHeight(TekScreenOf(tekWidget)); 3636d522f475Smrg#endif 3637d522f475Smrg } else 3638d522f475Smrg#endif 3639d522f475Smrg { 364020d2c4d2Smrg TTYSIZE_ROWS(ts) = (ttySize_t) MaxRows(screen); 364120d2c4d2Smrg TTYSIZE_COLS(ts) = (ttySize_t) MaxCols(screen); 3642d522f475Smrg#if defined(USE_STRUCT_WINSIZE) 364320d2c4d2Smrg ts.ws_xpixel = (ttySize_t) FullWidth(screen); 364420d2c4d2Smrg ts.ws_ypixel = (ttySize_t) FullHeight(screen); 3645d522f475Smrg#endif 3646d522f475Smrg } 364720d2c4d2Smrg TRACE_RC(i, SET_TTYSIZE(screen->respond, ts)); 3648d522f475Smrg TRACE(("spawn SET_TTYSIZE %dx%d return %d\n", 3649d522f475Smrg TTYSIZE_ROWS(ts), 3650d522f475Smrg TTYSIZE_COLS(ts), i)); 3651d522f475Smrg#endif /* TTYSIZE_STRUCT */ 3652d522f475Smrg 36530bd37d32Smrg#if !defined(USE_OPENPTY) 36540bd37d32Smrg#if defined(USE_USG_PTYS) || defined(HAVE_POSIX_OPENPT) 36550bd37d32Smrg /* 36560bd37d32Smrg * utempter checks the ownership of the device; some implementations 36570bd37d32Smrg * set ownership in grantpt - do this first. 36580bd37d32Smrg */ 36590bd37d32Smrg grantpt(screen->respond); 36600bd37d32Smrg#endif 36610bd37d32Smrg#if !defined(USE_USG_PTYS) && defined(HAVE_POSIX_OPENPT) 36620bd37d32Smrg unlockpt(screen->respond); 36630bd37d32Smrg TRACE_TTYSIZE(screen->respond, "after unlockpt"); 36640bd37d32Smrg#endif 36650bd37d32Smrg#endif /* !USE_OPENPTY */ 36660bd37d32Smrg 3667d522f475Smrg added_utmp_entry = False; 3668d522f475Smrg#if defined(USE_UTEMPTER) 3669d522f475Smrg#undef UTMP 3670d522f475Smrg if (!resource.utmpInhibit) { 3671d522f475Smrg struct UTMP_STR dummy; 3672d522f475Smrg 3673d522f475Smrg /* Note: utempter may trim it anyway */ 3674d522f475Smrg SetUtmpHost(dummy.ut_host, screen); 36750bd37d32Smrg TRACE(("...calling addToUtmp(pty=%s, hostname=%s, master_fd=%d)\n", 36760bd37d32Smrg ttydev, dummy.ut_host, screen->respond)); 3677d522f475Smrg addToUtmp(ttydev, dummy.ut_host, screen->respond); 3678d522f475Smrg added_utmp_entry = True; 3679d522f475Smrg } 3680d522f475Smrg#endif 3681d522f475Smrg 3682d522f475Smrg if (am_slave < 0) { 3683d522f475Smrg#if OPT_PTY_HANDSHAKE 3684d522f475Smrg if (resource.ptyHandshake && (pipe(pc_pipe) || pipe(cp_pipe))) 3685d522f475Smrg SysError(ERROR_FORK); 3686d522f475Smrg#endif 3687d522f475Smrg TRACE(("Forking...\n")); 3688d522f475Smrg if ((screen->pid = fork()) == -1) 3689d522f475Smrg SysError(ERROR_FORK); 3690d522f475Smrg 3691d522f475Smrg if (screen->pid == 0) { 3692d522f475Smrg#ifdef USE_USG_PTYS 369320d2c4d2Smrg int ptyfd = -1; 3694d522f475Smrg char *pty_name; 3695d522f475Smrg#endif 3696d522f475Smrg /* 3697d522f475Smrg * now in child process 3698d522f475Smrg */ 3699d522f475Smrg#if defined(_POSIX_SOURCE) || defined(SVR4) || defined(__convex__) || defined(__SCO__) || defined(__QNX__) 3700d522f475Smrg int pgrp = setsid(); /* variable may not be used... */ 3701d522f475Smrg#else 3702d522f475Smrg int pgrp = getpid(); 3703d522f475Smrg#endif 3704d522f475Smrg TRACE_CHILD 3705d522f475Smrg 3706d522f475Smrg#ifdef USE_USG_PTYS 37070bd37d32Smrg#ifdef HAVE_SETPGID 37080bd37d32Smrg setpgid(0, 0); 37090bd37d32Smrg#else 3710d522f475Smrg setpgrp(); 37110bd37d32Smrg#endif 37120bd37d32Smrg unlockpt(screen->respond); 37130bd37d32Smrg TRACE_TTYSIZE(screen->respond, "after unlockpt"); 37140bd37d32Smrg if ((pty_name = ptsname(screen->respond)) == 0) { 37150bd37d32Smrg SysError(ERROR_PTSNAME); 37160bd37d32Smrg } else if ((ptyfd = open(pty_name, O_RDWR)) < 0) { 37170bd37d32Smrg SysError(ERROR_OPPTSNAME); 37180bd37d32Smrg } 3719d522f475Smrg#ifdef I_PUSH 37200bd37d32Smrg else if (ioctl(ptyfd, I_PUSH, "ptem") < 0) { 37210bd37d32Smrg SysError(ERROR_PTEM); 37220bd37d32Smrg } 3723d522f475Smrg#if !defined(SVR4) && !(defined(SYSV) && defined(i386)) 37240bd37d32Smrg else if (!x_getenv("CONSEM") 37250bd37d32Smrg && ioctl(ptyfd, I_PUSH, "consem") < 0) { 37260bd37d32Smrg SysError(ERROR_CONSEM); 37270bd37d32Smrg } 3728d522f475Smrg#endif /* !SVR4 */ 37290bd37d32Smrg else if (ioctl(ptyfd, I_PUSH, "ldterm") < 0) { 37300bd37d32Smrg SysError(ERROR_LDTERM); 37310bd37d32Smrg } 3732d522f475Smrg#ifdef SVR4 /* from Sony */ 37330bd37d32Smrg else if (ioctl(ptyfd, I_PUSH, "ttcompat") < 0) { 37340bd37d32Smrg SysError(ERROR_TTCOMPAT); 37350bd37d32Smrg } 3736d522f475Smrg#endif /* SVR4 */ 3737d522f475Smrg#endif /* I_PUSH */ 37380bd37d32Smrg ttyfd = ptyfd; 3739d522f475Smrg#ifndef __MVS__ 37400bd37d32Smrg close_fd(screen->respond); 3741d522f475Smrg#endif /* __MVS__ */ 3742d522f475Smrg 3743d522f475Smrg#ifdef TTYSIZE_STRUCT 37440bd37d32Smrg /* tell tty how big window is */ 3745d522f475Smrg#if OPT_TEK4014 37460bd37d32Smrg if (TEK4014_ACTIVE(xw)) { 37470bd37d32Smrg TTYSIZE_ROWS(ts) = 24; 37480bd37d32Smrg TTYSIZE_COLS(ts) = 80; 3749d522f475Smrg#ifdef USE_STRUCT_WINSIZE 37500bd37d32Smrg ts.ws_xpixel = TFullWidth(TekScreenOf(tekWidget)); 37510bd37d32Smrg ts.ws_ypixel = TFullHeight(TekScreenOf(tekWidget)); 3752d522f475Smrg#endif 37530bd37d32Smrg } else 3754d522f475Smrg#endif /* OPT_TEK4014 */ 37550bd37d32Smrg { 37560bd37d32Smrg TTYSIZE_ROWS(ts) = (ttySize_t) MaxRows(screen); 37570bd37d32Smrg TTYSIZE_COLS(ts) = (ttySize_t) MaxCols(screen); 3758d522f475Smrg#ifdef USE_STRUCT_WINSIZE 37590bd37d32Smrg ts.ws_xpixel = (ttySize_t) FullWidth(screen); 37600bd37d32Smrg ts.ws_ypixel = (ttySize_t) FullHeight(screen); 3761d522f475Smrg#endif 37620bd37d32Smrg } 3763d522f475Smrg#endif /* TTYSIZE_STRUCT */ 3764d522f475Smrg 3765d522f475Smrg#endif /* USE_USG_PTYS */ 3766d522f475Smrg 37670bd37d32Smrg (void) pgrp; /* not all branches use this variable */ 3768d522f475Smrg 3769d522f475Smrg#if OPT_PTY_HANDSHAKE /* warning, goes for a long ways */ 37700bd37d32Smrg if (resource.ptyHandshake) { 37710bd37d32Smrg char *ptr; 3772d522f475Smrg 37730bd37d32Smrg /* close parent's sides of the pipes */ 37740bd37d32Smrg close(cp_pipe[0]); 37750bd37d32Smrg close(pc_pipe[1]); 37760bd37d32Smrg 37770bd37d32Smrg /* Make sure that our sides of the pipes are not in the 37780bd37d32Smrg * 0, 1, 2 range so that we don't fight with stdin, out 37790bd37d32Smrg * or err. 37800bd37d32Smrg */ 37810bd37d32Smrg if (cp_pipe[1] <= 2) { 37820bd37d32Smrg if ((i = fcntl(cp_pipe[1], F_DUPFD, 3)) >= 0) { 37830bd37d32Smrg IGNORE_RC(close(cp_pipe[1])); 37840bd37d32Smrg cp_pipe[1] = i; 3785d522f475Smrg } 37860bd37d32Smrg } 37870bd37d32Smrg if (pc_pipe[0] <= 2) { 37880bd37d32Smrg if ((i = fcntl(pc_pipe[0], F_DUPFD, 3)) >= 0) { 37890bd37d32Smrg IGNORE_RC(close(pc_pipe[0])); 37900bd37d32Smrg pc_pipe[0] = i; 3791d522f475Smrg } 37920bd37d32Smrg } 3793d522f475Smrg 37940bd37d32Smrg /* we don't need the socket, or the pty master anymore */ 37950bd37d32Smrg close(ConnectionNumber(screen->display)); 3796d522f475Smrg#ifndef __MVS__ 3797894e0ac8Smrg if (screen->respond >= 0) 3798894e0ac8Smrg close(screen->respond); 3799d522f475Smrg#endif /* __MVS__ */ 3800d522f475Smrg 38010bd37d32Smrg /* Now is the time to set up our process group and 38020bd37d32Smrg * open up the pty slave. 38030bd37d32Smrg */ 3804d522f475Smrg#ifdef USE_SYSV_PGRP 3805d522f475Smrg#if defined(CRAY) && (OSMAJORVERSION > 5) 38060bd37d32Smrg IGNORE_RC(setsid()); 3807d522f475Smrg#else 38080bd37d32Smrg IGNORE_RC(setpgrp()); 3809d522f475Smrg#endif 3810d522f475Smrg#endif /* USE_SYSV_PGRP */ 3811d522f475Smrg 3812d522f475Smrg#if defined(__QNX__) && !defined(__QNXNTO__) 38130bd37d32Smrg qsetlogin(getlogin(), ttydev); 3814d522f475Smrg#endif 38150bd37d32Smrg if (ttyfd >= 0) { 3816d522f475Smrg#ifdef __MVS__ 38170bd37d32Smrg if (ttyGetAttr(ttyfd, &gio) == 0) { 38180bd37d32Smrg gio.c_cflag &= ~(HUPCL | PARENB); 38190bd37d32Smrg ttySetAttr(ttyfd, &gio); 38200bd37d32Smrg } 3821d522f475Smrg#else /* !__MVS__ */ 38220bd37d32Smrg close_fd(ttyfd); 3823d522f475Smrg#endif /* __MVS__ */ 38240bd37d32Smrg } 3825d522f475Smrg 38260bd37d32Smrg for (;;) { 382720d2c4d2Smrg#if USE_NO_DEV_TTY 38280bd37d32Smrg if (!no_dev_tty 38290bd37d32Smrg && (ttyfd = open("/dev/tty", O_RDWR)) >= 0) { 38300bd37d32Smrg ioctl(ttyfd, TIOCNOTTY, (char *) NULL); 38310bd37d32Smrg close_fd(ttyfd); 38320bd37d32Smrg } 383320d2c4d2Smrg#endif /* USE_NO_DEV_TTY */ 3834d522f475Smrg#ifdef CSRG_BASED 38350bd37d32Smrg IGNORE_RC(revoke(ttydev)); 3836d522f475Smrg#endif 38370bd37d32Smrg if ((ttyfd = open(ttydev, O_RDWR)) >= 0) { 38380bd37d32Smrg TRACE_TTYSIZE(ttyfd, "after open"); 38390bd37d32Smrg TRACE_RC(i, SET_TTYSIZE(ttyfd, ts)); 38400bd37d32Smrg TRACE_TTYSIZE(ttyfd, "after fixup"); 3841d522f475Smrg#if defined(CRAY) && defined(TCSETCTTY) 38420bd37d32Smrg /* make /dev/tty work */ 38430bd37d32Smrg ioctl(ttyfd, TCSETCTTY, 0); 3844d522f475Smrg#endif 3845d522f475Smrg#if ((defined(__GLIBC__) && defined(__FreeBSD_kernel__)) || defined(__GNU__)) && defined(TIOCSCTTY) 38460bd37d32Smrg /* make /dev/tty work */ 38470bd37d32Smrg ioctl(ttyfd, TIOCSCTTY, 0); 3848d522f475Smrg#endif 3849d522f475Smrg#ifdef USE_SYSV_PGRP 38500bd37d32Smrg /* We need to make sure that we are actually 38510bd37d32Smrg * the process group leader for the pty. If 38520bd37d32Smrg * we are, then we should now be able to open 38530bd37d32Smrg * /dev/tty. 38540bd37d32Smrg */ 38550bd37d32Smrg if ((i = open("/dev/tty", O_RDWR)) >= 0) { 38560bd37d32Smrg /* success! */ 38570bd37d32Smrg close(i); 3858d522f475Smrg break; 3859d522f475Smrg } 38600bd37d32Smrg#else /* USE_SYSV_PGRP */ 38610bd37d32Smrg break; 38620bd37d32Smrg#endif /* USE_SYSV_PGRP */ 38630bd37d32Smrg } 38640bd37d32Smrg perror("open ttydev"); 3865d522f475Smrg#ifdef TIOCSCTTY 38660bd37d32Smrg ioctl(ttyfd, TIOCSCTTY, 0); 3867d522f475Smrg#endif 38680bd37d32Smrg /* let our master know that the open failed */ 38690bd37d32Smrg handshake.status = PTY_BAD; 38700bd37d32Smrg handshake.error = errno; 38710bd37d32Smrg strncpy(handshake.buffer, ttydev, sizeof(handshake.buffer)); 38720bd37d32Smrg TRACE_HANDSHAKE("writing", &handshake); 38730bd37d32Smrg IGNORE_RC(write(cp_pipe[1], 38740bd37d32Smrg (const char *) &handshake, 38750bd37d32Smrg sizeof(handshake))); 3876d522f475Smrg 38770bd37d32Smrg /* get reply from parent */ 38780bd37d32Smrg i = (int) read(pc_pipe[0], (char *) &handshake, 38790bd37d32Smrg sizeof(handshake)); 38800bd37d32Smrg if (i <= 0) { 38810bd37d32Smrg /* parent terminated */ 38820bd37d32Smrg exit(1); 3883d522f475Smrg } 3884d522f475Smrg 38850bd37d32Smrg if (handshake.status == PTY_NOMORE) { 38860bd37d32Smrg /* No more ptys, let's shutdown. */ 38870bd37d32Smrg exit(1); 3888d522f475Smrg } 38890bd37d32Smrg 38900bd37d32Smrg /* We have a new pty to try */ 38910bd37d32Smrg if (ttyfd >= 0) 38920bd37d32Smrg close(ttyfd); 38930bd37d32Smrg free(ttydev); 38940bd37d32Smrg ttydev = x_strdup(handshake.buffer); 3895d522f475Smrg } 3896d522f475Smrg 38970bd37d32Smrg /* use the same tty name that everyone else will use 38980bd37d32Smrg * (from ttyname) 38990bd37d32Smrg */ 39000bd37d32Smrg if ((ptr = ttyname(ttyfd)) != 0) { 39010bd37d32Smrg free(ttydev); 39020bd37d32Smrg ttydev = x_strdup(ptr); 39030bd37d32Smrg } 39040bd37d32Smrg } 39050bd37d32Smrg#endif /* OPT_PTY_HANDSHAKE -- from near fork */ 3906d522f475Smrg 3907d522f475Smrg set_pty_permissions(screen->uid, 3908d522f475Smrg screen->gid, 3909d522f475Smrg (resource.messages 3910d522f475Smrg ? 0622U 3911d522f475Smrg : 0600U)); 3912d522f475Smrg 3913d522f475Smrg /* 3914d522f475Smrg * set up the tty modes 3915d522f475Smrg */ 3916d522f475Smrg { 3917d522f475Smrg#ifdef TERMIO_STRUCT 3918d522f475Smrg#if defined(umips) || defined(CRAY) || defined(linux) 3919d522f475Smrg /* If the control tty had its modes screwed around with, 3920d522f475Smrg eg. by lineedit in the shell, or emacs, etc. then tio 3921d522f475Smrg will have bad values. Let's just get termio from the 3922d522f475Smrg new tty and tailor it. */ 3923d522f475Smrg if (ttyGetAttr(ttyfd, &tio) == -1) 3924d522f475Smrg SysError(ERROR_TIOCGETP); 3925d522f475Smrg tio.c_lflag |= ECHOE; 3926d522f475Smrg#endif /* umips */ 3927d522f475Smrg /* Now is also the time to change the modes of the 3928d522f475Smrg * child pty. 3929d522f475Smrg */ 3930d522f475Smrg /* input: nl->nl, don't ignore cr, cr->nl */ 393120d2c4d2Smrg UIntClr(tio.c_iflag, (INLCR | IGNCR)); 3932d522f475Smrg tio.c_iflag |= ICRNL; 39330bd37d32Smrg#if OPT_WIDE_CHARS && defined(IUTF8) 3934d522f475Smrg#if OPT_LUIT_PROG 3935d522f475Smrg if (command_to_exec_with_luit == 0) 3936d522f475Smrg#endif 3937d522f475Smrg if (screen->utf8_mode) 3938d522f475Smrg tio.c_iflag |= IUTF8; 3939d522f475Smrg#endif 3940d522f475Smrg /* ouput: cr->cr, nl is not return, no delays, ln->cr/nl */ 3941d522f475Smrg#ifndef USE_POSIX_TERMIOS 394220d2c4d2Smrg UIntClr(tio.c_oflag, 394320d2c4d2Smrg (OCRNL 394420d2c4d2Smrg | ONLRET 394520d2c4d2Smrg | NLDLY 394620d2c4d2Smrg | CRDLY 394720d2c4d2Smrg | TABDLY 394820d2c4d2Smrg | BSDLY 394920d2c4d2Smrg | VTDLY 395020d2c4d2Smrg | FFDLY)); 3951d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 3952d522f475Smrg#ifdef ONLCR 3953d522f475Smrg tio.c_oflag |= ONLCR; 3954d522f475Smrg#endif /* ONLCR */ 3955d522f475Smrg#ifdef OPOST 3956d522f475Smrg tio.c_oflag |= OPOST; 3957d522f475Smrg#endif /* OPOST */ 3958d522f475Smrg#ifndef USE_POSIX_TERMIOS 3959d522f475Smrg# if defined(Lynx) && !defined(CBAUD) 3960d522f475Smrg# define CBAUD V_CBAUD 3961d522f475Smrg# endif 396220d2c4d2Smrg UIntClr(tio.c_cflag, CBAUD); 3963d522f475Smrg#ifdef BAUD_0 3964d522f475Smrg /* baud rate is 0 (don't care) */ 3965d522f475Smrg#elif defined(HAVE_TERMIO_C_ISPEED) 3966d522f475Smrg tio.c_ispeed = tio.c_ospeed = VAL_LINE_SPEED; 3967d522f475Smrg#else /* !BAUD_0 */ 3968d522f475Smrg tio.c_cflag |= VAL_LINE_SPEED; 3969d522f475Smrg#endif /* !BAUD_0 */ 3970d522f475Smrg#else /* USE_POSIX_TERMIOS */ 3971d522f475Smrg cfsetispeed(&tio, VAL_LINE_SPEED); 3972d522f475Smrg cfsetospeed(&tio, VAL_LINE_SPEED); 3973d522f475Smrg#ifdef __MVS__ 3974d522f475Smrg /* turn off bits that can't be set from the slave side */ 3975d522f475Smrg tio.c_cflag &= ~(PACKET | PKT3270 | PTU3270 | PKTXTND); 3976d522f475Smrg#endif /* __MVS__ */ 3977d522f475Smrg /* Clear CLOCAL so that SIGHUP is sent to us 3978d522f475Smrg when the xterm ends */ 3979d522f475Smrg tio.c_cflag &= ~CLOCAL; 3980d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 3981d522f475Smrg /* enable signals, canonical processing (erase, kill, etc), 3982d522f475Smrg * echo 3983d522f475Smrg */ 3984d522f475Smrg tio.c_lflag |= ISIG | ICANON | ECHO | ECHOE | ECHOK; 3985d522f475Smrg#ifdef ECHOKE 3986d522f475Smrg tio.c_lflag |= ECHOKE | IEXTEN; 3987d522f475Smrg#endif 3988d522f475Smrg#ifdef ECHOCTL 3989d522f475Smrg tio.c_lflag |= ECHOCTL | IEXTEN; 3990d522f475Smrg#endif 3991d522f475Smrg for (nn = 0; nn < XtNumber(known_ttyChars); ++nn) { 3992d522f475Smrg if (validTtyChar(tio, nn)) { 3993d522f475Smrg int sysMode = known_ttyChars[nn].sysMode; 3994d522f475Smrg#ifdef __MVS__ 3995d522f475Smrg if (tio.c_cc[sysMode] != 0) { 3996d522f475Smrg switch (sysMode) { 3997d522f475Smrg case VEOL: 3998d522f475Smrg case VEOF: 3999d522f475Smrg continue; 4000d522f475Smrg } 4001d522f475Smrg } 4002d522f475Smrg#endif 40030bd37d32Smrg tio.c_cc[sysMode] = (cc_t) known_ttyChars[nn].myDefault; 4004d522f475Smrg } 4005d522f475Smrg } 4006d522f475Smrg 4007d522f475Smrg if (override_tty_modes) { 4008d522f475Smrg for (nn = 0; nn < XtNumber(known_ttyChars); ++nn) { 4009d522f475Smrg if (validTtyChar(tio, nn)) { 4010d522f475Smrg TMODE(known_ttyChars[nn].myMode, 4011d522f475Smrg tio.c_cc[known_ttyChars[nn].sysMode]); 4012d522f475Smrg } 4013d522f475Smrg } 4014d522f475Smrg#ifdef HAS_LTCHARS 4015d522f475Smrg /* both SYSV and BSD have ltchars */ 4016d522f475Smrg TMODE(XTTYMODE_susp, ltc.t_suspc); 4017d522f475Smrg TMODE(XTTYMODE_dsusp, ltc.t_dsuspc); 4018d522f475Smrg TMODE(XTTYMODE_rprnt, ltc.t_rprntc); 4019d522f475Smrg TMODE(XTTYMODE_flush, ltc.t_flushc); 4020d522f475Smrg TMODE(XTTYMODE_weras, ltc.t_werasc); 4021d522f475Smrg TMODE(XTTYMODE_lnext, ltc.t_lnextc); 4022d522f475Smrg#endif 4023d522f475Smrg } 4024d522f475Smrg#ifdef HAS_LTCHARS 4025d522f475Smrg#ifdef __hpux 4026d522f475Smrg /* ioctl chokes when the "reserved" process group controls 4027d522f475Smrg * are not set to _POSIX_VDISABLE */ 4028d522f475Smrg ltc.t_rprntc = ltc.t_rprntc = ltc.t_flushc = 4029d522f475Smrg ltc.t_werasc = ltc.t_lnextc = _POSIX_VDISABLE; 4030d522f475Smrg#endif /* __hpux */ 4031d522f475Smrg if (ioctl(ttyfd, TIOCSLTC, <c) == -1) 4032d522f475Smrg HsSysError(ERROR_TIOCSETC); 4033d522f475Smrg#endif /* HAS_LTCHARS */ 4034d522f475Smrg#ifdef TIOCLSET 4035d522f475Smrg if (ioctl(ttyfd, TIOCLSET, (char *) &lmode) == -1) 4036d522f475Smrg HsSysError(ERROR_TIOCLSET); 4037d522f475Smrg#endif /* TIOCLSET */ 4038d522f475Smrg if (ttySetAttr(ttyfd, &tio) == -1) 4039d522f475Smrg HsSysError(ERROR_TIOCSETP); 4040d522f475Smrg 4041d522f475Smrg /* ignore errors here - some platforms don't work */ 404220d2c4d2Smrg UIntClr(tio.c_cflag, CSIZE); 4043d522f475Smrg if (screen->input_eight_bits) 4044d522f475Smrg tio.c_cflag |= CS8; 4045d522f475Smrg else 4046d522f475Smrg tio.c_cflag |= CS7; 4047d522f475Smrg (void) ttySetAttr(ttyfd, &tio); 4048d522f475Smrg 4049d522f475Smrg#else /* !TERMIO_STRUCT */ 4050d522f475Smrg sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW); 4051d522f475Smrg sg.sg_flags |= ECHO | CRMOD; 4052d522f475Smrg /* make sure speed is set on pty so that editors work right */ 4053d522f475Smrg sg.sg_ispeed = VAL_LINE_SPEED; 4054d522f475Smrg sg.sg_ospeed = VAL_LINE_SPEED; 4055d522f475Smrg /* reset t_brkc to default value */ 4056d522f475Smrg tc.t_brkc = -1; 4057d522f475Smrg#ifdef LPASS8 4058d522f475Smrg if (screen->input_eight_bits) 4059d522f475Smrg lmode |= LPASS8; 4060d522f475Smrg else 4061d522f475Smrg lmode &= ~(LPASS8); 4062d522f475Smrg#endif 4063d522f475Smrg#ifdef sony 4064d522f475Smrg jmode &= ~KM_KANJI; 4065d522f475Smrg#endif /* sony */ 4066d522f475Smrg 4067d522f475Smrg ltc = d_ltc; 4068d522f475Smrg 4069d522f475Smrg if (override_tty_modes) { 4070d522f475Smrg TMODE(XTTYMODE_intr, tc.t_intrc); 4071d522f475Smrg TMODE(XTTYMODE_quit, tc.t_quitc); 4072d522f475Smrg TMODE(XTTYMODE_erase, sg.sg_erase); 4073d522f475Smrg TMODE(XTTYMODE_kill, sg.sg_kill); 4074d522f475Smrg TMODE(XTTYMODE_eof, tc.t_eofc); 4075d522f475Smrg TMODE(XTTYMODE_start, tc.t_startc); 4076d522f475Smrg TMODE(XTTYMODE_stop, tc.t_stopc); 4077d522f475Smrg TMODE(XTTYMODE_brk, tc.t_brkc); 4078d522f475Smrg /* both SYSV and BSD have ltchars */ 4079d522f475Smrg TMODE(XTTYMODE_susp, ltc.t_suspc); 4080d522f475Smrg TMODE(XTTYMODE_dsusp, ltc.t_dsuspc); 4081d522f475Smrg TMODE(XTTYMODE_rprnt, ltc.t_rprntc); 4082d522f475Smrg TMODE(XTTYMODE_flush, ltc.t_flushc); 4083d522f475Smrg TMODE(XTTYMODE_weras, ltc.t_werasc); 4084d522f475Smrg TMODE(XTTYMODE_lnext, ltc.t_lnextc); 4085d522f475Smrg } 4086d522f475Smrg 4087d522f475Smrg if (ioctl(ttyfd, TIOCSETP, (char *) &sg) == -1) 4088d522f475Smrg HsSysError(ERROR_TIOCSETP); 4089d522f475Smrg if (ioctl(ttyfd, TIOCSETC, (char *) &tc) == -1) 4090d522f475Smrg HsSysError(ERROR_TIOCSETC); 4091d522f475Smrg if (ioctl(ttyfd, TIOCSETD, (char *) &discipline) == -1) 4092d522f475Smrg HsSysError(ERROR_TIOCSETD); 4093d522f475Smrg if (ioctl(ttyfd, TIOCSLTC, (char *) <c) == -1) 4094d522f475Smrg HsSysError(ERROR_TIOCSLTC); 4095d522f475Smrg if (ioctl(ttyfd, TIOCLSET, (char *) &lmode) == -1) 4096d522f475Smrg HsSysError(ERROR_TIOCLSET); 4097d522f475Smrg#ifdef sony 4098d522f475Smrg if (ioctl(ttyfd, TIOCKSET, (char *) &jmode) == -1) 4099d522f475Smrg HsSysError(ERROR_TIOCKSET); 4100d522f475Smrg if (ioctl(ttyfd, TIOCKSETC, (char *) &jtc) == -1) 4101d522f475Smrg HsSysError(ERROR_TIOCKSETC); 4102d522f475Smrg#endif /* sony */ 4103d522f475Smrg#endif /* TERMIO_STRUCT */ 4104d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 4105d522f475Smrg if (Console) { 4106d522f475Smrg#ifdef TIOCCONS 4107d522f475Smrg int on = 1; 4108d522f475Smrg if (ioctl(ttyfd, TIOCCONS, (char *) &on) == -1) 41090bd37d32Smrg xtermPerror("cannot open console"); 4110d522f475Smrg#endif 4111d522f475Smrg#ifdef SRIOCSREDIR 4112d522f475Smrg int fd = open("/dev/console", O_RDWR); 4113d522f475Smrg if (fd == -1 || ioctl(fd, SRIOCSREDIR, ttyfd) == -1) 41140bd37d32Smrg xtermPerror("cannot open console"); 411520d2c4d2Smrg IGNORE_RC(close(fd)); 4116d522f475Smrg#endif 4117d522f475Smrg } 4118d522f475Smrg#endif /* TIOCCONS */ 4119d522f475Smrg } 4120d522f475Smrg 4121d522f475Smrg signal(SIGCHLD, SIG_DFL); 4122d522f475Smrg#ifdef USE_SYSV_SIGHUP 4123d522f475Smrg /* watch out for extra shells (I don't understand either) */ 4124d522f475Smrg signal(SIGHUP, SIG_DFL); 4125d522f475Smrg#else 4126d522f475Smrg signal(SIGHUP, SIG_IGN); 4127d522f475Smrg#endif 4128d522f475Smrg /* restore various signals to their defaults */ 4129d522f475Smrg signal(SIGINT, SIG_DFL); 4130d522f475Smrg signal(SIGQUIT, SIG_DFL); 4131d522f475Smrg signal(SIGTERM, SIG_DFL); 4132d522f475Smrg 4133d522f475Smrg /* 4134d522f475Smrg * If we're not asked to let the parent process set the terminal's 4135d522f475Smrg * erase mode, or if we had the ttyModes erase resource, then set 4136d522f475Smrg * the terminal's erase mode from our best guess. 4137d522f475Smrg */ 4138d522f475Smrg#if OPT_INITIAL_ERASE 4139d522f475Smrg TRACE(("check if we should set erase to %d:%s\n\tptyInitialErase:%d,\n\toveride_tty_modes:%d,\n\tXTTYMODE_erase:%d\n", 4140d522f475Smrg initial_erase, 4141d522f475Smrg setInitialErase ? "YES" : "NO", 4142d522f475Smrg resource.ptyInitialErase, 4143d522f475Smrg override_tty_modes, 4144d522f475Smrg ttymodelist[XTTYMODE_erase].set)); 4145d522f475Smrg if (setInitialErase) { 4146d522f475Smrg#if OPT_TRACE 4147d522f475Smrg int old_erase; 4148d522f475Smrg#endif 4149d522f475Smrg#ifdef TERMIO_STRUCT 4150d522f475Smrg if (ttyGetAttr(ttyfd, &tio) == -1) 4151d522f475Smrg tio = d_tio; 4152d522f475Smrg#if OPT_TRACE 4153d522f475Smrg old_erase = tio.c_cc[VERASE]; 4154d522f475Smrg#endif 41550bd37d32Smrg tio.c_cc[VERASE] = (cc_t) initial_erase; 415620d2c4d2Smrg TRACE_RC(rc, ttySetAttr(ttyfd, &tio)); 4157d522f475Smrg#else /* !TERMIO_STRUCT */ 4158d522f475Smrg if (ioctl(ttyfd, TIOCGETP, (char *) &sg) == -1) 4159d522f475Smrg sg = d_sg; 4160d522f475Smrg#if OPT_TRACE 4161d522f475Smrg old_erase = sg.sg_erase; 4162d522f475Smrg#endif 4163d522f475Smrg sg.sg_erase = initial_erase; 4164d522f475Smrg rc = ioctl(ttyfd, TIOCSETP, (char *) &sg); 4165d522f475Smrg#endif /* TERMIO_STRUCT */ 4166d522f475Smrg TRACE(("%s setting erase to %d (was %d)\n", 4167d522f475Smrg rc ? "FAIL" : "OK", initial_erase, old_erase)); 4168d522f475Smrg } 4169d522f475Smrg#endif 4170d522f475Smrg 4171d522f475Smrg xtermCopyEnv(environ); 4172d522f475Smrg 41730bd37d32Smrg /* 41740bd37d32Smrg * standards.freedesktop.org/startup-notification-spec/ 41750bd37d32Smrg * notes that this variable is used when a "reliable" mechanism is 41760bd37d32Smrg * not available; in practice it must be unset to avoid confusing 41770bd37d32Smrg * GTK applications. 41780bd37d32Smrg */ 41790bd37d32Smrg xtermUnsetenv("DESKTOP_STARTUP_ID"); 4180e0a2b6dfSmrg /* 4181e0a2b6dfSmrg * We set this temporarily to work around poor design of Xcursor. 4182e0a2b6dfSmrg * Unset it here to avoid confusion. 4183e0a2b6dfSmrg */ 4184e0a2b6dfSmrg xtermUnsetenv("XCURSOR_PATH"); 41850bd37d32Smrg 4186a1f3da82Smrg xtermSetenv("TERM", resource.term_name); 4187a1f3da82Smrg if (!resource.term_name) 418820d2c4d2Smrg *get_tcap_buffer(xw) = 0; 4189d522f475Smrg 4190d522f475Smrg sprintf(buf, "%lu", 4191d522f475Smrg ((unsigned long) XtWindow(SHELL_OF(CURRENT_EMU())))); 4192d522f475Smrg xtermSetenv("WINDOWID", buf); 4193d522f475Smrg 4194d522f475Smrg /* put the display into the environment of the shell */ 4195d522f475Smrg xtermSetenv("DISPLAY", XDisplayString(screen->display)); 4196d522f475Smrg 4197d522f475Smrg xtermSetenv("XTERM_VERSION", xtermVersion()); 4198d522f475Smrg xtermSetenv("XTERM_LOCALE", xtermEnvLocale()); 4199d522f475Smrg 4200e39b573cSmrg /* 4201e39b573cSmrg * For debugging only, add environment variables that can be used 4202e39b573cSmrg * in scripts to selectively kill xterm's parent or child 4203e39b573cSmrg * processes. 4204e39b573cSmrg */ 4205e39b573cSmrg#if OPT_TRACE 4206e39b573cSmrg sprintf(buf, "%lu", (unsigned long) xterm_parent); 4207e39b573cSmrg xtermSetenv("XTERM_PARENT", buf); 4208e39b573cSmrg sprintf(buf, "%lu", (unsigned long) getpid()); 4209e39b573cSmrg xtermSetenv("XTERM_CHILD", buf); 4210e39b573cSmrg#endif 4211e39b573cSmrg 4212d522f475Smrg signal(SIGTERM, SIG_DFL); 4213d522f475Smrg 4214d522f475Smrg /* this is the time to go and set up stdin, out, and err 4215d522f475Smrg */ 4216d522f475Smrg { 4217d522f475Smrg#if defined(CRAY) && (OSMAJORVERSION >= 6) 4218d522f475Smrg close_fd(ttyfd); 4219d522f475Smrg 422020d2c4d2Smrg IGNORE_RC(close(0)); 4221d522f475Smrg 4222d522f475Smrg if (open("/dev/tty", O_RDWR)) { 4223d522f475Smrg SysError(ERROR_OPDEVTTY); 4224d522f475Smrg } 422520d2c4d2Smrg IGNORE_RC(close(1)); 422620d2c4d2Smrg IGNORE_RC(close(2)); 4227d522f475Smrg dup(0); 4228d522f475Smrg dup(0); 4229d522f475Smrg#else 4230d522f475Smrg /* dup the tty */ 4231d522f475Smrg for (i = 0; i <= 2; i++) 4232d522f475Smrg if (i != ttyfd) { 423320d2c4d2Smrg IGNORE_RC(close(i)); 423420d2c4d2Smrg IGNORE_RC(dup(ttyfd)); 4235d522f475Smrg } 4236d522f475Smrg#ifndef ATT 4237d522f475Smrg /* and close the tty */ 4238d522f475Smrg if (ttyfd > 2) 4239d522f475Smrg close_fd(ttyfd); 4240d522f475Smrg#endif 4241d522f475Smrg#endif /* CRAY */ 4242d522f475Smrg } 4243d522f475Smrg 4244d522f475Smrg#if !defined(USE_SYSV_PGRP) 4245d522f475Smrg#ifdef TIOCSCTTY 4246d522f475Smrg setsid(); 4247d522f475Smrg ioctl(0, TIOCSCTTY, 0); 4248d522f475Smrg#endif 4249d522f475Smrg ioctl(0, TIOCSPGRP, (char *) &pgrp); 4250d522f475Smrg setpgrp(0, 0); 4251d522f475Smrg close(open(ttydev, O_WRONLY)); 4252d522f475Smrg setpgrp(0, pgrp); 4253d522f475Smrg#if defined(__QNX__) 4254d522f475Smrg tcsetpgrp(0, pgrp /*setsid() */ ); 4255d522f475Smrg#endif 4256d522f475Smrg#endif /* !USE_SYSV_PGRP */ 4257d522f475Smrg 4258d522f475Smrg#ifdef Lynx 4259d522f475Smrg { 4260d522f475Smrg TERMIO_STRUCT t; 4261d522f475Smrg if (ttyGetAttr(0, &t) >= 0) { 4262d522f475Smrg /* this gets lost somewhere on our way... */ 4263d522f475Smrg t.c_oflag |= OPOST; 4264d522f475Smrg ttySetAttr(0, &t); 4265d522f475Smrg } 4266d522f475Smrg } 4267d522f475Smrg#endif 4268d522f475Smrg 4269d522f475Smrg#ifdef HAVE_UTMP 4270d522f475Smrg login_name = NULL; 42710bd37d32Smrg if (x_getpwuid(screen->uid, &pw)) { 42720bd37d32Smrg login_name = x_getlogin(screen->uid, &pw); 4273d522f475Smrg } 4274d522f475Smrg if (login_name != NULL) { 4275d522f475Smrg xtermSetenv("LOGNAME", login_name); /* for POSIX */ 4276d522f475Smrg } 4277d522f475Smrg#ifndef USE_UTEMPTER 4278d522f475Smrg#ifdef USE_UTMP_SETGID 4279d522f475Smrg setEffectiveGroup(save_egid); 4280d522f475Smrg TRACE_IDS; 4281d522f475Smrg#endif 4282d522f475Smrg#ifdef USE_SYSV_UTMP 4283d522f475Smrg /* Set up our utmp entry now. We need to do it here 4284d522f475Smrg * for the following reasons: 4285d522f475Smrg * - It needs to have our correct process id (for 4286d522f475Smrg * login). 4287d522f475Smrg * - If our parent was to set it after the fork(), 4288d522f475Smrg * it might make it out before we need it. 4289d522f475Smrg * - We need to do it before we go and change our 4290d522f475Smrg * user and group id's. 4291d522f475Smrg */ 4292d522f475Smrg (void) call_setutent(); 4293d522f475Smrg init_utmp(DEAD_PROCESS, &utmp); 4294d522f475Smrg 4295d522f475Smrg /* position to entry in utmp file */ 4296d522f475Smrg /* Test return value: beware of entries left behind: PSz 9 Mar 00 */ 429720d2c4d2Smrg utret = find_utmp(&utmp); 429820d2c4d2Smrg if (utret == 0) { 4299d522f475Smrg (void) call_setutent(); 4300d522f475Smrg init_utmp(USER_PROCESS, &utmp); 430120d2c4d2Smrg utret = find_utmp(&utmp); 430220d2c4d2Smrg if (utret == 0) { 4303d522f475Smrg (void) call_setutent(); 4304d522f475Smrg } 4305d522f475Smrg } 4306d522f475Smrg#if OPT_TRACE 4307d522f475Smrg if (!utret) 4308d522f475Smrg TRACE(("getutid: NULL\n")); 4309d522f475Smrg else 43100bd37d32Smrg TRACE(("getutid: pid=%d type=%d user=%s line=%.*s id=%.*s\n", 431120d2c4d2Smrg (int) utret->ut_pid, utret->ut_type, utret->ut_user, 43120bd37d32Smrg (int) sizeof(utret->ut_line), utret->ut_line, 43130bd37d32Smrg (int) sizeof(utret->ut_id), utret->ut_id)); 4314d522f475Smrg#endif 4315d522f475Smrg 4316d522f475Smrg /* set up the new entry */ 4317d522f475Smrg utmp.ut_type = USER_PROCESS; 4318d522f475Smrg#ifdef HAVE_UTMP_UT_XSTATUS 4319d522f475Smrg utmp.ut_xstatus = 2; 4320d522f475Smrg#endif 4321894e0ac8Smrg copy_filled(utmp.ut_user, 4322894e0ac8Smrg (login_name != NULL) ? login_name : "????", 4323894e0ac8Smrg sizeof(utmp.ut_user)); 4324d522f475Smrg /* why are we copying this string again? (see above) */ 4325894e0ac8Smrg copy_filled(utmp.ut_id, my_utmp_id(ttydev), sizeof(utmp.ut_id)); 4326894e0ac8Smrg copy_filled(utmp.ut_line, 4327894e0ac8Smrg my_pty_name(ttydev), sizeof(utmp.ut_line)); 4328d522f475Smrg 4329d522f475Smrg#ifdef HAVE_UTMP_UT_HOST 4330d522f475Smrg SetUtmpHost(utmp.ut_host, screen); 4331d522f475Smrg#endif 4332d522f475Smrg#ifdef HAVE_UTMP_UT_SYSLEN 4333d522f475Smrg SetUtmpSysLen(utmp); 4334d522f475Smrg#endif 4335d522f475Smrg 4336894e0ac8Smrg copy_filled(utmp.ut_name, 4337894e0ac8Smrg (login_name) ? login_name : "????", 4338894e0ac8Smrg sizeof(utmp.ut_name)); 4339d522f475Smrg 4340d522f475Smrg utmp.ut_pid = getpid(); 4341d522f475Smrg#if defined(HAVE_UTMP_UT_XTIME) 4342d522f475Smrg#if defined(HAVE_UTMP_UT_SESSION) 4343d522f475Smrg utmp.ut_session = getsid(0); 4344d522f475Smrg#endif 4345d522f475Smrg utmp.ut_xtime = time((time_t *) 0); 4346d522f475Smrg utmp.ut_tv.tv_usec = 0; 4347d522f475Smrg#else 4348d522f475Smrg utmp.ut_time = time((time_t *) 0); 4349d522f475Smrg#endif 4350d522f475Smrg 4351d522f475Smrg /* write out the entry */ 4352d522f475Smrg if (!resource.utmpInhibit) { 4353d522f475Smrg errno = 0; 4354d522f475Smrg call_pututline(&utmp); 43550bd37d32Smrg TRACE(("pututline: id %.*s, line %.*s, pid %ld, errno %d %s\n", 43560bd37d32Smrg (int) sizeof(utmp.ut_id), utmp.ut_id, 43570bd37d32Smrg (int) sizeof(utmp.ut_line), utmp.ut_line, 4358d522f475Smrg (long) utmp.ut_pid, 4359d522f475Smrg errno, (errno != 0) ? strerror(errno) : "")); 4360d522f475Smrg } 4361d522f475Smrg#ifdef WTMP 4362d522f475Smrg#if defined(WTMPX_FILE) && (defined(SVR4) || defined(__SCO__)) 4363d522f475Smrg if (xw->misc.login_shell) 4364d522f475Smrg updwtmpx(WTMPX_FILE, &utmp); 4365d522f475Smrg#elif defined(linux) && defined(__GLIBC__) && (__GLIBC__ >= 2) && !(defined(__powerpc__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)) 4366d522f475Smrg if (xw->misc.login_shell) 4367d522f475Smrg call_updwtmp(etc_wtmp, &utmp); 4368d522f475Smrg#else 4369d522f475Smrg if (xw->misc.login_shell && 4370d522f475Smrg (i = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 43710bd37d32Smrg IGNORE_RC(write(i, (char *) &utmp, sizeof(utmp))); 4372d522f475Smrg close(i); 4373d522f475Smrg } 4374d522f475Smrg#endif 4375d522f475Smrg#endif 4376d522f475Smrg /* close the file */ 4377d522f475Smrg (void) call_endutent(); 4378d522f475Smrg 4379d522f475Smrg#else /* USE_SYSV_UTMP */ 4380d522f475Smrg /* We can now get our ttyslot! We can also set the initial 4381d522f475Smrg * utmp entry. 4382d522f475Smrg */ 4383d522f475Smrg tslot = ttyslot(); 4384d522f475Smrg added_utmp_entry = False; 4385d522f475Smrg { 43860bd37d32Smrg if (tslot > 0 && OkPasswd(&pw) && !resource.utmpInhibit && 4387d522f475Smrg (i = open(etc_utmp, O_WRONLY)) >= 0) { 4388956cc18dSsnj memset(&utmp, 0, sizeof(utmp)); 4389894e0ac8Smrg copy_filled(utmp.ut_line, 4390894e0ac8Smrg my_pty_name(ttydev), 4391894e0ac8Smrg sizeof(utmp.ut_line)); 4392894e0ac8Smrg copy_filled(utmp.ut_name, login_name, 4393894e0ac8Smrg sizeof(utmp.ut_name)); 4394d522f475Smrg#ifdef HAVE_UTMP_UT_HOST 4395d522f475Smrg SetUtmpHost(utmp.ut_host, screen); 4396d522f475Smrg#endif 4397d522f475Smrg#ifdef HAVE_UTMP_UT_SYSLEN 4398d522f475Smrg SetUtmpSysLen(utmp); 4399d522f475Smrg#endif 4400d522f475Smrg 4401d522f475Smrg utmp.ut_time = time((time_t *) 0); 4402d522f475Smrg lseek(i, (long) (tslot * sizeof(utmp)), 0); 44030bd37d32Smrg IGNORE_RC(write(i, (char *) &utmp, sizeof(utmp))); 4404d522f475Smrg close(i); 4405d522f475Smrg added_utmp_entry = True; 4406d522f475Smrg#if defined(WTMP) 4407d522f475Smrg if (xw->misc.login_shell && 4408d522f475Smrg (i = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 4409d522f475Smrg int status; 4410d522f475Smrg status = write(i, (char *) &utmp, sizeof(utmp)); 4411d522f475Smrg status = close(i); 4412d522f475Smrg } 4413d522f475Smrg#elif defined(MNX_LASTLOG) 4414d522f475Smrg if (xw->misc.login_shell && 4415d522f475Smrg (i = open(_U_LASTLOG, O_WRONLY)) >= 0) { 4416d522f475Smrg lseek(i, (long) (screen->uid * 4417d522f475Smrg sizeof(utmp)), 0); 44180bd37d32Smrg IGNORE_RC(write(i, (char *) &utmp, sizeof(utmp))); 4419d522f475Smrg close(i); 4420d522f475Smrg } 4421d522f475Smrg#endif /* WTMP or MNX_LASTLOG */ 4422d522f475Smrg } else 4423d522f475Smrg tslot = -tslot; 4424d522f475Smrg } 4425d522f475Smrg 4426d522f475Smrg /* Let's pass our ttyslot to our parent so that it can 4427d522f475Smrg * clean up after us. 4428d522f475Smrg */ 4429d522f475Smrg#if OPT_PTY_HANDSHAKE 4430d522f475Smrg if (resource.ptyHandshake) { 4431d522f475Smrg handshake.tty_slot = tslot; 4432d522f475Smrg } 4433d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4434d522f475Smrg#endif /* USE_SYSV_UTMP */ 4435d522f475Smrg 4436d522f475Smrg#ifdef USE_LASTLOGX 4437d522f475Smrg if (xw->misc.login_shell) { 4438956cc18dSsnj memset(&lastlogx, 0, sizeof(lastlogx)); 4439d522f475Smrg (void) strncpy(lastlogx.ll_line, 4440d522f475Smrg my_pty_name(ttydev), 4441d522f475Smrg sizeof(lastlogx.ll_line)); 4442d522f475Smrg X_GETTIMEOFDAY(&lastlogx.ll_tv); 4443d522f475Smrg SetUtmpHost(lastlogx.ll_host, screen); 4444d522f475Smrg updlastlogx(_PATH_LASTLOGX, screen->uid, &lastlogx); 4445d522f475Smrg } 4446d522f475Smrg#endif 4447d522f475Smrg 4448d522f475Smrg#ifdef USE_LASTLOG 4449d522f475Smrg if (xw->misc.login_shell && 4450d522f475Smrg (i = open(etc_lastlog, O_WRONLY)) >= 0) { 4451d522f475Smrg size_t size = sizeof(struct lastlog); 44520bd37d32Smrg off_t offset = (off_t) (screen->uid * size); 4453d522f475Smrg 4454956cc18dSsnj memset(&lastlog, 0, size); 4455d522f475Smrg (void) strncpy(lastlog.ll_line, 4456d522f475Smrg my_pty_name(ttydev), 4457d522f475Smrg sizeof(lastlog.ll_line)); 4458d522f475Smrg SetUtmpHost(lastlog.ll_host, screen); 4459d522f475Smrg lastlog.ll_time = time((time_t *) 0); 4460d522f475Smrg if (lseek(i, offset, 0) != (off_t) (-1)) { 44610bd37d32Smrg IGNORE_RC(write(i, (char *) &lastlog, size)); 4462d522f475Smrg } 4463d522f475Smrg close(i); 4464d522f475Smrg } 4465d522f475Smrg#endif /* USE_LASTLOG */ 4466d522f475Smrg 4467d522f475Smrg#if defined(USE_UTMP_SETGID) 4468d522f475Smrg disableSetGid(); 4469d522f475Smrg TRACE_IDS; 4470d522f475Smrg#endif 4471d522f475Smrg 4472d522f475Smrg#if OPT_PTY_HANDSHAKE 4473d522f475Smrg /* Let our parent know that we set up our utmp entry 4474d522f475Smrg * so that it can clean up after us. 4475d522f475Smrg */ 4476d522f475Smrg if (resource.ptyHandshake) { 4477d522f475Smrg handshake.status = UTMP_ADDED; 4478d522f475Smrg handshake.error = 0; 44790bd37d32Smrg strncpy(handshake.buffer, ttydev, sizeof(handshake.buffer)); 4480d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 448120d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], (char *) &handshake, sizeof(handshake))); 4482d522f475Smrg } 4483d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4484d522f475Smrg#endif /* USE_UTEMPTER */ 4485d522f475Smrg#endif /* HAVE_UTMP */ 4486d522f475Smrg 448720d2c4d2Smrg IGNORE_RC(setgid(screen->gid)); 4488d522f475Smrg TRACE_IDS; 4489e0a2b6dfSmrg#ifdef HAVE_INITGROUPS 44900bd37d32Smrg if (geteuid() == 0 && OkPasswd(&pw)) { 44910bd37d32Smrg if (initgroups(login_name, pw.pw_gid)) { 4492d522f475Smrg perror("initgroups failed"); 4493d522f475Smrg SysError(ERROR_INIGROUPS); 4494d522f475Smrg } 4495d522f475Smrg } 4496d522f475Smrg#endif 4497d522f475Smrg if (setuid(screen->uid)) { 4498d522f475Smrg SysError(ERROR_SETUID); 4499d522f475Smrg } 4500d522f475Smrg TRACE_IDS; 4501d522f475Smrg#if OPT_PTY_HANDSHAKE 4502d522f475Smrg if (resource.ptyHandshake) { 4503d522f475Smrg /* mark the pipes as close on exec */ 45040bd37d32Smrg (void) fcntl(cp_pipe[1], F_SETFD, 1); 45050bd37d32Smrg (void) fcntl(pc_pipe[0], F_SETFD, 1); 4506d522f475Smrg 4507d522f475Smrg /* We are at the point where we are going to 4508d522f475Smrg * exec our shell (or whatever). Let our parent 4509d522f475Smrg * know we arrived safely. 4510d522f475Smrg */ 4511d522f475Smrg handshake.status = PTY_GOOD; 4512d522f475Smrg handshake.error = 0; 45130bd37d32Smrg (void) strncpy(handshake.buffer, ttydev, sizeof(handshake.buffer)); 4514d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 451520d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], 451620d2c4d2Smrg (const char *) &handshake, 451720d2c4d2Smrg sizeof(handshake))); 4518d522f475Smrg 4519d522f475Smrg if (resource.wait_for_map) { 452020d2c4d2Smrg i = (int) read(pc_pipe[0], (char *) &handshake, 452120d2c4d2Smrg sizeof(handshake)); 4522d522f475Smrg if (i != sizeof(handshake) || 4523d522f475Smrg handshake.status != PTY_EXEC) { 4524d522f475Smrg /* some very bad problem occurred */ 4525d522f475Smrg exit(ERROR_PTY_EXEC); 4526d522f475Smrg } 4527d522f475Smrg if (handshake.rows > 0 && handshake.cols > 0) { 4528d522f475Smrg TRACE(("handshake ttysize: %dx%d\n", 4529d522f475Smrg handshake.rows, handshake.cols)); 4530d522f475Smrg set_max_row(screen, handshake.rows); 4531d522f475Smrg set_max_col(screen, handshake.cols); 4532d522f475Smrg#ifdef TTYSIZE_STRUCT 4533d522f475Smrg got_handshake_size = True; 453420d2c4d2Smrg TTYSIZE_ROWS(ts) = (ttySize_t) MaxRows(screen); 453520d2c4d2Smrg TTYSIZE_COLS(ts) = (ttySize_t) MaxCols(screen); 4536d522f475Smrg#if defined(USE_STRUCT_WINSIZE) 453720d2c4d2Smrg ts.ws_xpixel = (ttySize_t) FullWidth(screen); 453820d2c4d2Smrg ts.ws_ypixel = (ttySize_t) FullHeight(screen); 4539d522f475Smrg#endif 4540d522f475Smrg#endif /* TTYSIZE_STRUCT */ 4541d522f475Smrg } 4542d522f475Smrg } 4543d522f475Smrg } 4544d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4545d522f475Smrg 4546d522f475Smrg#ifdef USE_SYSV_ENVVARS 4547d522f475Smrg { 4548d522f475Smrg char numbuf[12]; 4549d522f475Smrg sprintf(numbuf, "%d", MaxCols(screen)); 4550d522f475Smrg xtermSetenv("COLUMNS", numbuf); 4551d522f475Smrg sprintf(numbuf, "%d", MaxRows(screen)); 4552d522f475Smrg xtermSetenv("LINES", numbuf); 4553d522f475Smrg } 4554d522f475Smrg#ifdef HAVE_UTMP 45550bd37d32Smrg if (OkPasswd(&pw)) { /* SVR4 doesn't provide these */ 4556d522f475Smrg if (!x_getenv("HOME")) 45570bd37d32Smrg xtermSetenv("HOME", pw.pw_dir); 4558d522f475Smrg if (!x_getenv("SHELL")) 45590bd37d32Smrg xtermSetenv("SHELL", pw.pw_shell); 4560d522f475Smrg } 4561d522f475Smrg#endif /* HAVE_UTMP */ 4562d522f475Smrg#ifdef OWN_TERMINFO_DIR 4563d522f475Smrg xtermSetenv("TERMINFO", OWN_TERMINFO_DIR); 4564d522f475Smrg#endif 4565d522f475Smrg#else /* USE_SYSV_ENVVARS */ 456620d2c4d2Smrg if (*(newtc = get_tcap_buffer(xw)) != '\0') { 456720d2c4d2Smrg resize_termcap(xw); 456820d2c4d2Smrg if (xw->misc.titeInhibit && !xw->misc.tiXtraScroll) { 456920d2c4d2Smrg remove_termcap_entry(newtc, "ti="); 457020d2c4d2Smrg remove_termcap_entry(newtc, "te="); 457120d2c4d2Smrg } 457220d2c4d2Smrg /* 457320d2c4d2Smrg * work around broken termcap entries */ 457420d2c4d2Smrg if (resource.useInsertMode) { 457520d2c4d2Smrg remove_termcap_entry(newtc, "ic="); 457620d2c4d2Smrg /* don't get duplicates */ 457720d2c4d2Smrg remove_termcap_entry(newtc, "im="); 457820d2c4d2Smrg remove_termcap_entry(newtc, "ei="); 457920d2c4d2Smrg remove_termcap_entry(newtc, "mi"); 458020d2c4d2Smrg if (*newtc) 458120d2c4d2Smrg strcat(newtc, ":im=\\E[4h:ei=\\E[4l:mi:"); 458220d2c4d2Smrg } 458320d2c4d2Smrg if (*newtc) { 4584d522f475Smrg#if OPT_INITIAL_ERASE 458520d2c4d2Smrg unsigned len; 458620d2c4d2Smrg remove_termcap_entry(newtc, TERMCAP_ERASE "="); 458720d2c4d2Smrg len = (unsigned) strlen(newtc); 458820d2c4d2Smrg if (len != 0 && newtc[len - 1] == ':') 458920d2c4d2Smrg len--; 459020d2c4d2Smrg sprintf(newtc + len, ":%s=\\%03o:", 459120d2c4d2Smrg TERMCAP_ERASE, 459220d2c4d2Smrg CharOf(initial_erase)); 459320d2c4d2Smrg#endif 459420d2c4d2Smrg xtermSetenv("TERMCAP", newtc); 459520d2c4d2Smrg } 4596d522f475Smrg } 4597d522f475Smrg#endif /* USE_SYSV_ENVVARS */ 4598d522f475Smrg 4599d522f475Smrg#if OPT_PTY_HANDSHAKE 4600d522f475Smrg /* 4601d522f475Smrg * Need to reset after all the ioctl bashing we did above. 4602d522f475Smrg * 4603d522f475Smrg * If we expect the waitForMap logic to set the handshake-size, 4604d522f475Smrg * use that to prevent races. 4605d522f475Smrg */ 4606d522f475Smrg if (resource.ptyHandshake 4607d522f475Smrg && resource.ptySttySize 4608d522f475Smrg && (got_handshake_size || !resource.wait_for_map0)) { 4609d522f475Smrg#ifdef TTYSIZE_STRUCT 461020d2c4d2Smrg TRACE_RC(i, SET_TTYSIZE(0, ts)); 4611d522f475Smrg TRACE(("ptyHandshake SET_TTYSIZE %dx%d return %d\n", 4612d522f475Smrg TTYSIZE_ROWS(ts), 4613d522f475Smrg TTYSIZE_COLS(ts), i)); 4614d522f475Smrg#endif /* TTYSIZE_STRUCT */ 4615d522f475Smrg } 4616d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4617d522f475Smrg signal(SIGHUP, SIG_DFL); 4618d522f475Smrg 46190bd37d32Smrg /* 4620e0a2b6dfSmrg * If we have an explicit shell to run, make that set $SHELL. 4621e0a2b6dfSmrg * Next, allow an existing setting of $SHELL, for absolute paths. 46220bd37d32Smrg * Otherwise, if $SHELL is not set, determine it from the user's 46230bd37d32Smrg * password information, if possible. 46240bd37d32Smrg * 46250bd37d32Smrg * Incidentally, our setting of $SHELL tells luit to use that 46260bd37d32Smrg * program rather than choosing between $SHELL and "/bin/sh". 46270bd37d32Smrg */ 4628e0a2b6dfSmrg if (validShell(explicit_shname)) { 4629e0a2b6dfSmrg xtermSetenv("SHELL", explicit_shname); 4630e0a2b6dfSmrg } else if (validProgram(shell_path = x_getenv("SHELL"))) { 4631e0a2b6dfSmrg if (!validShell(shell_path)) { 4632e0a2b6dfSmrg xtermUnsetenv("SHELL"); 4633d522f475Smrg } 4634e0a2b6dfSmrg } else if ((!OkPasswd(&pw) && !x_getpwuid(screen->uid, &pw)) 4635e0a2b6dfSmrg || *(shell_path = x_strdup(pw.pw_shell)) == 0) { 4636e0a2b6dfSmrg shell_path = resetShell(shell_path); 4637e0a2b6dfSmrg } else if (validShell(shell_path)) { 4638e0a2b6dfSmrg xtermSetenv("SHELL", shell_path); 4639d522f475Smrg } else { 4640e0a2b6dfSmrg shell_path = resetShell(shell_path); 4641d522f475Smrg } 4642e0a2b6dfSmrg 4643e0a2b6dfSmrg /* 4644e0a2b6dfSmrg * Set $XTERM_SHELL, which is not necessarily a valid shell, but 4645e0a2b6dfSmrg * is executable. 4646e0a2b6dfSmrg */ 4647e0a2b6dfSmrg if (validProgram(explicit_shname)) { 4648e0a2b6dfSmrg shell_path = explicit_shname; 4649e0a2b6dfSmrg } else if (shell_path == 0) { 4650e0a2b6dfSmrg /* this could happen if the explicit shname lost a race */ 4651e0a2b6dfSmrg shell_path = resetShell(shell_path); 46520bd37d32Smrg } 46530bd37d32Smrg xtermSetenv("XTERM_SHELL", shell_path); 4654d522f475Smrg 46550bd37d32Smrg shname = x_basename(shell_path); 46560bd37d32Smrg TRACE(("shell path '%s' leaf '%s'\n", shell_path, shname)); 4657d522f475Smrg 4658d522f475Smrg#if OPT_LUIT_PROG 4659d522f475Smrg /* 4660d522f475Smrg * Use two copies of command_to_exec, in case luit is not actually 4661d522f475Smrg * there, or refuses to run. In that case we will fall-through to 4662d522f475Smrg * to command that the user gave anyway. 4663d522f475Smrg */ 46642eaa94a1Schristos if (command_to_exec_with_luit && command_to_exec) { 46650bd37d32Smrg char *myShell = xtermFindShell(*command_to_exec_with_luit, False); 46660bd37d32Smrg xtermSetenv("XTERM_SHELL", myShell); 46670bd37d32Smrg free(myShell); 46680bd37d32Smrg TRACE_ARGV("spawning luit command", command_to_exec_with_luit); 4669d522f475Smrg execvp(*command_to_exec_with_luit, command_to_exec_with_luit); 46700bd37d32Smrg xtermPerror("Can't execvp %s", *command_to_exec_with_luit); 46710bd37d32Smrg xtermWarning("cannot support your locale.\n"); 4672d522f475Smrg } 4673d522f475Smrg#endif 4674d522f475Smrg if (command_to_exec) { 46750bd37d32Smrg char *myShell = xtermFindShell(*command_to_exec, False); 46760bd37d32Smrg xtermSetenv("XTERM_SHELL", myShell); 46770bd37d32Smrg free(myShell); 46780bd37d32Smrg TRACE_ARGV("spawning command", command_to_exec); 4679d522f475Smrg execvp(*command_to_exec, command_to_exec); 4680d522f475Smrg if (command_to_exec[1] == 0) 46810bd37d32Smrg execlp(shell_path, shname, "-c", command_to_exec[0], 46820bd37d32Smrg (void *) 0); 46830bd37d32Smrg xtermPerror("Can't execvp %s", *command_to_exec); 4684d522f475Smrg } 4685d522f475Smrg#ifdef USE_SYSV_SIGHUP 4686d522f475Smrg /* fix pts sh hanging around */ 4687d522f475Smrg signal(SIGHUP, SIG_DFL); 4688d522f475Smrg#endif 4689d522f475Smrg 4690d522f475Smrg shname_minus = CastMallocN(char, strlen(shname) + 2); 4691d522f475Smrg (void) strcpy(shname_minus, "-"); 4692d522f475Smrg (void) strcat(shname_minus, shname); 4693d522f475Smrg#ifndef TERMIO_STRUCT 46940bd37d32Smrg ldisc = (!XStrCmp("csh", shname + strlen(shname) - 3) 46950bd37d32Smrg ? NTTYDISC 46960bd37d32Smrg : 0); 4697d522f475Smrg ioctl(0, TIOCSETD, (char *) &ldisc); 4698d522f475Smrg#endif /* !TERMIO_STRUCT */ 4699d522f475Smrg 4700d522f475Smrg#ifdef USE_LOGIN_DASH_P 47010bd37d32Smrg if (xw->misc.login_shell && OkPasswd(&pw) && added_utmp_entry) 4702d522f475Smrg execl(bin_login, "login", "-p", "-f", login_name, (void *) 0); 4703d522f475Smrg#endif 47042eaa94a1Schristos 47052eaa94a1Schristos#if OPT_LUIT_PROG 47062eaa94a1Schristos if (command_to_exec_with_luit) { 47072eaa94a1Schristos if (xw->misc.login_shell) { 47080bd37d32Smrg char *params[4]; 47090bd37d32Smrg params[0] = x_strdup("-argv0"); 47100bd37d32Smrg params[1] = shname_minus; 47110bd37d32Smrg params[2] = NULL; 47120bd37d32Smrg x_appendargv(command_to_exec_with_luit 47130bd37d32Smrg + command_length_with_luit, 47140bd37d32Smrg params); 47152eaa94a1Schristos } 47160bd37d32Smrg TRACE_ARGV("final luit command", command_to_exec_with_luit); 47172eaa94a1Schristos execvp(*command_to_exec_with_luit, command_to_exec_with_luit); 47182eaa94a1Schristos /* Exec failed. */ 47190bd37d32Smrg xtermPerror("Can't execvp %s", *command_to_exec_with_luit); 47202eaa94a1Schristos } 47212eaa94a1Schristos#endif 47220bd37d32Smrg execlp(shell_path, 4723d522f475Smrg (xw->misc.login_shell ? shname_minus : shname), 4724d522f475Smrg (void *) 0); 4725d522f475Smrg 4726d522f475Smrg /* Exec failed. */ 47270bd37d32Smrg xtermPerror("Could not exec %s", shell_path); 472820d2c4d2Smrg IGNORE_RC(sleep(5)); 47290bd37d32Smrg free(shell_path); 4730d522f475Smrg exit(ERROR_EXEC); 4731d522f475Smrg } 4732d522f475Smrg /* end if in child after fork */ 4733d522f475Smrg#if OPT_PTY_HANDSHAKE 4734d522f475Smrg if (resource.ptyHandshake) { 4735d522f475Smrg /* Parent process. Let's handle handshaked requests to our 4736d522f475Smrg * child process. 4737d522f475Smrg */ 4738d522f475Smrg 4739d522f475Smrg /* close childs's sides of the pipes */ 4740d522f475Smrg close(cp_pipe[1]); 4741d522f475Smrg close(pc_pipe[0]); 4742d522f475Smrg 4743d522f475Smrg for (done = 0; !done;) { 4744d522f475Smrg if (read(cp_pipe[0], 4745d522f475Smrg (char *) &handshake, 4746d522f475Smrg sizeof(handshake)) <= 0) { 4747d522f475Smrg /* Our child is done talking to us. If it terminated 4748d522f475Smrg * due to an error, we will catch the death of child 4749d522f475Smrg * and clean up. 4750d522f475Smrg */ 4751d522f475Smrg break; 4752d522f475Smrg } 4753d522f475Smrg 4754d522f475Smrg TRACE_HANDSHAKE("read", &handshake); 4755d522f475Smrg switch (handshake.status) { 4756d522f475Smrg case PTY_GOOD: 4757d522f475Smrg /* Success! Let's free up resources and 4758d522f475Smrg * continue. 4759d522f475Smrg */ 4760d522f475Smrg done = 1; 4761d522f475Smrg break; 4762d522f475Smrg 4763d522f475Smrg case PTY_BAD: 4764d522f475Smrg /* The open of the pty failed! Let's get 4765d522f475Smrg * another one. 4766d522f475Smrg */ 476720d2c4d2Smrg IGNORE_RC(close(screen->respond)); 4768d522f475Smrg if (get_pty(&screen->respond, XDisplayString(screen->display))) { 4769d522f475Smrg /* no more ptys! */ 47700bd37d32Smrg xtermPerror("child process can find no available ptys"); 4771d522f475Smrg handshake.status = PTY_NOMORE; 4772d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 477320d2c4d2Smrg IGNORE_RC(write(pc_pipe[1], 477420d2c4d2Smrg (const char *) &handshake, 477520d2c4d2Smrg sizeof(handshake))); 4776d522f475Smrg exit(ERROR_PTYS); 4777d522f475Smrg } 4778d522f475Smrg handshake.status = PTY_NEW; 47790bd37d32Smrg (void) strncpy(handshake.buffer, ttydev, sizeof(handshake.buffer)); 4780d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 478120d2c4d2Smrg IGNORE_RC(write(pc_pipe[1], 478220d2c4d2Smrg (const char *) &handshake, 478320d2c4d2Smrg sizeof(handshake))); 4784d522f475Smrg break; 4785d522f475Smrg 4786d522f475Smrg case PTY_FATALERROR: 4787d522f475Smrg errno = handshake.error; 4788d522f475Smrg close(cp_pipe[0]); 4789d522f475Smrg close(pc_pipe[1]); 4790d522f475Smrg SysError(handshake.fatal_error); 4791d522f475Smrg /*NOTREACHED */ 4792d522f475Smrg 4793d522f475Smrg case UTMP_ADDED: 4794d522f475Smrg /* The utmp entry was set by our slave. Remember 4795d522f475Smrg * this so that we can reset it later. 4796d522f475Smrg */ 4797d522f475Smrg added_utmp_entry = True; 4798d522f475Smrg#ifndef USE_SYSV_UTMP 4799d522f475Smrg tslot = handshake.tty_slot; 4800d522f475Smrg#endif /* USE_SYSV_UTMP */ 4801d522f475Smrg free(ttydev); 4802d522f475Smrg ttydev = x_strdup(handshake.buffer); 4803d522f475Smrg break; 4804d522f475Smrg case PTY_NEW: 4805d522f475Smrg case PTY_NOMORE: 4806d522f475Smrg case UTMP_TTYSLOT: 4807d522f475Smrg case PTY_EXEC: 4808d522f475Smrg default: 48090bd37d32Smrg xtermWarning("unexpected handshake status %d\n", 48100bd37d32Smrg (int) handshake.status); 4811d522f475Smrg } 4812d522f475Smrg } 4813d522f475Smrg /* close our sides of the pipes */ 4814d522f475Smrg if (!resource.wait_for_map) { 4815d522f475Smrg close(cp_pipe[0]); 4816d522f475Smrg close(pc_pipe[1]); 4817d522f475Smrg } 4818d522f475Smrg } 4819d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4820d522f475Smrg } 4821d522f475Smrg 4822d522f475Smrg /* end if no slave */ 4823d522f475Smrg /* 4824d522f475Smrg * still in parent (xterm process) 4825d522f475Smrg */ 4826d522f475Smrg#ifdef USE_SYSV_SIGHUP 4827d522f475Smrg /* hung sh problem? */ 4828d522f475Smrg signal(SIGHUP, SIG_DFL); 4829d522f475Smrg#else 4830d522f475Smrg signal(SIGHUP, SIG_IGN); 4831d522f475Smrg#endif 4832d522f475Smrg 4833d522f475Smrg/* 4834d522f475Smrg * Unfortunately, System V seems to have trouble divorcing the child process 4835d522f475Smrg * from the process group of xterm. This is a problem because hitting the 4836d522f475Smrg * INTR or QUIT characters on the keyboard will cause xterm to go away if we 4837d522f475Smrg * don't ignore the signals. This is annoying. 4838d522f475Smrg */ 4839d522f475Smrg 4840d522f475Smrg#if defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP) 4841d522f475Smrg signal(SIGINT, SIG_IGN); 4842d522f475Smrg 4843d522f475Smrg#ifndef SYSV 4844d522f475Smrg /* hung shell problem */ 4845d522f475Smrg signal(SIGQUIT, SIG_IGN); 4846d522f475Smrg#endif 4847d522f475Smrg signal(SIGTERM, SIG_IGN); 4848d522f475Smrg#elif defined(SYSV) || defined(__osf__) 4849d522f475Smrg /* if we were spawned by a jobcontrol smart shell (like ksh or csh), 4850d522f475Smrg * then our pgrp and pid will be the same. If we were spawned by 4851d522f475Smrg * a jobcontrol dumb shell (like /bin/sh), then we will be in our 4852d522f475Smrg * parent's pgrp, and we must ignore keyboard signals, or we will 4853d522f475Smrg * tank on everything. 4854d522f475Smrg */ 4855d522f475Smrg if (getpid() == getpgrp()) { 4856d522f475Smrg (void) signal(SIGINT, Exit); 4857d522f475Smrg (void) signal(SIGQUIT, Exit); 4858d522f475Smrg (void) signal(SIGTERM, Exit); 4859d522f475Smrg } else { 4860d522f475Smrg (void) signal(SIGINT, SIG_IGN); 4861d522f475Smrg (void) signal(SIGQUIT, SIG_IGN); 4862d522f475Smrg (void) signal(SIGTERM, SIG_IGN); 4863d522f475Smrg } 4864d522f475Smrg (void) signal(SIGPIPE, Exit); 4865d522f475Smrg#else /* SYSV */ 4866d522f475Smrg signal(SIGINT, Exit); 4867d522f475Smrg signal(SIGQUIT, Exit); 4868d522f475Smrg signal(SIGTERM, Exit); 4869d522f475Smrg signal(SIGPIPE, Exit); 4870d522f475Smrg#endif /* USE_SYSV_SIGNALS and not SIGTSTP */ 48710bd37d32Smrg#ifdef NO_LEAKS 48720bd37d32Smrg if (ok_termcap != True) 48730bd37d32Smrg free(TermName); 48740bd37d32Smrg#endif 4875d522f475Smrg 4876d522f475Smrg return 0; 4877d522f475Smrg} /* end spawnXTerm */ 4878d522f475Smrg 48790bd37d32Smrgvoid 4880d522f475SmrgExit(int n) 4881d522f475Smrg{ 488220d2c4d2Smrg XtermWidget xw = term; 488320d2c4d2Smrg TScreen *screen = TScreenOf(xw); 4884d522f475Smrg 4885d522f475Smrg#ifdef USE_UTEMPTER 48860bd37d32Smrg DEBUG_MSG("handle:Exit USE_UTEMPTER\n"); 48870bd37d32Smrg if (!resource.utmpInhibit && added_utmp_entry) { 48880bd37d32Smrg TRACE(("...calling removeFromUtmp\n")); 4889d522f475Smrg removeFromUtmp(); 48900bd37d32Smrg } 4891d522f475Smrg#elif defined(HAVE_UTMP) 4892d522f475Smrg#ifdef USE_SYSV_UTMP 4893d522f475Smrg struct UTMP_STR utmp; 4894d522f475Smrg struct UTMP_STR *utptr; 4895d522f475Smrg 48960bd37d32Smrg DEBUG_MSG("handle:Exit USE_SYSV_UTMP\n"); 4897d522f475Smrg /* don't do this more than once */ 48980bd37d32Smrg if (xterm_exiting) { 48990bd37d32Smrg exit(n); 49000bd37d32Smrg } 4901d522f475Smrg xterm_exiting = True; 4902d522f475Smrg 4903d522f475Smrg#ifdef PUCC_PTYD 4904d522f475Smrg closepty(ttydev, ptydev, (resource.utmpInhibit ? OPTY_NOP : OPTY_LOGIN), screen->respond); 4905d522f475Smrg#endif /* PUCC_PTYD */ 4906d522f475Smrg 4907d522f475Smrg /* cleanup the utmp entry we forged earlier */ 4908d522f475Smrg if (!resource.utmpInhibit 4909d522f475Smrg#if OPT_PTY_HANDSHAKE /* without handshake, no way to know */ 4910d522f475Smrg && (resource.ptyHandshake && added_utmp_entry) 4911d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4912d522f475Smrg ) { 4913d522f475Smrg#if defined(USE_UTMP_SETGID) 4914d522f475Smrg setEffectiveGroup(save_egid); 4915d522f475Smrg TRACE_IDS; 4916d522f475Smrg#endif 4917d522f475Smrg init_utmp(USER_PROCESS, &utmp); 4918d522f475Smrg (void) call_setutent(); 4919d522f475Smrg 4920d522f475Smrg /* 4921d522f475Smrg * We could use getutline() if we didn't support old systems. 4922d522f475Smrg */ 4923d522f475Smrg while ((utptr = find_utmp(&utmp)) != 0) { 4924d522f475Smrg if (utptr->ut_pid == screen->pid) { 4925d522f475Smrg utptr->ut_type = DEAD_PROCESS; 4926d522f475Smrg#if defined(HAVE_UTMP_UT_XTIME) 4927d522f475Smrg#if defined(HAVE_UTMP_UT_SESSION) 4928d522f475Smrg utptr->ut_session = getsid(0); 4929d522f475Smrg#endif 4930d522f475Smrg utptr->ut_xtime = time((time_t *) 0); 4931d522f475Smrg utptr->ut_tv.tv_usec = 0; 4932d522f475Smrg#else 4933d522f475Smrg *utptr->ut_user = 0; 4934d522f475Smrg utptr->ut_time = time((time_t *) 0); 4935d522f475Smrg#endif 4936d522f475Smrg (void) call_pututline(utptr); 4937d522f475Smrg#ifdef WTMP 4938d522f475Smrg#if defined(WTMPX_FILE) && (defined(SVR4) || defined(__SCO__)) 493920d2c4d2Smrg if (xw->misc.login_shell) 4940d522f475Smrg updwtmpx(WTMPX_FILE, utptr); 4941d522f475Smrg#elif defined(linux) && defined(__GLIBC__) && (__GLIBC__ >= 2) && !(defined(__powerpc__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)) 4942894e0ac8Smrg copy_filled(utmp.ut_line, utptr->ut_line, sizeof(utmp.ut_line)); 494320d2c4d2Smrg if (xw->misc.login_shell) 4944d522f475Smrg call_updwtmp(etc_wtmp, utptr); 4945d522f475Smrg#else 4946d522f475Smrg /* set wtmp entry if wtmp file exists */ 494720d2c4d2Smrg if (xw->misc.login_shell) { 4948d522f475Smrg int fd; 4949d522f475Smrg if ((fd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 49500bd37d32Smrg IGNORE_RC(write(fd, utptr, sizeof(*utptr))); 4951d522f475Smrg close(fd); 4952d522f475Smrg } 4953d522f475Smrg } 4954d522f475Smrg#endif 4955d522f475Smrg#endif 4956d522f475Smrg break; 4957d522f475Smrg } 4958d522f475Smrg memset(utptr, 0, sizeof(*utptr)); /* keep searching */ 4959d522f475Smrg } 4960d522f475Smrg (void) call_endutent(); 4961d522f475Smrg#ifdef USE_UTMP_SETGID 4962d522f475Smrg disableSetGid(); 4963d522f475Smrg TRACE_IDS; 4964d522f475Smrg#endif 4965d522f475Smrg } 4966d522f475Smrg#else /* not USE_SYSV_UTMP */ 4967d522f475Smrg int wfd; 4968d522f475Smrg struct utmp utmp; 4969d522f475Smrg 49700bd37d32Smrg DEBUG_MSG("handle:Exit !USE_SYSV_UTMP\n"); 4971d522f475Smrg if (!resource.utmpInhibit && added_utmp_entry && 4972d522f475Smrg (am_slave < 0 && tslot > 0)) { 4973d522f475Smrg#if defined(USE_UTMP_SETGID) 4974d522f475Smrg setEffectiveGroup(save_egid); 4975d522f475Smrg TRACE_IDS; 4976d522f475Smrg#endif 4977d522f475Smrg if ((wfd = open(etc_utmp, O_WRONLY)) >= 0) { 4978956cc18dSsnj memset(&utmp, 0, sizeof(utmp)); 4979d522f475Smrg lseek(wfd, (long) (tslot * sizeof(utmp)), 0); 49800bd37d32Smrg IGNORE_RC(write(wfd, (char *) &utmp, sizeof(utmp))); 4981d522f475Smrg close(wfd); 4982d522f475Smrg } 4983d522f475Smrg#ifdef WTMP 498420d2c4d2Smrg if (xw->misc.login_shell && 4985d522f475Smrg (wfd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 4986894e0ac8Smrg copy_filled(utmp.ut_line, 4987894e0ac8Smrg my_pty_name(ttydev), 4988894e0ac8Smrg sizeof(utmp.ut_line)); 4989d522f475Smrg utmp.ut_time = time((time_t *) 0); 49900bd37d32Smrg IGNORE_RC(write(wfd, (char *) &utmp, sizeof(utmp))); 4991d522f475Smrg close(wfd); 4992d522f475Smrg } 4993d522f475Smrg#endif /* WTMP */ 4994d522f475Smrg#ifdef USE_UTMP_SETGID 4995d522f475Smrg disableSetGid(); 4996d522f475Smrg TRACE_IDS; 4997d522f475Smrg#endif 4998d522f475Smrg } 4999d522f475Smrg#endif /* USE_SYSV_UTMP */ 5000d522f475Smrg#endif /* HAVE_UTMP */ 5001d522f475Smrg 5002e0a2b6dfSmrg cleanup_colored_cursor(); 5003e0a2b6dfSmrg 5004d522f475Smrg /* 5005d522f475Smrg * Flush pending data before releasing ownership, so nobody else can write 5006d522f475Smrg * in the middle of the data. 5007d522f475Smrg */ 5008d522f475Smrg ttyFlush(screen->respond); 5009d522f475Smrg 5010e39b573cSmrg#ifdef USE_PTY_SEARCH 5011d522f475Smrg if (am_slave < 0) { 5012d522f475Smrg TRACE_IDS; 5013d522f475Smrg /* restore ownership of tty and pty */ 5014d522f475Smrg set_owner(ttydev, 0, 0, 0666U); 5015d522f475Smrg#if (defined(USE_PTY_DEVICE) && !defined(__sgi) && !defined(__hpux)) 5016d522f475Smrg set_owner(ptydev, 0, 0, 0666U); 5017d522f475Smrg#endif 5018d522f475Smrg } 5019e39b573cSmrg#endif 5020d522f475Smrg 5021d522f475Smrg /* 50220bd37d32Smrg * Close after releasing ownership to avoid race condition: other programs 5023d522f475Smrg * grabbing it, and *then* having us release ownership.... 5024d522f475Smrg */ 5025d522f475Smrg close(screen->respond); /* close explicitly to avoid race with slave side */ 5026d522f475Smrg#ifdef ALLOWLOGGING 5027d522f475Smrg if (screen->logging) 502820d2c4d2Smrg CloseLog(xw); 5029d522f475Smrg#endif 5030d522f475Smrg 5031e39b573cSmrg xtermPrintOnXError(xw, n); 5032e39b573cSmrg 5033d522f475Smrg#ifdef NO_LEAKS 5034d522f475Smrg if (n == 0) { 50350bd37d32Smrg Display *dpy = TScreenOf(xw)->display; 50360bd37d32Smrg 5037d522f475Smrg TRACE(("Freeing memory leaks\n")); 5038d522f475Smrg 50390bd37d32Smrg if (toplevel) { 50400bd37d32Smrg XtDestroyWidget(toplevel); 50410bd37d32Smrg TRACE(("destroyed top-level widget\n")); 50420bd37d32Smrg } 50430bd37d32Smrg sortedOpts(0, 0, 0); 50440bd37d32Smrg noleaks_charproc(); 50450bd37d32Smrg noleaks_ptydata(); 5046894e0ac8Smrg#if OPT_GRAPHICS 5047894e0ac8Smrg noleaks_graphics(); 5048894e0ac8Smrg#endif 5049d522f475Smrg#if OPT_WIDE_CHARS 50500bd37d32Smrg noleaks_CharacterClass(); 5051d522f475Smrg#endif 50520bd37d32Smrg /* XrmSetDatabase(dpy, 0); increases leaks ;-) */ 50530bd37d32Smrg XtCloseDisplay(dpy); 50540bd37d32Smrg XtDestroyApplicationContext(app_con); 50550bd37d32Smrg xtermCloseSession(); 50560bd37d32Smrg TRACE(("closed display\n")); 50570bd37d32Smrg 505820d2c4d2Smrg TRACE_CLOSE(); 5059d522f475Smrg } 5060d522f475Smrg#endif 5061d522f475Smrg 5062d522f475Smrg exit(n); 5063d522f475Smrg} 5064d522f475Smrg 5065d522f475Smrg/* ARGSUSED */ 5066d522f475Smrgstatic void 506720d2c4d2Smrgresize_termcap(XtermWidget xw) 5068d522f475Smrg{ 506920d2c4d2Smrg char *newtc = get_tcap_buffer(xw); 507020d2c4d2Smrg 5071d522f475Smrg#ifndef USE_SYSV_ENVVARS 5072d522f475Smrg if (!TEK4014_ACTIVE(xw) && *newtc) { 5073d522f475Smrg TScreen *screen = TScreenOf(xw); 5074d522f475Smrg char *ptr1, *ptr2; 5075d522f475Smrg size_t i; 5076d522f475Smrg int li_first = 0; 5077d522f475Smrg char *temp; 5078d522f475Smrg char oldtc[TERMCAP_SIZE]; 5079d522f475Smrg 5080d522f475Smrg strcpy(oldtc, newtc); 5081d522f475Smrg TRACE(("resize %s\n", oldtc)); 5082d522f475Smrg if ((ptr1 = x_strindex(oldtc, "co#")) == NULL) { 5083d522f475Smrg strcat(oldtc, "co#80:"); 5084d522f475Smrg ptr1 = x_strindex(oldtc, "co#"); 5085d522f475Smrg } 5086d522f475Smrg if ((ptr2 = x_strindex(oldtc, "li#")) == NULL) { 5087d522f475Smrg strcat(oldtc, "li#24:"); 5088d522f475Smrg ptr2 = x_strindex(oldtc, "li#"); 5089d522f475Smrg } 5090d522f475Smrg if (ptr1 > ptr2) { 5091d522f475Smrg li_first++; 5092d522f475Smrg temp = ptr1; 5093d522f475Smrg ptr1 = ptr2; 5094d522f475Smrg ptr2 = temp; 5095d522f475Smrg } 5096d522f475Smrg ptr1 += 3; 5097d522f475Smrg ptr2 += 3; 5098956cc18dSsnj strncpy(newtc, oldtc, i = (size_t) (ptr1 - oldtc)); 5099d522f475Smrg temp = newtc + i; 5100d522f475Smrg sprintf(temp, "%d", (li_first 5101d522f475Smrg ? MaxRows(screen) 5102d522f475Smrg : MaxCols(screen))); 5103d522f475Smrg temp += strlen(temp); 51040bd37d32Smrg if ((ptr1 = strchr(ptr1, ':')) != 0 && (ptr1 < ptr2)) { 51050bd37d32Smrg strncpy(temp, ptr1, i = (size_t) (ptr2 - ptr1)); 51060bd37d32Smrg temp += i; 51070bd37d32Smrg sprintf(temp, "%d", (li_first 51080bd37d32Smrg ? MaxCols(screen) 51090bd37d32Smrg : MaxRows(screen))); 51100bd37d32Smrg if ((ptr2 = strchr(ptr2, ':')) != 0) { 51110bd37d32Smrg strcat(temp, ptr2); 51120bd37d32Smrg } 51130bd37d32Smrg } 5114d522f475Smrg TRACE((" ==> %s\n", newtc)); 5115d522f475Smrg TRACE((" new size %dx%d\n", MaxRows(screen), MaxCols(screen))); 5116d522f475Smrg } 5117d522f475Smrg#endif /* USE_SYSV_ENVVARS */ 5118d522f475Smrg} 5119d522f475Smrg 5120d522f475Smrg#endif /* ! VMS */ 5121d522f475Smrg 5122d522f475Smrg/* 5123d522f475Smrg * Does a non-blocking wait for a child process. If the system 5124d522f475Smrg * doesn't support non-blocking wait, do nothing. 5125d522f475Smrg * Returns the pid of the child, or 0 or -1 if none or error. 5126d522f475Smrg */ 5127d522f475Smrgint 5128d522f475Smrgnonblocking_wait(void) 5129d522f475Smrg{ 5130d522f475Smrg#ifdef USE_POSIX_WAIT 5131d522f475Smrg pid_t pid; 5132d522f475Smrg 5133d522f475Smrg pid = waitpid(-1, NULL, WNOHANG); 5134d522f475Smrg#elif defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP)) 5135d522f475Smrg /* cannot do non-blocking wait */ 5136d522f475Smrg int pid = 0; 5137d522f475Smrg#else /* defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP)) */ 5138d522f475Smrg#if defined(Lynx) 5139d522f475Smrg int status; 5140d522f475Smrg#else 5141d522f475Smrg union wait status; 5142d522f475Smrg#endif 5143d522f475Smrg int pid; 5144d522f475Smrg 5145d522f475Smrg pid = wait3(&status, WNOHANG, (struct rusage *) NULL); 5146d522f475Smrg#endif /* USE_POSIX_WAIT else */ 5147d522f475Smrg return pid; 5148d522f475Smrg} 5149d522f475Smrg 5150d522f475Smrg#ifndef VMS 5151d522f475Smrg 5152d522f475Smrg/* ARGSUSED */ 51530bd37d32Smrgstatic void 5154d522f475Smrgreapchild(int n GCC_UNUSED) 5155d522f475Smrg{ 5156d522f475Smrg int olderrno = errno; 5157d522f475Smrg int pid; 5158d522f475Smrg 51590bd37d32Smrg DEBUG_MSG("handle:reapchild\n"); 51600bd37d32Smrg 5161d522f475Smrg pid = wait(NULL); 5162d522f475Smrg 5163d522f475Smrg#ifdef USE_SYSV_SIGNALS 5164d522f475Smrg /* cannot re-enable signal before waiting for child 5165d522f475Smrg * because then SVR4 loops. Sigh. HP-UX 9.01 too. 5166d522f475Smrg */ 5167d522f475Smrg (void) signal(SIGCHLD, reapchild); 5168d522f475Smrg#endif 5169d522f475Smrg 5170d522f475Smrg do { 517120d2c4d2Smrg if (pid == TScreenOf(term)->pid) { 51720bd37d32Smrg DEBUG_MSG("Exiting\n"); 5173d522f475Smrg if (!hold_screen) 5174d522f475Smrg need_cleanup = True; 5175d522f475Smrg } 5176d522f475Smrg } while ((pid = nonblocking_wait()) > 0); 5177d522f475Smrg 5178d522f475Smrg errno = olderrno; 5179d522f475Smrg} 5180d522f475Smrg#endif /* !VMS */ 5181d522f475Smrg 5182d522f475Smrgstatic void 518320d2c4d2Smrgremove_termcap_entry(char *buf, const char *str) 5184d522f475Smrg{ 5185d522f475Smrg char *base = buf; 5186d522f475Smrg char *first = base; 5187d522f475Smrg int count = 0; 5188d522f475Smrg size_t len = strlen(str); 5189d522f475Smrg 5190d522f475Smrg TRACE(("*** remove_termcap_entry('%s', '%s')\n", str, buf)); 5191d522f475Smrg 5192d522f475Smrg while (*buf != 0) { 5193d522f475Smrg if (!count && !strncmp(buf, str, len)) { 5194d522f475Smrg while (*buf != 0) { 5195d522f475Smrg if (*buf == '\\') 5196d522f475Smrg buf++; 5197d522f475Smrg else if (*buf == ':') 5198d522f475Smrg break; 5199d522f475Smrg if (*buf != 0) 5200d522f475Smrg buf++; 5201d522f475Smrg } 52020bd37d32Smrg while ((*first++ = *buf++) != 0) { 52030bd37d32Smrg ; 52040bd37d32Smrg } 5205d522f475Smrg TRACE(("...removed_termcap_entry('%s', '%s')\n", str, base)); 5206d522f475Smrg return; 5207d522f475Smrg } else if (*buf == '\\') { 5208d522f475Smrg buf++; 5209d522f475Smrg } else if (*buf == ':') { 5210d522f475Smrg first = buf; 5211d522f475Smrg count = 0; 5212d522f475Smrg } else if (!isspace(CharOf(*buf))) { 5213d522f475Smrg count++; 5214d522f475Smrg } 5215d522f475Smrg if (*buf != 0) 5216d522f475Smrg buf++; 5217d522f475Smrg } 5218d522f475Smrg TRACE(("...cannot remove\n")); 5219d522f475Smrg} 5220d522f475Smrg 5221d522f475Smrg/* 5222d522f475Smrg * parse_tty_modes accepts lines of the following form: 5223d522f475Smrg * 5224d522f475Smrg * [SETTING] ... 5225d522f475Smrg * 5226d522f475Smrg * where setting consists of the words in the modelist followed by a character 5227d522f475Smrg * or ^char. 5228d522f475Smrg */ 5229d522f475Smrgstatic int 5230d522f475Smrgparse_tty_modes(char *s, struct _xttymodes *modelist) 5231d522f475Smrg{ 5232d522f475Smrg struct _xttymodes *mp; 5233d522f475Smrg int c; 5234d522f475Smrg int count = 0; 5235d522f475Smrg 5236d522f475Smrg TRACE(("parse_tty_modes\n")); 5237a1f3da82Smrg for (;;) { 5238d522f475Smrg size_t len; 5239d522f475Smrg 5240d522f475Smrg while (*s && isascii(CharOf(*s)) && isspace(CharOf(*s))) 5241d522f475Smrg s++; 5242d522f475Smrg if (!*s) 5243d522f475Smrg return count; 5244d522f475Smrg 5245d522f475Smrg for (len = 0; isalnum(CharOf(s[len])); ++len) ; 5246d522f475Smrg for (mp = modelist; mp->name; mp++) { 5247d522f475Smrg if (len == mp->len 5248d522f475Smrg && strncmp(s, mp->name, mp->len) == 0) 5249d522f475Smrg break; 5250d522f475Smrg } 5251d522f475Smrg if (!mp->name) 5252d522f475Smrg return -1; 5253d522f475Smrg 5254d522f475Smrg s += mp->len; 5255d522f475Smrg while (*s && isascii(CharOf(*s)) && isspace(CharOf(*s))) 5256d522f475Smrg s++; 5257d522f475Smrg if (!*s) 5258d522f475Smrg return -1; 5259d522f475Smrg 5260d522f475Smrg if ((c = decode_keyvalue(&s, False)) != -1) { 5261d522f475Smrg mp->value = c; 5262d522f475Smrg mp->set = 1; 5263d522f475Smrg count++; 5264d522f475Smrg TRACE(("...parsed #%d: %s=%#x\n", count, mp->name, c)); 5265d522f475Smrg } 5266d522f475Smrg } 5267d522f475Smrg} 5268d522f475Smrg 5269d522f475Smrg#ifndef VMS /* don't use pipes on OpenVMS */ 5270d522f475Smrgint 5271d522f475SmrgGetBytesAvailable(int fd) 5272d522f475Smrg{ 5273d522f475Smrg#if defined(FIONREAD) 5274d522f475Smrg int arg; 5275d522f475Smrg ioctl(fd, FIONREAD, (char *) &arg); 5276d522f475Smrg return (int) arg; 5277d522f475Smrg#elif defined(__CYGWIN__) 5278d522f475Smrg fd_set set; 527920d2c4d2Smrg struct timeval select_timeout = 5280d522f475Smrg {0, 0}; 5281d522f475Smrg 5282d522f475Smrg FD_ZERO(&set); 5283d522f475Smrg FD_SET(fd, &set); 528420d2c4d2Smrg if (Select(fd + 1, &set, NULL, NULL, &select_timeout) > 0) 5285d522f475Smrg return 1; 5286d522f475Smrg else 5287d522f475Smrg return 0; 5288d522f475Smrg#elif defined(FIORDCK) 5289d522f475Smrg return (ioctl(fd, FIORDCHK, NULL)); 5290d522f475Smrg#else /* !FIORDCK */ 5291d522f475Smrg struct pollfd pollfds[1]; 5292d522f475Smrg 5293d522f475Smrg pollfds[0].fd = fd; 5294d522f475Smrg pollfds[0].events = POLLIN; 5295d522f475Smrg return poll(pollfds, 1, 0); 5296d522f475Smrg#endif 5297d522f475Smrg} 5298d522f475Smrg#endif /* !VMS */ 5299d522f475Smrg 5300d522f475Smrg/* Utility function to try to hide system differences from 5301d522f475Smrg everybody who used to call killpg() */ 5302d522f475Smrg 5303d522f475Smrgint 5304d522f475Smrgkill_process_group(int pid, int sig) 5305d522f475Smrg{ 5306d522f475Smrg TRACE(("kill_process_group(pid=%d, sig=%d)\n", pid, sig)); 5307d522f475Smrg#if defined(SVR4) || defined(SYSV) || !defined(X_NOT_POSIX) 5308d522f475Smrg return kill(-pid, sig); 5309d522f475Smrg#else 5310d522f475Smrg return killpg(pid, sig); 5311d522f475Smrg#endif 5312d522f475Smrg} 5313d522f475Smrg 5314d522f475Smrg#if OPT_EBCDIC 5315d522f475Smrgint 5316d522f475SmrgA2E(int x) 5317d522f475Smrg{ 5318d522f475Smrg char c; 5319d522f475Smrg c = x; 5320d522f475Smrg __atoe_l(&c, 1); 5321d522f475Smrg return c; 5322d522f475Smrg} 5323d522f475Smrg 5324d522f475Smrgint 5325d522f475SmrgE2A(int x) 5326d522f475Smrg{ 5327d522f475Smrg char c; 5328d522f475Smrg c = x; 5329d522f475Smrg __etoa_l(&c, 1); 5330d522f475Smrg return c; 5331d522f475Smrg} 5332d522f475Smrg#endif 5333d522f475Smrg 5334d522f475Smrg#if defined(__QNX__) && !defined(__QNXNTO__) 5335d522f475Smrg#include <sys/types.h> 5336d522f475Smrg#include <sys/proc_msg.h> 5337d522f475Smrg#include <sys/kernel.h> 5338d522f475Smrg#include <string.h> 5339d522f475Smrg#include <errno.h> 5340d522f475Smrg 5341d522f475Smrgstruct _proc_session ps; 5342d522f475Smrgstruct _proc_session_reply rps; 5343d522f475Smrg 5344d522f475Smrgint 5345d522f475Smrgqsetlogin(char *login, char *ttyname) 5346d522f475Smrg{ 5347d522f475Smrg int v = getsid(getpid()); 5348d522f475Smrg 5349d522f475Smrg memset(&ps, 0, sizeof(ps)); 5350d522f475Smrg memset(&rps, 0, sizeof(rps)); 5351d522f475Smrg 5352d522f475Smrg ps.type = _PROC_SESSION; 5353d522f475Smrg ps.subtype = _PROC_SUB_ACTION1; 5354d522f475Smrg ps.sid = v; 5355d522f475Smrg strcpy(ps.name, login); 5356d522f475Smrg 5357d522f475Smrg Send(1, &ps, &rps, sizeof(ps), sizeof(rps)); 5358d522f475Smrg 5359d522f475Smrg if (rps.status < 0) 5360d522f475Smrg return (rps.status); 5361d522f475Smrg 5362d522f475Smrg ps.type = _PROC_SESSION; 5363d522f475Smrg ps.subtype = _PROC_SUB_ACTION2; 5364d522f475Smrg ps.sid = v; 5365d522f475Smrg sprintf(ps.name, "//%d%s", getnid(), ttyname); 5366d522f475Smrg Send(1, &ps, &rps, sizeof(ps), sizeof(rps)); 5367d522f475Smrg 5368d522f475Smrg return (rps.status); 5369d522f475Smrg} 5370d522f475Smrg#endif 5371