main.c revision 20d2c4d2
120d2c4d2Smrg/* $XTermId: main.c,v 1.618 2010/06/20 21:11:51 tom Exp $ */ 2d522f475Smrg 3d522f475Smrg/* 4d522f475Smrg * W A R N I N G 5d522f475Smrg * 6d522f475Smrg * If you think you know what all of this code is doing, you are 7d522f475Smrg * probably very mistaken. There be serious and nasty dragons here. 8d522f475Smrg * 9d522f475Smrg * This client is *not* to be taken as an example of how to write X 10d522f475Smrg * Toolkit applications. It is in need of a substantial rewrite, 11d522f475Smrg * ideally to create a generic tty widget with several different parsing 12d522f475Smrg * widgets so that you can plug 'em together any way you want. Don't 13d522f475Smrg * hold your breath, though.... 14d522f475Smrg */ 15d522f475Smrg 16d522f475Smrg/*********************************************************** 17d522f475Smrg 1820d2c4d2SmrgCopyright 2002-2009,2010 by Thomas E. Dickey 19d522f475Smrg 20d522f475Smrg All Rights Reserved 21d522f475Smrg 22d522f475SmrgPermission is hereby granted, free of charge, to any person obtaining a 23d522f475Smrgcopy of this software and associated documentation files (the 24d522f475Smrg"Software"), to deal in the Software without restriction, including 25d522f475Smrgwithout limitation the rights to use, copy, modify, merge, publish, 26d522f475Smrgdistribute, sublicense, and/or sell copies of the Software, and to 27d522f475Smrgpermit persons to whom the Software is furnished to do so, subject to 28d522f475Smrgthe following conditions: 29d522f475Smrg 30d522f475SmrgThe above copyright notice and this permission notice shall be included 31d522f475Smrgin all copies or substantial portions of the Software. 32d522f475Smrg 33d522f475SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 34d522f475SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 35d522f475SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 36d522f475SmrgIN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 37d522f475SmrgCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 38d522f475SmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 39d522f475SmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 40d522f475Smrg 41d522f475SmrgExcept as contained in this notice, the name(s) of the above copyright 42d522f475Smrgholders shall not be used in advertising or otherwise to promote the 43d522f475Smrgsale, use or other dealings in this Software without prior written 44d522f475Smrgauthorization. 45d522f475Smrg 46d522f475SmrgCopyright 1987, 1988 The Open Group 47d522f475Smrg 48d522f475SmrgPermission to use, copy, modify, distribute, and sell this software and its 49d522f475Smrgdocumentation for any purpose is hereby granted without fee, provided that 50d522f475Smrgthe above copyright notice appear in all copies and that both that 51d522f475Smrgcopyright notice and this permission notice appear in supporting 52d522f475Smrgdocumentation. 53d522f475Smrg 54d522f475SmrgThe above copyright notice and this permission notice shall be included in 55d522f475Smrgall copies or substantial portions of the Software. 56d522f475Smrg 57d522f475SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 58d522f475SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 59d522f475SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 60d522f475SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 61d522f475SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 62d522f475SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 63d522f475Smrg 64d522f475SmrgExcept as contained in this notice, the name of The Open Group shall not be 65d522f475Smrgused in advertising or otherwise to promote the sale, use or other dealings 66d522f475Smrgin this Software without prior written authorization from The Open Group. 67d522f475Smrg 68d522f475SmrgCopyright 1987, 1988 by Digital Equipment Corporation, Maynard. 69d522f475Smrg 70d522f475Smrg All Rights Reserved 71d522f475Smrg 72d522f475SmrgPermission to use, copy, modify, and distribute this software and its 73d522f475Smrgdocumentation for any purpose and without fee is hereby granted, 74d522f475Smrgprovided that the above copyright notice appear in all copies and that 75d522f475Smrgboth that copyright notice and this permission notice appear in 76d522f475Smrgsupporting documentation, and that the name of Digital not be used in 77d522f475Smrgadvertising or publicity pertaining to distribution of the software 78d522f475Smrgwithout specific, written prior permission. 79d522f475Smrg 80d522f475SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 81d522f475SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 82d522f475SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 83d522f475SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 84d522f475SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 85d522f475SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 86d522f475SmrgSOFTWARE. 87d522f475Smrg 88d522f475Smrg******************************************************************/ 89d522f475Smrg 90d522f475Smrg/* main.c */ 91d522f475Smrg 92d522f475Smrg#define RES_OFFSET(field) XtOffsetOf(XTERM_RESOURCE, field) 93d522f475Smrg 94d522f475Smrg#include <xterm.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 138d522f475Smrg#ifdef USE_ISPTS_FLAG 139d522f475Smrgstatic Bool IsPts = False; 140d522f475Smrg#endif 141d522f475Smrg 142d522f475Smrg#if defined(__SCO__) || defined(SVR4) || defined(_POSIX_SOURCE) 143d522f475Smrg#define USE_POSIX_SIGNALS 144d522f475Smrg#endif 145d522f475Smrg 146d522f475Smrg#if defined(SYSV) && !defined(SVR4) && !defined(ISC22) && !defined(ISC30) 147d522f475Smrg/* older SYSV systems cannot ignore SIGHUP. 148d522f475Smrg Shell hangs, or you get extra shells, or something like that */ 149d522f475Smrg#define USE_SYSV_SIGHUP 150d522f475Smrg#endif 151d522f475Smrg 152d522f475Smrg#if defined(sony) && defined(bsd43) && !defined(KANJI) 153d522f475Smrg#define KANJI 154d522f475Smrg#endif 155d522f475Smrg 156d522f475Smrg#ifdef linux 157d522f475Smrg#define USE_SYSV_PGRP 158d522f475Smrg#define USE_SYSV_SIGNALS 159d522f475Smrg#define WTMP 160d522f475Smrg#ifdef __GLIBC__ 161d522f475Smrg#if (__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)) 162d522f475Smrg#include <pty.h> 163d522f475Smrg#endif 164d522f475Smrg#endif 165d522f475Smrg#endif 166d522f475Smrg 167d522f475Smrg#ifdef __MVS__ 168d522f475Smrg#define USE_SYSV_PGRP 169d522f475Smrg#define USE_SYSV_SIGNALS 170d522f475Smrg#endif 171d522f475Smrg 172d522f475Smrg#ifdef __CYGWIN__ 173d522f475Smrg#define WTMP 174d522f475Smrg#endif 175d522f475Smrg 176d522f475Smrg#ifdef __SCO__ 177d522f475Smrg#ifndef _SVID3 178d522f475Smrg#define _SVID3 179d522f475Smrg#endif 180d522f475Smrg#endif 181d522f475Smrg 182d522f475Smrg#if defined(__GLIBC__) && !defined(linux) 183d522f475Smrg#define USE_SYSV_PGRP 184d522f475Smrg#define WTMP 185d522f475Smrg#define HAS_BSD_GROUPS 186d522f475Smrg#endif 187d522f475Smrg 188d522f475Smrg#if defined(USE_TTY_GROUP) || defined(USE_UTMP_SETGID) 189d522f475Smrg#include <grp.h> 190d522f475Smrg#endif 191d522f475Smrg 192d522f475Smrg#ifndef TTY_GROUP_NAME 193d522f475Smrg#define TTY_GROUP_NAME "tty" 194d522f475Smrg#endif 195d522f475Smrg 196d522f475Smrg#include <sys/stat.h> 197d522f475Smrg 198d522f475Smrg#ifdef Lynx 199d522f475Smrg#ifndef BSDLY 200d522f475Smrg#define BSDLY 0 201d522f475Smrg#endif 202d522f475Smrg#ifndef VTDLY 203d522f475Smrg#define VTDLY 0 204d522f475Smrg#endif 205d522f475Smrg#ifndef FFDLY 206d522f475Smrg#define FFDLY 0 207d522f475Smrg#endif 208d522f475Smrg#endif 209d522f475Smrg 210d522f475Smrg#ifdef SYSV /* { */ 211d522f475Smrg 212d522f475Smrg#ifdef USE_USG_PTYS /* AT&T SYSV has no ptyio.h */ 213d522f475Smrg#include <sys/stropts.h> /* for I_PUSH */ 214d522f475Smrg#include <poll.h> /* for POLLIN */ 215d522f475Smrg#endif /* USE_USG_PTYS */ 216d522f475Smrg 217d522f475Smrg#define USE_SYSV_SIGNALS 218d522f475Smrg#define USE_SYSV_PGRP 219d522f475Smrg 220d522f475Smrg#if !defined(TIOCSWINSZ) || defined(__SCO__) || defined(__UNIXWARE__) 221d522f475Smrg#define USE_SYSV_ENVVARS /* COLUMNS/LINES vs. TERMCAP */ 222d522f475Smrg#endif 223d522f475Smrg 224d522f475Smrg/* 225d522f475Smrg * now get system-specific includes 226d522f475Smrg */ 227d522f475Smrg#ifdef CRAY 228d522f475Smrg#define HAS_BSD_GROUPS 229d522f475Smrg#endif 230d522f475Smrg 231d522f475Smrg#ifdef macII 232d522f475Smrg#define HAS_BSD_GROUPS 233d522f475Smrg#include <sys/ttychars.h> 234d522f475Smrg#undef USE_SYSV_ENVVARS 235d522f475Smrg#undef FIOCLEX 236d522f475Smrg#undef FIONCLEX 237d522f475Smrg#define setpgrp2 setpgrp 238d522f475Smrg#include <sgtty.h> 239d522f475Smrg#include <sys/resource.h> 240d522f475Smrg#endif 241d522f475Smrg 242d522f475Smrg#ifdef __hpux 243d522f475Smrg#define HAS_BSD_GROUPS 244d522f475Smrg#include <sys/ptyio.h> 245d522f475Smrg#endif /* __hpux */ 246d522f475Smrg 247d522f475Smrg#ifdef __osf__ 248d522f475Smrg#define HAS_BSD_GROUPS 249d522f475Smrg#undef USE_SYSV_PGRP 250d522f475Smrg#define setpgrp setpgid 251d522f475Smrg#endif 252d522f475Smrg 253d522f475Smrg#ifdef __sgi 254d522f475Smrg#define HAS_BSD_GROUPS 255d522f475Smrg#include <sys/sysmacros.h> 256d522f475Smrg#endif /* __sgi */ 257d522f475Smrg 258d522f475Smrg#ifdef sun 259d522f475Smrg#include <sys/strredir.h> 260d522f475Smrg#endif 261d522f475Smrg 262d522f475Smrg#else /* } !SYSV { */ /* BSD systems */ 263d522f475Smrg 264d522f475Smrg#ifdef __QNX__ 265d522f475Smrg 266d522f475Smrg#ifndef __QNXNTO__ 267d522f475Smrg#define ttyslot() 1 268d522f475Smrg#else 269d522f475Smrg#define USE_SYSV_PGRP 270d522f475Smrgextern __inline__ 271d522f475Smrgint 272d522f475Smrgttyslot(void) 273d522f475Smrg{ 274d522f475Smrg return 1; /* yuk */ 275d522f475Smrg} 276d522f475Smrg#endif 277d522f475Smrg 278d522f475Smrg#else 279d522f475Smrg 280d522f475Smrg#if defined(__INTERIX) || defined(__APPLE__) 281d522f475Smrg#define setpgrp setpgid 282d522f475Smrg#endif 283d522f475Smrg 284d522f475Smrg#ifndef linux 285d522f475Smrg#ifndef VMS 286d522f475Smrg#ifndef USE_POSIX_TERMIOS 287d522f475Smrg#ifndef USE_ANY_SYSV_TERMIO 288d522f475Smrg#include <sgtty.h> 289d522f475Smrg#endif 290d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 291d522f475Smrg#ifdef Lynx 292d522f475Smrg#include <resource.h> 293d522f475Smrg#else 294d522f475Smrg#include <sys/resource.h> 295d522f475Smrg#endif 296d522f475Smrg#ifndef __INTERIX 297d522f475Smrg#define HAS_BSD_GROUPS 298d522f475Smrg#endif 299d522f475Smrg#endif /* !VMS */ 300d522f475Smrg#endif /* !linux */ 301d522f475Smrg 302d522f475Smrg#endif /* __QNX__ */ 303d522f475Smrg 304d522f475Smrg#endif /* } !SYSV */ 305d522f475Smrg 306d522f475Smrg/* Xpoll.h and <sys/param.h> on glibc 2.1 systems have colliding NBBY's */ 307d522f475Smrg#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))) 308d522f475Smrg#ifndef NOFILE 309d522f475Smrg#define NOFILE OPEN_MAX 310d522f475Smrg#endif 311d522f475Smrg#elif !(defined(VMS) || defined(WIN32) || defined(Lynx) || defined(__GNU__) || defined(__MVS__)) 312d522f475Smrg#include <sys/param.h> /* for NOFILE */ 313d522f475Smrg#endif 314d522f475Smrg 315d522f475Smrg#if defined(BSD) && (BSD >= 199103) 316d522f475Smrg#define WTMP 317d522f475Smrg#endif 318d522f475Smrg 319d522f475Smrg#include <stdio.h> 320d522f475Smrg 321d522f475Smrg#ifdef __hpux 322d522f475Smrg#include <sys/utsname.h> 323d522f475Smrg#endif /* __hpux */ 324d522f475Smrg 325d522f475Smrg#if defined(apollo) && (OSMAJORVERSION == 10) && (OSMINORVERSION < 4) 326d522f475Smrg#define ttyslot() 1 327d522f475Smrg#endif /* apollo */ 328d522f475Smrg 329d522f475Smrg#if defined(UTMPX_FOR_UTMP) 330d522f475Smrg#define UTMP_STR utmpx 331d522f475Smrg#else 332d522f475Smrg#define UTMP_STR utmp 333d522f475Smrg#endif 334d522f475Smrg 335d522f475Smrg#if defined(USE_UTEMPTER) 336d522f475Smrg#include <utempter.h> 337d522f475Smrg#endif 338d522f475Smrg 339d522f475Smrg#if defined(UTMPX_FOR_UTMP) 340d522f475Smrg 341d522f475Smrg#include <utmpx.h> 342d522f475Smrg 343d522f475Smrg#define call_endutent endutxent 344d522f475Smrg#define call_getutid getutxid 345d522f475Smrg#define call_pututline pututxline 346d522f475Smrg#define call_setutent setutxent 347d522f475Smrg#define call_updwtmp updwtmpx 348d522f475Smrg 349d522f475Smrg#elif defined(HAVE_UTMP) 350d522f475Smrg 351d522f475Smrg#include <utmp.h> 352d522f475Smrg 353d522f475Smrg#if defined(_CRAY) && (OSMAJORVERSION < 8) 354d522f475Smrgextern struct utmp *getutid __((struct utmp * _Id)); 355d522f475Smrg#endif 356d522f475Smrg 357d522f475Smrg#define call_endutent endutent 358d522f475Smrg#define call_getutid getutid 359d522f475Smrg#define call_pututline pututline 360d522f475Smrg#define call_setutent setutent 361d522f475Smrg#define call_updwtmp updwtmp 362d522f475Smrg 363d522f475Smrg#endif 364d522f475Smrg 365d522f475Smrg#if defined(USE_LASTLOG) && defined(HAVE_LASTLOG_H) 366d522f475Smrg#include <lastlog.h> /* caution: glibc includes utmp.h here */ 367d522f475Smrg#endif 368d522f475Smrg 369d522f475Smrg#ifndef USE_LASTLOGX 370d522f475Smrg#if defined(_NETBSD_SOURCE) && defined(_PATH_LASTLOGX) 371d522f475Smrg#define USE_LASTLOGX 1 372d522f475Smrg#endif 373d522f475Smrg#endif 374d522f475Smrg 375d522f475Smrg#ifdef PUCC_PTYD 376d522f475Smrg#include <local/openpty.h> 377d522f475Smrg#endif /* PUCC_PTYD */ 378d522f475Smrg 379d522f475Smrg#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) 380d522f475Smrg#include <util.h> /* openpty() */ 381d522f475Smrg#endif 382d522f475Smrg 383956cc18dSsnj#if defined(__FreeBSD__) || defined(__DragonFly__) 384d522f475Smrg#include <libutil.h> /* openpty() */ 385d522f475Smrg#endif 386d522f475Smrg 387d522f475Smrg#if !defined(UTMP_FILENAME) 388d522f475Smrg#if defined(UTMP_FILE) 389d522f475Smrg#define UTMP_FILENAME UTMP_FILE 390d522f475Smrg#elif defined(_PATH_UTMP) 391d522f475Smrg#define UTMP_FILENAME _PATH_UTMP 392d522f475Smrg#else 393d522f475Smrg#define UTMP_FILENAME "/etc/utmp" 394d522f475Smrg#endif 395d522f475Smrg#endif 396d522f475Smrg 397d522f475Smrg#ifndef LASTLOG_FILENAME 398d522f475Smrg#ifdef _PATH_LASTLOG 399d522f475Smrg#define LASTLOG_FILENAME _PATH_LASTLOG 400d522f475Smrg#else 401d522f475Smrg#define LASTLOG_FILENAME "/usr/adm/lastlog" /* only on BSD systems */ 402d522f475Smrg#endif 403d522f475Smrg#endif 404d522f475Smrg 405d522f475Smrg#if !defined(WTMP_FILENAME) 406d522f475Smrg#if defined(WTMP_FILE) 407d522f475Smrg#define WTMP_FILENAME WTMP_FILE 408d522f475Smrg#elif defined(_PATH_WTMP) 409d522f475Smrg#define WTMP_FILENAME _PATH_WTMP 410d522f475Smrg#elif defined(SYSV) 411d522f475Smrg#define WTMP_FILENAME "/etc/wtmp" 412d522f475Smrg#else 413d522f475Smrg#define WTMP_FILENAME "/usr/adm/wtmp" 414d522f475Smrg#endif 415d522f475Smrg#endif 416d522f475Smrg 417d522f475Smrg#include <signal.h> 418d522f475Smrg 419d522f475Smrg#if defined(__SCO__) || (defined(ISC) && !defined(_POSIX_SOURCE)) 420d522f475Smrg#undef SIGTSTP /* defined, but not the BSD way */ 421d522f475Smrg#endif 422d522f475Smrg 423d522f475Smrg#ifdef SIGTSTP 424d522f475Smrg#include <sys/wait.h> 425d522f475Smrg#endif 426d522f475Smrg 427d522f475Smrg#if defined(__SCO__) || defined(__UNIXWARE__) 428d522f475Smrg#undef ECHOKE 429d522f475Smrg#undef ECHOCTL 430d522f475Smrg#endif 431d522f475Smrg 432d522f475Smrg#if defined(HAVE_SYS_TTYDEFAULTS_H) && !defined(CEOF) 433d522f475Smrg#include <sys/ttydefaults.h> 434d522f475Smrg#endif 435d522f475Smrg 436d522f475Smrg#ifdef X_NOT_POSIX 437d522f475Smrgextern long lseek(); 438d522f475Smrg#if defined(USG) || defined(SVR4) 439d522f475Smrgextern unsigned sleep(); 440d522f475Smrg#else 441d522f475Smrgextern void sleep(); 442d522f475Smrg#endif 443d522f475Smrgextern char *ttyname(); 444d522f475Smrg#endif 445d522f475Smrg 446d522f475Smrg#if defined(SYSV) && defined(DECL_PTSNAME) 447d522f475Smrgextern char *ptsname(int); 448d522f475Smrg#endif 449d522f475Smrg 450d522f475Smrg#ifndef VMS 45120d2c4d2Smrgstatic SIGNAL_T reapchild(int /* n */ ); 452d522f475Smrgstatic int spawnXTerm(XtermWidget /* xw */ ); 45320d2c4d2Smrgstatic void remove_termcap_entry(char *, const char *); 454d522f475Smrg#ifdef USE_PTY_SEARCH 45520d2c4d2Smrgstatic int pty_search(int * /* pty */ ); 456d522f475Smrg#endif 457d522f475Smrg#endif /* ! VMS */ 458d522f475Smrg 459d522f475Smrgstatic int get_pty(int *pty, char *from); 46020d2c4d2Smrgstatic void resize_termcap(XtermWidget xw); 461d522f475Smrgstatic void set_owner(char *device, uid_t uid, gid_t gid, mode_t mode); 462d522f475Smrg 463d522f475Smrgstatic Bool added_utmp_entry = False; 464d522f475Smrg 465d522f475Smrg#ifdef HAVE_POSIX_SAVED_IDS 466d522f475Smrgstatic uid_t save_euid; 467d522f475Smrgstatic gid_t save_egid; 468d522f475Smrg#endif 469d522f475Smrg 470d522f475Smrgstatic uid_t save_ruid; 471d522f475Smrgstatic gid_t save_rgid; 472d522f475Smrg 473d522f475Smrg#if defined(USE_UTMP_SETGID) 474d522f475Smrgstatic int really_get_pty(int *pty, char *from); 475d522f475Smrg#endif 476d522f475Smrg 477d522f475Smrg#if defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 478d522f475Smrgstatic Bool xterm_exiting = False; 479d522f475Smrg#endif 480d522f475Smrg 481d522f475Smrgstatic char *explicit_shname = NULL; 482d522f475Smrg 483d522f475Smrg/* 484d522f475Smrg** Ordinarily it should be okay to omit the assignment in the following 485d522f475Smrg** statement. Apparently the c89 compiler on AIX 4.1.3 has a bug, or does 486d522f475Smrg** it? Without the assignment though the compiler will init command_to_exec 487d522f475Smrg** to 0xffffffff instead of NULL; and subsequent usage, e.g. in spawnXTerm() to 488d522f475Smrg** SEGV. 489d522f475Smrg*/ 490d522f475Smrgstatic char **command_to_exec = NULL; 491d522f475Smrg 492d522f475Smrg#if OPT_LUIT_PROG 493d522f475Smrgstatic char **command_to_exec_with_luit = NULL; 494d522f475Smrg#endif 495d522f475Smrg 496d522f475Smrg#define TERMCAP_ERASE "kb" 497d522f475Smrg#define VAL_INITIAL_ERASE A2E(8) 498d522f475Smrg 499d522f475Smrg/* choose a nice default value for speed - if we make it too low, users who 500d522f475Smrg * mistakenly use $TERM set to vt100 will get padding delays. Setting it to a 501d522f475Smrg * higher value is not useful since legacy applications (termcap) that care 502d522f475Smrg * about padding generally store the code in a short, which does not have 503d522f475Smrg * enough bits for the extended values. 504d522f475Smrg */ 505d522f475Smrg#ifdef B38400 /* everyone should define this */ 506d522f475Smrg#define VAL_LINE_SPEED B38400 507d522f475Smrg#else /* ...but xterm's used this for a long time */ 508d522f475Smrg#define VAL_LINE_SPEED B9600 509d522f475Smrg#endif 510d522f475Smrg 511d522f475Smrg/* 512d522f475Smrg * Allow use of system default characters if defined and reasonable. 513d522f475Smrg * These are based on the BSD ttydefaults.h 514d522f475Smrg */ 515d522f475Smrg#ifndef CBRK 516d522f475Smrg#define CBRK 0xff /* was 0 */ 517d522f475Smrg#endif 518d522f475Smrg#ifndef CDISCARD 519d522f475Smrg#define CDISCARD CONTROL('O') 520d522f475Smrg#endif 521d522f475Smrg#ifndef CDSUSP 522d522f475Smrg#define CDSUSP CONTROL('Y') 523d522f475Smrg#endif 524d522f475Smrg#ifndef CEOF 525d522f475Smrg#define CEOF CONTROL('D') 526d522f475Smrg#endif 527d522f475Smrg#ifndef CEOL 528d522f475Smrg#define CEOL 0xff /* was 0 */ 529d522f475Smrg#endif 530d522f475Smrg#ifndef CERASE 531d522f475Smrg#define CERASE 0177 532d522f475Smrg#endif 533d522f475Smrg#ifndef CERASE2 534d522f475Smrg#define CERASE2 CONTROL('H') 535d522f475Smrg#endif 536d522f475Smrg#ifndef CFLUSH 537d522f475Smrg#define CFLUSH CONTROL('O') 538d522f475Smrg#endif 539d522f475Smrg#ifndef CINTR 540d522f475Smrg#define CINTR CONTROL('C') 541d522f475Smrg#endif 542d522f475Smrg#ifndef CKILL 543d522f475Smrg#define CKILL CONTROL('U') /* was '@' */ 544d522f475Smrg#endif 545d522f475Smrg#ifndef CLNEXT 546d522f475Smrg#define CLNEXT CONTROL('V') 547d522f475Smrg#endif 548d522f475Smrg#ifndef CNUL 549d522f475Smrg#define CNUL 0 550d522f475Smrg#endif 551d522f475Smrg#ifndef CQUIT 552d522f475Smrg#define CQUIT CONTROL('\\') 553d522f475Smrg#endif 554d522f475Smrg#ifndef CRPRNT 555d522f475Smrg#define CRPRNT CONTROL('R') 556d522f475Smrg#endif 557d522f475Smrg#ifndef CREPRINT 558d522f475Smrg#define CREPRINT CRPRNT 559d522f475Smrg#endif 560d522f475Smrg#ifndef CSTART 561d522f475Smrg#define CSTART CONTROL('Q') 562d522f475Smrg#endif 563d522f475Smrg#ifndef CSTATUS 564d522f475Smrg#define CSTATUS CONTROL('T') 565d522f475Smrg#endif 566d522f475Smrg#ifndef CSTOP 567d522f475Smrg#define CSTOP CONTROL('S') 568d522f475Smrg#endif 569d522f475Smrg#ifndef CSUSP 570d522f475Smrg#define CSUSP CONTROL('Z') 571d522f475Smrg#endif 572d522f475Smrg#ifndef CSWTCH 573d522f475Smrg#define CSWTCH 0 574d522f475Smrg#endif 575d522f475Smrg#ifndef CWERASE 576d522f475Smrg#define CWERASE CONTROL('W') 577d522f475Smrg#endif 578d522f475Smrg 579d522f475Smrg#ifdef USE_ANY_SYSV_TERMIO 580d522f475Smrg#define TERMIO_STRUCT struct termio 581d522f475Smrg#define ttySetAttr(fd, datap) ioctl(fd, TCSETA, datap) 582d522f475Smrg#define ttyGetAttr(fd, datap) ioctl(fd, TCGETA, datap) 583d522f475Smrg#define ttyFlush(fd) ioctl(fd, TCFLSH, 1) 584d522f475Smrg#elif defined(USE_POSIX_TERMIOS) 585d522f475Smrg#define TERMIO_STRUCT struct termios 586d522f475Smrg#define ttySetAttr(fd, datap) tcsetattr(fd, TCSANOW, datap) 587d522f475Smrg#define ttyGetAttr(fd, datap) tcgetattr(fd, datap) 588d522f475Smrg#define ttyFlush(fd) tcflush(fd, TCOFLUSH) 589d522f475Smrg#endif /* USE_ANY_SYSV_TERMIO */ 590d522f475Smrg 591d522f475Smrg#ifndef VMS 592d522f475Smrg#ifdef TERMIO_STRUCT 593d522f475Smrg/* The following structures are initialized in main() in order 594d522f475Smrg** to eliminate any assumptions about the internal order of their 595d522f475Smrg** contents. 596d522f475Smrg*/ 597d522f475Smrgstatic TERMIO_STRUCT d_tio; 598d522f475Smrg 599d522f475Smrg#ifdef HAS_LTCHARS 600d522f475Smrgstatic struct ltchars d_ltc; 601d522f475Smrg#endif /* HAS_LTCHARS */ 602d522f475Smrg 603d522f475Smrg#ifdef TIOCLSET 604d522f475Smrgstatic unsigned int d_lmode; 605d522f475Smrg#endif /* TIOCLSET */ 606d522f475Smrg 607d522f475Smrg#else /* !TERMIO_STRUCT */ 608d522f475Smrgstatic struct sgttyb d_sg = 609d522f475Smrg{ 610d522f475Smrg 0, 0, 0177, CKILL, (EVENP | ODDP | ECHO | XTABS | CRMOD) 611d522f475Smrg}; 612d522f475Smrgstatic struct tchars d_tc = 613d522f475Smrg{ 614d522f475Smrg CINTR, CQUIT, CSTART, 615d522f475Smrg CSTOP, CEOF, CBRK 616d522f475Smrg}; 617d522f475Smrgstatic struct ltchars d_ltc = 618d522f475Smrg{ 619d522f475Smrg CSUSP, CDSUSP, CRPRNT, 620d522f475Smrg CFLUSH, CWERASE, CLNEXT 621d522f475Smrg}; 622d522f475Smrgstatic int d_disipline = NTTYDISC; 623d522f475Smrgstatic long int d_lmode = LCRTBS | LCRTERA | LCRTKIL | LCTLECH; 624d522f475Smrg#ifdef sony 625d522f475Smrgstatic long int d_jmode = KM_SYSSJIS | KM_ASCII; 626d522f475Smrgstatic struct jtchars d_jtc = 627d522f475Smrg{ 628d522f475Smrg 'J', 'B' 629d522f475Smrg}; 630d522f475Smrg#endif /* sony */ 631d522f475Smrg#endif /* TERMIO_STRUCT */ 632d522f475Smrg#endif /* ! VMS */ 633d522f475Smrg 634d522f475Smrg/* 635d522f475Smrg * SYSV has the termio.c_cc[V] and ltchars; BSD has tchars and ltchars; 636d522f475Smrg * SVR4 has only termio.c_cc, but it includes everything from ltchars. 637d522f475Smrg * POSIX termios has termios.c_cc, which is similar to SVR4. 638d522f475Smrg */ 639d522f475Smrg#define TTYMODE(name) { name, sizeof(name)-1, 0, 0 } 640d522f475Smrgstatic Boolean override_tty_modes = False; 641d522f475Smrg/* *INDENT-OFF* */ 642d522f475Smrgstatic struct _xttymodes { 64320d2c4d2Smrg const char *name; 644d522f475Smrg size_t len; 645d522f475Smrg int set; 646d522f475Smrg int value; 647d522f475Smrg} ttymodelist[] = { 648d522f475Smrg TTYMODE("intr"), /* tchars.t_intrc ; VINTR */ 649d522f475Smrg#define XTTYMODE_intr 0 650d522f475Smrg TTYMODE("quit"), /* tchars.t_quitc ; VQUIT */ 651d522f475Smrg#define XTTYMODE_quit 1 652d522f475Smrg TTYMODE("erase"), /* sgttyb.sg_erase ; VERASE */ 653d522f475Smrg#define XTTYMODE_erase 2 654d522f475Smrg TTYMODE("kill"), /* sgttyb.sg_kill ; VKILL */ 655d522f475Smrg#define XTTYMODE_kill 3 656d522f475Smrg TTYMODE("eof"), /* tchars.t_eofc ; VEOF */ 657d522f475Smrg#define XTTYMODE_eof 4 658d522f475Smrg TTYMODE("eol"), /* VEOL */ 659d522f475Smrg#define XTTYMODE_eol 5 660d522f475Smrg TTYMODE("swtch"), /* VSWTCH */ 661d522f475Smrg#define XTTYMODE_swtch 6 662d522f475Smrg TTYMODE("start"), /* tchars.t_startc ; VSTART */ 663d522f475Smrg#define XTTYMODE_start 7 664d522f475Smrg TTYMODE("stop"), /* tchars.t_stopc ; VSTOP */ 665d522f475Smrg#define XTTYMODE_stop 8 666d522f475Smrg TTYMODE("brk"), /* tchars.t_brkc */ 667d522f475Smrg#define XTTYMODE_brk 9 668d522f475Smrg TTYMODE("susp"), /* ltchars.t_suspc ; VSUSP */ 669d522f475Smrg#define XTTYMODE_susp 10 670d522f475Smrg TTYMODE("dsusp"), /* ltchars.t_dsuspc ; VDSUSP */ 671d522f475Smrg#define XTTYMODE_dsusp 11 672d522f475Smrg TTYMODE("rprnt"), /* ltchars.t_rprntc ; VREPRINT */ 673d522f475Smrg#define XTTYMODE_rprnt 12 674d522f475Smrg TTYMODE("flush"), /* ltchars.t_flushc ; VDISCARD */ 675d522f475Smrg#define XTTYMODE_flush 13 676d522f475Smrg TTYMODE("weras"), /* ltchars.t_werasc ; VWERASE */ 677d522f475Smrg#define XTTYMODE_weras 14 678d522f475Smrg TTYMODE("lnext"), /* ltchars.t_lnextc ; VLNEXT */ 679d522f475Smrg#define XTTYMODE_lnext 15 680d522f475Smrg TTYMODE("status"), /* VSTATUS */ 681d522f475Smrg#define XTTYMODE_status 16 682d522f475Smrg TTYMODE("erase2"), /* VERASE2 */ 683d522f475Smrg#define XTTYMODE_erase2 17 684d522f475Smrg TTYMODE("eol2"), /* VEOL2 */ 685d522f475Smrg#define XTTYMODE_eol2 18 686d522f475Smrg { NULL, 0, 0, '\0' }, /* end of data */ 687d522f475Smrg}; 688d522f475Smrg 689d522f475Smrg#define validTtyChar(data, n) \ 690d522f475Smrg (known_ttyChars[n].sysMode >= 0 && \ 691d522f475Smrg known_ttyChars[n].sysMode < (int) XtNumber(data.c_cc)) 692d522f475Smrg 693d522f475Smrgstatic const struct { 694d522f475Smrg int sysMode; 695d522f475Smrg int myMode; 696d522f475Smrg int myDefault; 697d522f475Smrg} known_ttyChars[] = { 698d522f475Smrg#ifdef VINTR 699d522f475Smrg { VINTR, XTTYMODE_intr, CINTR }, 700d522f475Smrg#endif 701d522f475Smrg#ifdef VQUIT 702d522f475Smrg { VQUIT, XTTYMODE_quit, CQUIT }, 703d522f475Smrg#endif 704d522f475Smrg#ifdef VERASE 705d522f475Smrg { VERASE, XTTYMODE_erase, CERASE }, 706d522f475Smrg#endif 707d522f475Smrg#ifdef VKILL 708d522f475Smrg { VKILL, XTTYMODE_kill, CKILL }, 709d522f475Smrg#endif 710d522f475Smrg#ifdef VEOF 711d522f475Smrg { VEOF, XTTYMODE_eof, CEOF }, 712d522f475Smrg#endif 713d522f475Smrg#ifdef VEOL 714d522f475Smrg { VEOL, XTTYMODE_eol, CEOL }, 715d522f475Smrg#endif 716d522f475Smrg#ifdef VSWTCH 717d522f475Smrg { VSWTCH, XTTYMODE_swtch, CNUL }, 718d522f475Smrg#endif 719d522f475Smrg#ifdef VSTART 720d522f475Smrg { VSTART, XTTYMODE_start, CSTART }, 721d522f475Smrg#endif 722d522f475Smrg#ifdef VSTOP 723d522f475Smrg { VSTOP, XTTYMODE_stop, CSTOP }, 724d522f475Smrg#endif 725d522f475Smrg#ifdef VSUSP 726d522f475Smrg { VSUSP, XTTYMODE_susp, CSUSP }, 727d522f475Smrg#endif 728d522f475Smrg#ifdef VDSUSP 729d522f475Smrg { VDSUSP, XTTYMODE_dsusp, CDSUSP }, 730d522f475Smrg#endif 731d522f475Smrg#ifdef VREPRINT 732d522f475Smrg { VREPRINT, XTTYMODE_rprnt, CREPRINT }, 733d522f475Smrg#endif 734d522f475Smrg#ifdef VDISCARD 735d522f475Smrg { VDISCARD, XTTYMODE_flush, CDISCARD }, 736d522f475Smrg#endif 737d522f475Smrg#ifdef VWERASE 738d522f475Smrg { VWERASE, XTTYMODE_weras, CWERASE }, 739d522f475Smrg#endif 740d522f475Smrg#ifdef VLNEXT 741d522f475Smrg { VLNEXT, XTTYMODE_lnext, CLNEXT }, 742d522f475Smrg#endif 743d522f475Smrg#ifdef VSTATUS 744d522f475Smrg { VSTATUS, XTTYMODE_status, CSTATUS }, 745d522f475Smrg#endif 746d522f475Smrg#ifdef VERASE2 747d522f475Smrg { VERASE2, XTTYMODE_erase2, CERASE2 }, 748d522f475Smrg#endif 749d522f475Smrg#ifdef VEOL2 750d522f475Smrg { VEOL2, XTTYMODE_eol2, CNUL }, 751d522f475Smrg#endif 752d522f475Smrg}; 753d522f475Smrg/* *INDENT-ON* */ 754d522f475Smrg 755d522f475Smrg#define TMODE(ind,var) if (ttymodelist[ind].set) var = ttymodelist[ind].value 756d522f475Smrg 757d522f475Smrgstatic int parse_tty_modes(char *s, struct _xttymodes *modelist); 758d522f475Smrg 759d522f475Smrg#ifndef USE_UTEMPTER 760d522f475Smrg#ifdef USE_SYSV_UTMP 761d522f475Smrg#if (defined(AIXV3) && (OSMAJORVERSION < 4)) && !(defined(getutid)) 762d522f475Smrgextern struct utmp *getutid(); 763d522f475Smrg#endif /* AIXV3 */ 764d522f475Smrg 765d522f475Smrg#else /* not USE_SYSV_UTMP */ 766d522f475Smrgstatic char etc_utmp[] = UTMP_FILENAME; 767d522f475Smrg#endif /* USE_SYSV_UTMP */ 768d522f475Smrg 769d522f475Smrg#if defined(USE_LASTLOG) && defined(USE_STRUCT_LASTLOG) 770d522f475Smrgstatic char etc_lastlog[] = LASTLOG_FILENAME; 771d522f475Smrg#else 772d522f475Smrg#undef USE_LASTLOG 773d522f475Smrg#endif 774d522f475Smrg 775d522f475Smrg#ifdef WTMP 776d522f475Smrgstatic char etc_wtmp[] = WTMP_FILENAME; 777d522f475Smrg#endif 778d522f475Smrg#endif /* !USE_UTEMPTER */ 779d522f475Smrg 780d522f475Smrg/* 781d522f475Smrg * Some people with 4.3bsd /bin/login seem to like to use login -p -f user 782d522f475Smrg * to implement xterm -ls. They can turn on USE_LOGIN_DASH_P and turn off 783d522f475Smrg * WTMP and USE_LASTLOG. 784d522f475Smrg */ 785d522f475Smrg#ifdef USE_LOGIN_DASH_P 786d522f475Smrg#ifndef LOGIN_FILENAME 787d522f475Smrg#define LOGIN_FILENAME "/bin/login" 788d522f475Smrg#endif 789d522f475Smrgstatic char bin_login[] = LOGIN_FILENAME; 790d522f475Smrg#endif 791d522f475Smrg 792d522f475Smrgstatic char passedPty[PTYCHARLEN + 1]; /* name if pty if slave */ 793d522f475Smrg 794d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 795d522f475Smrgstatic int Console; 796d522f475Smrg#include <X11/Xmu/SysUtil.h> /* XmuGetHostname */ 797d522f475Smrg#define MIT_CONSOLE_LEN 12 798d522f475Smrg#define MIT_CONSOLE "MIT_CONSOLE_" 799d522f475Smrgstatic char mit_console_name[255 + MIT_CONSOLE_LEN + 1] = MIT_CONSOLE; 800d522f475Smrgstatic Atom mit_console; 801d522f475Smrg#endif /* TIOCCONS */ 802d522f475Smrg 803d522f475Smrg#ifndef USE_SYSV_UTMP 804d522f475Smrgstatic int tslot; 805d522f475Smrg#endif /* USE_SYSV_UTMP */ 806d522f475Smrgstatic sigjmp_buf env; 807d522f475Smrg 808d522f475Smrg#define SetUtmpHost(dst, screen) \ 809d522f475Smrg { \ 810d522f475Smrg char host[sizeof(dst) + 1]; \ 811d522f475Smrg strncpy(host, DisplayString(screen->display), sizeof(host)); \ 812d522f475Smrg TRACE(("DisplayString(%s)\n", host)); \ 813d522f475Smrg if (!resource.utmpDisplayId) { \ 814d522f475Smrg char *endptr = strrchr(host, ':'); \ 815d522f475Smrg if (endptr) { \ 816d522f475Smrg TRACE(("trimming display-id '%s'\n", host)); \ 817d522f475Smrg *endptr = '\0'; \ 818d522f475Smrg } \ 819d522f475Smrg } \ 820d522f475Smrg strncpy(dst, host, sizeof(dst)); \ 821d522f475Smrg } 822d522f475Smrg 823d522f475Smrg#ifdef HAVE_UTMP_UT_SYSLEN 824d522f475Smrg# define SetUtmpSysLen(utmp) \ 825d522f475Smrg { \ 826d522f475Smrg utmp.ut_host[sizeof(utmp.ut_host)-1] = '\0'; \ 827d522f475Smrg utmp.ut_syslen = strlen(utmp.ut_host) + 1; \ 828d522f475Smrg } 829d522f475Smrg#endif 830d522f475Smrg 831d522f475Smrg/* used by VT (charproc.c) */ 832d522f475Smrg 833d522f475Smrgstatic XtResource application_resources[] = 834d522f475Smrg{ 835d522f475Smrg Sres("name", "Name", xterm_name, DFT_TERMTYPE), 836d522f475Smrg Sres("iconGeometry", "IconGeometry", icon_geometry, NULL), 837d522f475Smrg Sres(XtNtitle, XtCTitle, title, NULL), 838d522f475Smrg Sres(XtNiconName, XtCIconName, icon_name, NULL), 839d522f475Smrg Sres("termName", "TermName", term_name, NULL), 840d522f475Smrg Sres("ttyModes", "TtyModes", tty_modes, NULL), 841d522f475Smrg Bres("hold", "Hold", hold_screen, False), 842d522f475Smrg Bres("utmpInhibit", "UtmpInhibit", utmpInhibit, False), 843d522f475Smrg Bres("utmpDisplayId", "UtmpDisplayId", utmpDisplayId, True), 844d522f475Smrg Bres("messages", "Messages", messages, True), 845d522f475Smrg Ires("minBufSize", "MinBufSize", minBufSize, 4096), 846d522f475Smrg Ires("maxBufSize", "MaxBufSize", maxBufSize, 32768), 84720d2c4d2Smrg Sres("menuLocale", "MenuLocale", menuLocale, DEF_MENU_LOCALE), 848d522f475Smrg Sres("keyboardType", "KeyboardType", keyboardType, "unknown"), 849d522f475Smrg#if OPT_SUNPC_KBD 850d522f475Smrg Bres("sunKeyboard", "SunKeyboard", sunKeyboard, False), 851d522f475Smrg#endif 852d522f475Smrg#if OPT_HP_FUNC_KEYS 853d522f475Smrg Bres("hpFunctionKeys", "HpFunctionKeys", hpFunctionKeys, False), 854d522f475Smrg#endif 855d522f475Smrg#if OPT_SCO_FUNC_KEYS 856d522f475Smrg Bres("scoFunctionKeys", "ScoFunctionKeys", scoFunctionKeys, False), 857d522f475Smrg#endif 858d522f475Smrg#if OPT_SUN_FUNC_KEYS 859d522f475Smrg Bres("sunFunctionKeys", "SunFunctionKeys", sunFunctionKeys, False), 860d522f475Smrg#endif 861d522f475Smrg#if OPT_TCAP_FKEYS 862d522f475Smrg Bres("tcapFunctionKeys", "TcapFunctionKeys", termcapKeys, False), 863d522f475Smrg#endif 864d522f475Smrg#if OPT_INITIAL_ERASE 865d522f475Smrg Bres("ptyInitialErase", "PtyInitialErase", ptyInitialErase, DEF_INITIAL_ERASE), 866d522f475Smrg Bres("backarrowKeyIsErase", "BackarrowKeyIsErase", backarrow_is_erase, DEF_BACKARO_ERASE), 867d522f475Smrg#endif 868d522f475Smrg Bres("useInsertMode", "UseInsertMode", useInsertMode, False), 869d522f475Smrg#if OPT_ZICONBEEP 870d522f475Smrg Ires("zIconBeep", "ZIconBeep", zIconBeep, 0), 871d522f475Smrg#endif 872d522f475Smrg#if OPT_PTY_HANDSHAKE 873d522f475Smrg Bres("waitForMap", "WaitForMap", wait_for_map, False), 874d522f475Smrg Bres("ptyHandshake", "PtyHandshake", ptyHandshake, True), 875d522f475Smrg Bres("ptySttySize", "PtySttySize", ptySttySize, DEF_PTY_STTY_SIZE), 876d522f475Smrg#endif 877d522f475Smrg#if OPT_SAME_NAME 878d522f475Smrg Bres("sameName", "SameName", sameName, True), 879d522f475Smrg#endif 880d522f475Smrg#if OPT_SESSION_MGT 881d522f475Smrg Bres("sessionMgt", "SessionMgt", sessionMgt, True), 882d522f475Smrg#endif 883d522f475Smrg#if OPT_TOOLBAR 884d522f475Smrg Bres(XtNtoolBar, XtCToolBar, toolBar, True), 885d522f475Smrg#endif 886956cc18dSsnj#if OPT_MAXIMIZE 887956cc18dSsnj Bres(XtNmaximized, XtCMaximized, maximized, False), 888956cc18dSsnj#endif 889d522f475Smrg}; 890d522f475Smrg 89120d2c4d2Smrgstatic String fallback_resources[] = 892d522f475Smrg{ 893d522f475Smrg "*SimpleMenu*menuLabel.vertSpace: 100", 894d522f475Smrg "*SimpleMenu*HorizontalMargins: 16", 895d522f475Smrg "*SimpleMenu*Sme.height: 16", 896d522f475Smrg "*SimpleMenu*Cursor: left_ptr", 897d522f475Smrg "*mainMenu.Label: Main Options (no app-defaults)", 898d522f475Smrg "*vtMenu.Label: VT Options (no app-defaults)", 899d522f475Smrg "*fontMenu.Label: VT Fonts (no app-defaults)", 900d522f475Smrg#if OPT_TEK4014 901d522f475Smrg "*tekMenu.Label: Tek Options (no app-defaults)", 902d522f475Smrg#endif 903d522f475Smrg NULL 904d522f475Smrg}; 905d522f475Smrg 906d522f475Smrg/* Command line options table. Only resources are entered here...there is a 907d522f475Smrg pass over the remaining options after XrmParseCommand is let loose. */ 908d522f475Smrg/* *INDENT-OFF* */ 909d522f475Smrgstatic XrmOptionDescRec optionDescList[] = { 91020d2c4d2Smrg{"-geometry", "*vt100.geometry",XrmoptionSepArg, (XPointer) NULL}, 91120d2c4d2Smrg{"-132", "*c132", XrmoptionNoArg, (XPointer) "on"}, 91220d2c4d2Smrg{"+132", "*c132", XrmoptionNoArg, (XPointer) "off"}, 91320d2c4d2Smrg{"-ah", "*alwaysHighlight", XrmoptionNoArg, (XPointer) "on"}, 91420d2c4d2Smrg{"+ah", "*alwaysHighlight", XrmoptionNoArg, (XPointer) "off"}, 91520d2c4d2Smrg{"-aw", "*autoWrap", XrmoptionNoArg, (XPointer) "on"}, 91620d2c4d2Smrg{"+aw", "*autoWrap", XrmoptionNoArg, (XPointer) "off"}, 917d522f475Smrg#ifndef NO_ACTIVE_ICON 91820d2c4d2Smrg{"-ai", "*activeIcon", XrmoptionNoArg, (XPointer) "off"}, 91920d2c4d2Smrg{"+ai", "*activeIcon", XrmoptionNoArg, (XPointer) "on"}, 920d522f475Smrg#endif /* NO_ACTIVE_ICON */ 92120d2c4d2Smrg{"-b", "*internalBorder",XrmoptionSepArg, (XPointer) NULL}, 92220d2c4d2Smrg{"-bc", "*cursorBlink", XrmoptionNoArg, (XPointer) "on"}, 92320d2c4d2Smrg{"+bc", "*cursorBlink", XrmoptionNoArg, (XPointer) "off"}, 92420d2c4d2Smrg{"-bcf", "*cursorOffTime",XrmoptionSepArg, (XPointer) NULL}, 92520d2c4d2Smrg{"-bcn", "*cursorOnTime",XrmoptionSepArg, (XPointer) NULL}, 92620d2c4d2Smrg{"-bdc", "*colorBDMode", XrmoptionNoArg, (XPointer) "off"}, 92720d2c4d2Smrg{"+bdc", "*colorBDMode", XrmoptionNoArg, (XPointer) "on"}, 92820d2c4d2Smrg{"-cb", "*cutToBeginningOfLine", XrmoptionNoArg, (XPointer) "off"}, 92920d2c4d2Smrg{"+cb", "*cutToBeginningOfLine", XrmoptionNoArg, (XPointer) "on"}, 93020d2c4d2Smrg{"-cc", "*charClass", XrmoptionSepArg, (XPointer) NULL}, 93120d2c4d2Smrg{"-cm", "*colorMode", XrmoptionNoArg, (XPointer) "off"}, 93220d2c4d2Smrg{"+cm", "*colorMode", XrmoptionNoArg, (XPointer) "on"}, 93320d2c4d2Smrg{"-cn", "*cutNewline", XrmoptionNoArg, (XPointer) "off"}, 93420d2c4d2Smrg{"+cn", "*cutNewline", XrmoptionNoArg, (XPointer) "on"}, 93520d2c4d2Smrg{"-cr", "*cursorColor", XrmoptionSepArg, (XPointer) NULL}, 93620d2c4d2Smrg{"-cu", "*curses", XrmoptionNoArg, (XPointer) "on"}, 93720d2c4d2Smrg{"+cu", "*curses", XrmoptionNoArg, (XPointer) "off"}, 93820d2c4d2Smrg{"-dc", "*dynamicColors",XrmoptionNoArg, (XPointer) "off"}, 93920d2c4d2Smrg{"+dc", "*dynamicColors",XrmoptionNoArg, (XPointer) "on"}, 94020d2c4d2Smrg{"-fb", "*boldFont", XrmoptionSepArg, (XPointer) NULL}, 94120d2c4d2Smrg{"-fbb", "*freeBoldBox", XrmoptionNoArg, (XPointer)"off"}, 94220d2c4d2Smrg{"+fbb", "*freeBoldBox", XrmoptionNoArg, (XPointer)"on"}, 94320d2c4d2Smrg{"-fbx", "*forceBoxChars", XrmoptionNoArg, (XPointer)"off"}, 94420d2c4d2Smrg{"+fbx", "*forceBoxChars", XrmoptionNoArg, (XPointer)"on"}, 945d522f475Smrg#ifndef NO_ACTIVE_ICON 94620d2c4d2Smrg{"-fi", "*iconFont", XrmoptionSepArg, (XPointer) NULL}, 947d522f475Smrg#endif /* NO_ACTIVE_ICON */ 948d522f475Smrg#if OPT_RENDERFONT 94920d2c4d2Smrg{"-fa", "*faceName", XrmoptionSepArg, (XPointer) NULL}, 95020d2c4d2Smrg{"-fd", "*faceNameDoublesize", XrmoptionSepArg, (XPointer) NULL}, 95120d2c4d2Smrg{"-fs", "*faceSize", XrmoptionSepArg, (XPointer) NULL}, 952d522f475Smrg#endif 953d522f475Smrg#if OPT_WIDE_CHARS 95420d2c4d2Smrg{"-fw", "*wideFont", XrmoptionSepArg, (XPointer) NULL}, 95520d2c4d2Smrg{"-fwb", "*wideBoldFont", XrmoptionSepArg, (XPointer) NULL}, 956d522f475Smrg#endif 957d522f475Smrg#if OPT_INPUT_METHOD 95820d2c4d2Smrg{"-fx", "*ximFont", XrmoptionSepArg, (XPointer) NULL}, 959d522f475Smrg#endif 960d522f475Smrg#if OPT_HIGHLIGHT_COLOR 96120d2c4d2Smrg{"-hc", "*highlightColor", XrmoptionSepArg, (XPointer) NULL}, 96220d2c4d2Smrg{"-hm", "*highlightColorMode", XrmoptionNoArg, (XPointer) "on"}, 96320d2c4d2Smrg{"+hm", "*highlightColorMode", XrmoptionNoArg, (XPointer) "off"}, 96420d2c4d2Smrg{"-selfg", "*highlightTextColor", XrmoptionSepArg, (XPointer) NULL}, 96520d2c4d2Smrg{"-selbg", "*highlightColor", XrmoptionSepArg, (XPointer) NULL}, 966d522f475Smrg#endif 967d522f475Smrg#if OPT_HP_FUNC_KEYS 96820d2c4d2Smrg{"-hf", "*hpFunctionKeys",XrmoptionNoArg, (XPointer) "on"}, 96920d2c4d2Smrg{"+hf", "*hpFunctionKeys",XrmoptionNoArg, (XPointer) "off"}, 970d522f475Smrg#endif 97120d2c4d2Smrg{"-hold", "*hold", XrmoptionNoArg, (XPointer) "on"}, 97220d2c4d2Smrg{"+hold", "*hold", XrmoptionNoArg, (XPointer) "off"}, 973d522f475Smrg#if OPT_INITIAL_ERASE 97420d2c4d2Smrg{"-ie", "*ptyInitialErase", XrmoptionNoArg, (XPointer) "on"}, 97520d2c4d2Smrg{"+ie", "*ptyInitialErase", XrmoptionNoArg, (XPointer) "off"}, 976d522f475Smrg#endif 97720d2c4d2Smrg{"-j", "*jumpScroll", XrmoptionNoArg, (XPointer) "on"}, 97820d2c4d2Smrg{"+j", "*jumpScroll", XrmoptionNoArg, (XPointer) "off"}, 979d522f475Smrg#if OPT_C1_PRINT 98020d2c4d2Smrg{"-k8", "*allowC1Printable", XrmoptionNoArg, (XPointer) "on"}, 98120d2c4d2Smrg{"+k8", "*allowC1Printable", XrmoptionNoArg, (XPointer) "off"}, 982d522f475Smrg#endif 98320d2c4d2Smrg{"-kt", "*keyboardType", XrmoptionSepArg, (XPointer) NULL}, 98420d2c4d2Smrg{"+kt", "*keyboardType", XrmoptionSepArg, (XPointer) NULL}, 985d522f475Smrg/* parse logging options anyway for compatibility */ 98620d2c4d2Smrg{"-l", "*logging", XrmoptionNoArg, (XPointer) "on"}, 98720d2c4d2Smrg{"+l", "*logging", XrmoptionNoArg, (XPointer) "off"}, 98820d2c4d2Smrg{"-lf", "*logFile", XrmoptionSepArg, (XPointer) NULL}, 98920d2c4d2Smrg{"-ls", "*loginShell", XrmoptionNoArg, (XPointer) "on"}, 99020d2c4d2Smrg{"+ls", "*loginShell", XrmoptionNoArg, (XPointer) "off"}, 99120d2c4d2Smrg{"-mb", "*marginBell", XrmoptionNoArg, (XPointer) "on"}, 99220d2c4d2Smrg{"+mb", "*marginBell", XrmoptionNoArg, (XPointer) "off"}, 99320d2c4d2Smrg{"-mc", "*multiClickTime", XrmoptionSepArg, (XPointer) NULL}, 99420d2c4d2Smrg{"-mesg", "*messages", XrmoptionNoArg, (XPointer) "off"}, 99520d2c4d2Smrg{"+mesg", "*messages", XrmoptionNoArg, (XPointer) "on"}, 99620d2c4d2Smrg{"-ms", "*pointerColor",XrmoptionSepArg, (XPointer) NULL}, 99720d2c4d2Smrg{"-nb", "*nMarginBell", XrmoptionSepArg, (XPointer) NULL}, 99820d2c4d2Smrg{"-nul", "*underLine", XrmoptionNoArg, (XPointer) "off"}, 99920d2c4d2Smrg{"+nul", "*underLine", XrmoptionNoArg, (XPointer) "on"}, 100020d2c4d2Smrg{"-pc", "*boldColors", XrmoptionNoArg, (XPointer) "on"}, 100120d2c4d2Smrg{"+pc", "*boldColors", XrmoptionNoArg, (XPointer) "off"}, 100220d2c4d2Smrg{"-rw", "*reverseWrap", XrmoptionNoArg, (XPointer) "on"}, 100320d2c4d2Smrg{"+rw", "*reverseWrap", XrmoptionNoArg, (XPointer) "off"}, 100420d2c4d2Smrg{"-s", "*multiScroll", XrmoptionNoArg, (XPointer) "on"}, 100520d2c4d2Smrg{"+s", "*multiScroll", XrmoptionNoArg, (XPointer) "off"}, 100620d2c4d2Smrg{"-sb", "*scrollBar", XrmoptionNoArg, (XPointer) "on"}, 100720d2c4d2Smrg{"+sb", "*scrollBar", XrmoptionNoArg, (XPointer) "off"}, 1008d522f475Smrg#ifdef SCROLLBAR_RIGHT 100920d2c4d2Smrg{"-leftbar", "*rightScrollBar", XrmoptionNoArg, (XPointer) "off"}, 101020d2c4d2Smrg{"-rightbar", "*rightScrollBar", XrmoptionNoArg, (XPointer) "on"}, 101120d2c4d2Smrg#endif 101220d2c4d2Smrg{"-rvc", "*colorRVMode", XrmoptionNoArg, (XPointer) "off"}, 101320d2c4d2Smrg{"+rvc", "*colorRVMode", XrmoptionNoArg, (XPointer) "on"}, 101420d2c4d2Smrg{"-sf", "*sunFunctionKeys", XrmoptionNoArg, (XPointer) "on"}, 101520d2c4d2Smrg{"+sf", "*sunFunctionKeys", XrmoptionNoArg, (XPointer) "off"}, 101620d2c4d2Smrg{"-si", "*scrollTtyOutput", XrmoptionNoArg, (XPointer) "off"}, 101720d2c4d2Smrg{"+si", "*scrollTtyOutput", XrmoptionNoArg, (XPointer) "on"}, 101820d2c4d2Smrg{"-sk", "*scrollKey", XrmoptionNoArg, (XPointer) "on"}, 101920d2c4d2Smrg{"+sk", "*scrollKey", XrmoptionNoArg, (XPointer) "off"}, 102020d2c4d2Smrg{"-sl", "*saveLines", XrmoptionSepArg, (XPointer) NULL}, 1021d522f475Smrg#if OPT_SUNPC_KBD 102220d2c4d2Smrg{"-sp", "*sunKeyboard", XrmoptionNoArg, (XPointer) "on"}, 102320d2c4d2Smrg{"+sp", "*sunKeyboard", XrmoptionNoArg, (XPointer) "off"}, 1024d522f475Smrg#endif 1025d522f475Smrg#if OPT_TEK4014 102620d2c4d2Smrg{"-t", "*tekStartup", XrmoptionNoArg, (XPointer) "on"}, 102720d2c4d2Smrg{"+t", "*tekStartup", XrmoptionNoArg, (XPointer) "off"}, 1028d522f475Smrg#endif 102920d2c4d2Smrg{"-ti", "*decTerminalID",XrmoptionSepArg, (XPointer) NULL}, 103020d2c4d2Smrg{"-tm", "*ttyModes", XrmoptionSepArg, (XPointer) NULL}, 103120d2c4d2Smrg{"-tn", "*termName", XrmoptionSepArg, (XPointer) NULL}, 1032d522f475Smrg#if OPT_WIDE_CHARS 103320d2c4d2Smrg{"-u8", "*utf8", XrmoptionNoArg, (XPointer) "2"}, 103420d2c4d2Smrg{"+u8", "*utf8", XrmoptionNoArg, (XPointer) "0"}, 1035d522f475Smrg#endif 1036d522f475Smrg#if OPT_LUIT_PROG 103720d2c4d2Smrg{"-lc", "*locale", XrmoptionNoArg, (XPointer) "on"}, 103820d2c4d2Smrg{"+lc", "*locale", XrmoptionNoArg, (XPointer) "off"}, 103920d2c4d2Smrg{"-lcc", "*localeFilter",XrmoptionSepArg, (XPointer) NULL}, 104020d2c4d2Smrg{"-en", "*locale", XrmoptionSepArg, (XPointer) NULL}, 104120d2c4d2Smrg#endif 104220d2c4d2Smrg{"-uc", "*cursorUnderLine", XrmoptionNoArg, (XPointer) "on"}, 104320d2c4d2Smrg{"+uc", "*cursorUnderLine", XrmoptionNoArg, (XPointer) "off"}, 104420d2c4d2Smrg{"-ulc", "*colorULMode", XrmoptionNoArg, (XPointer) "off"}, 104520d2c4d2Smrg{"+ulc", "*colorULMode", XrmoptionNoArg, (XPointer) "on"}, 104620d2c4d2Smrg{"-ulit", "*italicULMode", XrmoptionNoArg, (XPointer) "off"}, 104720d2c4d2Smrg{"+ulit", "*italicULMode", XrmoptionNoArg, (XPointer) "on"}, 104820d2c4d2Smrg{"-ut", "*utmpInhibit", XrmoptionNoArg, (XPointer) "on"}, 104920d2c4d2Smrg{"+ut", "*utmpInhibit", XrmoptionNoArg, (XPointer) "off"}, 105020d2c4d2Smrg{"-im", "*useInsertMode", XrmoptionNoArg, (XPointer) "on"}, 105120d2c4d2Smrg{"+im", "*useInsertMode", XrmoptionNoArg, (XPointer) "off"}, 105220d2c4d2Smrg{"-vb", "*visualBell", XrmoptionNoArg, (XPointer) "on"}, 105320d2c4d2Smrg{"+vb", "*visualBell", XrmoptionNoArg, (XPointer) "off"}, 105420d2c4d2Smrg{"-pob", "*popOnBell", XrmoptionNoArg, (XPointer) "on"}, 105520d2c4d2Smrg{"+pob", "*popOnBell", XrmoptionNoArg, (XPointer) "off"}, 1056d522f475Smrg#if OPT_WIDE_CHARS 105720d2c4d2Smrg{"-wc", "*wideChars", XrmoptionNoArg, (XPointer) "on"}, 105820d2c4d2Smrg{"+wc", "*wideChars", XrmoptionNoArg, (XPointer) "off"}, 105920d2c4d2Smrg{"-mk_width", "*mkWidth", XrmoptionNoArg, (XPointer) "on"}, 106020d2c4d2Smrg{"+mk_width", "*mkWidth", XrmoptionNoArg, (XPointer) "off"}, 106120d2c4d2Smrg{"-cjk_width", "*cjkWidth", XrmoptionNoArg, (XPointer) "on"}, 106220d2c4d2Smrg{"+cjk_width", "*cjkWidth", XrmoptionNoArg, (XPointer) "off"}, 106320d2c4d2Smrg#endif 106420d2c4d2Smrg{"-wf", "*waitForMap", XrmoptionNoArg, (XPointer) "on"}, 106520d2c4d2Smrg{"+wf", "*waitForMap", XrmoptionNoArg, (XPointer) "off"}, 1066d522f475Smrg#if OPT_ZICONBEEP 106720d2c4d2Smrg{"-ziconbeep", "*zIconBeep", XrmoptionSepArg, (XPointer) NULL}, 1068d522f475Smrg#endif 1069d522f475Smrg#if OPT_SAME_NAME 107020d2c4d2Smrg{"-samename", "*sameName", XrmoptionNoArg, (XPointer) "on"}, 107120d2c4d2Smrg{"+samename", "*sameName", XrmoptionNoArg, (XPointer) "off"}, 1072d522f475Smrg#endif 1073d522f475Smrg#if OPT_SESSION_MGT 107420d2c4d2Smrg{"-sm", "*sessionMgt", XrmoptionNoArg, (XPointer) "on"}, 107520d2c4d2Smrg{"+sm", "*sessionMgt", XrmoptionNoArg, (XPointer) "off"}, 1076d522f475Smrg#endif 1077d522f475Smrg#if OPT_TOOLBAR 107820d2c4d2Smrg{"-tb", "*"XtNtoolBar, XrmoptionNoArg, (XPointer) "on"}, 107920d2c4d2Smrg{"+tb", "*"XtNtoolBar, XrmoptionNoArg, (XPointer) "off"}, 1080d522f475Smrg#endif 1081956cc18dSsnj#if OPT_MAXIMIZE 108220d2c4d2Smrg{"-maximized", "*maximized", XrmoptionNoArg, (XPointer) "on"}, 108320d2c4d2Smrg{"+maximized", "*maximized", XrmoptionNoArg, (XPointer) "off"}, 1084956cc18dSsnj#endif 1085d522f475Smrg/* options that we process ourselves */ 108620d2c4d2Smrg{"-help", NULL, XrmoptionSkipNArgs, (XPointer) NULL}, 108720d2c4d2Smrg{"-version", NULL, XrmoptionSkipNArgs, (XPointer) NULL}, 108820d2c4d2Smrg{"-class", NULL, XrmoptionSkipArg, (XPointer) NULL}, 108920d2c4d2Smrg{"-e", NULL, XrmoptionSkipLine, (XPointer) NULL}, 109020d2c4d2Smrg{"-into", NULL, XrmoptionSkipArg, (XPointer) NULL}, 1091d522f475Smrg/* bogus old compatibility stuff for which there are 1092d522f475Smrg standard XtOpenApplication options now */ 109320d2c4d2Smrg{"%", "*tekGeometry", XrmoptionStickyArg, (XPointer) NULL}, 109420d2c4d2Smrg{"#", ".iconGeometry",XrmoptionStickyArg, (XPointer) NULL}, 109520d2c4d2Smrg{"-T", ".title", XrmoptionSepArg, (XPointer) NULL}, 109620d2c4d2Smrg{"-n", "*iconName", XrmoptionSepArg, (XPointer) NULL}, 109720d2c4d2Smrg{"-r", "*reverseVideo",XrmoptionNoArg, (XPointer) "on"}, 109820d2c4d2Smrg{"+r", "*reverseVideo",XrmoptionNoArg, (XPointer) "off"}, 109920d2c4d2Smrg{"-rv", "*reverseVideo",XrmoptionNoArg, (XPointer) "on"}, 110020d2c4d2Smrg{"+rv", "*reverseVideo",XrmoptionNoArg, (XPointer) "off"}, 110120d2c4d2Smrg{"-w", ".borderWidth", XrmoptionSepArg, (XPointer) NULL}, 1102d522f475Smrg}; 1103d522f475Smrg 1104d522f475Smrgstatic OptionHelp xtermOptions[] = { 1105d522f475Smrg{ "-version", "print the version number" }, 1106d522f475Smrg{ "-help", "print out this message" }, 1107d522f475Smrg{ "-display displayname", "X server to contact" }, 1108d522f475Smrg{ "-geometry geom", "size (in characters) and position" }, 1109d522f475Smrg{ "-/+rv", "turn on/off reverse video" }, 1110d522f475Smrg{ "-bg color", "background color" }, 1111d522f475Smrg{ "-fg color", "foreground color" }, 1112d522f475Smrg{ "-bd color", "border color" }, 1113d522f475Smrg{ "-bw number", "border width in pixels" }, 1114d522f475Smrg{ "-fn fontname", "normal text font" }, 1115d522f475Smrg{ "-fb fontname", "bold text font" }, 1116d522f475Smrg{ "-/+fbb", "turn on/off normal/bold font comparison inhibit"}, 1117d522f475Smrg{ "-/+fbx", "turn off/on linedrawing characters"}, 1118d522f475Smrg#if OPT_RENDERFONT 1119d522f475Smrg{ "-fa pattern", "FreeType font-selection pattern" }, 1120d522f475Smrg{ "-fd pattern", "FreeType Doublesize font-selection pattern" }, 1121d522f475Smrg{ "-fs size", "FreeType font-size" }, 1122d522f475Smrg#endif 1123d522f475Smrg#if OPT_WIDE_CHARS 1124d522f475Smrg{ "-fw fontname", "doublewidth text font" }, 1125d522f475Smrg{ "-fwb fontname", "doublewidth bold text font" }, 1126d522f475Smrg#endif 1127d522f475Smrg#if OPT_INPUT_METHOD 1128d522f475Smrg{ "-fx fontname", "XIM fontset" }, 1129d522f475Smrg#endif 1130d522f475Smrg{ "-iconic", "start iconic" }, 1131d522f475Smrg{ "-name string", "client instance, icon, and title strings" }, 1132d522f475Smrg{ "-class string", "class string (XTerm)" }, 1133d522f475Smrg{ "-title string", "title string" }, 1134d522f475Smrg{ "-xrm resourcestring", "additional resource specifications" }, 1135d522f475Smrg{ "-/+132", "turn on/off 80/132 column switching" }, 1136d522f475Smrg{ "-/+ah", "turn on/off always highlight" }, 1137d522f475Smrg#ifndef NO_ACTIVE_ICON 1138d522f475Smrg{ "-/+ai", "turn off/on active icon" }, 1139d522f475Smrg{ "-fi fontname", "icon font for active icon" }, 1140d522f475Smrg#endif /* NO_ACTIVE_ICON */ 1141d522f475Smrg{ "-b number", "internal border in pixels" }, 1142d522f475Smrg{ "-/+bc", "turn on/off text cursor blinking" }, 1143d522f475Smrg{ "-bcf milliseconds", "time text cursor is off when blinking"}, 1144d522f475Smrg{ "-bcn milliseconds", "time text cursor is on when blinking"}, 1145d522f475Smrg{ "-/+bdc", "turn off/on display of bold as color"}, 1146d522f475Smrg{ "-/+cb", "turn on/off cut-to-beginning-of-line inhibit" }, 1147d522f475Smrg{ "-cc classrange", "specify additional character classes" }, 1148d522f475Smrg{ "-/+cm", "turn off/on ANSI color mode" }, 1149d522f475Smrg{ "-/+cn", "turn on/off cut newline inhibit" }, 1150d522f475Smrg{ "-cr color", "text cursor color" }, 1151d522f475Smrg{ "-/+cu", "turn on/off curses emulation" }, 1152d522f475Smrg{ "-/+dc", "turn off/on dynamic color selection" }, 1153d522f475Smrg#if OPT_HIGHLIGHT_COLOR 1154d522f475Smrg{ "-/+hm", "turn on/off selection-color override" }, 1155d522f475Smrg{ "-selbg color", "selection background color" }, 1156d522f475Smrg{ "-selfg color", "selection foreground color" }, 1157d522f475Smrg#endif 1158d522f475Smrg#if OPT_HP_FUNC_KEYS 1159d522f475Smrg{ "-/+hf", "turn on/off HP Function Key escape codes" }, 1160d522f475Smrg#endif 1161d522f475Smrg{ "-/+hold", "turn on/off logic that retains window after exit" }, 1162d522f475Smrg#if OPT_INITIAL_ERASE 1163d522f475Smrg{ "-/+ie", "turn on/off initialization of 'erase' from pty" }, 1164d522f475Smrg#endif 1165d522f475Smrg{ "-/+im", "use insert mode for TERMCAP" }, 1166d522f475Smrg{ "-/+j", "turn on/off jump scroll" }, 1167d522f475Smrg#if OPT_C1_PRINT 1168d522f475Smrg{ "-/+k8", "turn on/off C1-printable classification"}, 1169d522f475Smrg#endif 1170d522f475Smrg{ "-kt keyboardtype", "set keyboard type:" KEYBOARD_TYPES }, 1171d522f475Smrg#ifdef ALLOWLOGGING 1172d522f475Smrg{ "-/+l", "turn on/off logging" }, 1173d522f475Smrg{ "-lf filename", "logging filename" }, 1174d522f475Smrg#else 1175d522f475Smrg{ "-/+l", "turn on/off logging (not supported)" }, 1176d522f475Smrg{ "-lf filename", "logging filename (not supported)" }, 1177d522f475Smrg#endif 1178d522f475Smrg{ "-/+ls", "turn on/off login shell" }, 1179d522f475Smrg{ "-/+mb", "turn on/off margin bell" }, 1180d522f475Smrg{ "-mc milliseconds", "multiclick time in milliseconds" }, 1181d522f475Smrg{ "-/+mesg", "forbid/allow messages" }, 1182d522f475Smrg{ "-ms color", "pointer color" }, 1183d522f475Smrg{ "-nb number", "margin bell in characters from right end" }, 1184d522f475Smrg{ "-/+nul", "turn off/on display of underlining" }, 1185d522f475Smrg{ "-/+aw", "turn on/off auto wraparound" }, 1186d522f475Smrg{ "-/+pc", "turn on/off PC-style bold colors" }, 1187d522f475Smrg{ "-/+rw", "turn on/off reverse wraparound" }, 1188d522f475Smrg{ "-/+s", "turn on/off multiscroll" }, 1189d522f475Smrg{ "-/+sb", "turn on/off scrollbar" }, 1190d522f475Smrg#ifdef SCROLLBAR_RIGHT 1191d522f475Smrg{ "-rightbar", "force scrollbar right (default left)" }, 1192d522f475Smrg{ "-leftbar", "force scrollbar left" }, 1193d522f475Smrg#endif 1194d522f475Smrg{ "-/+rvc", "turn off/on display of reverse as color" }, 1195d522f475Smrg{ "-/+sf", "turn on/off Sun Function Key escape codes" }, 1196d522f475Smrg{ "-/+si", "turn on/off scroll-on-tty-output inhibit" }, 1197d522f475Smrg{ "-/+sk", "turn on/off scroll-on-keypress" }, 1198d522f475Smrg{ "-sl number", "number of scrolled lines to save" }, 1199d522f475Smrg#if OPT_SUNPC_KBD 1200d522f475Smrg{ "-/+sp", "turn on/off Sun/PC Function/Keypad mapping" }, 1201d522f475Smrg#endif 1202d522f475Smrg#if OPT_TEK4014 1203d522f475Smrg{ "-/+t", "turn on/off Tek emulation window" }, 1204d522f475Smrg#endif 1205d522f475Smrg#if OPT_TOOLBAR 1206d522f475Smrg{ "-/+tb", "turn on/off toolbar" }, 1207d522f475Smrg#endif 1208d522f475Smrg{ "-ti termid", "terminal identifier" }, 1209d522f475Smrg{ "-tm string", "terminal mode keywords and characters" }, 1210d522f475Smrg{ "-tn name", "TERM environment variable name" }, 1211d522f475Smrg#if OPT_WIDE_CHARS 1212d522f475Smrg{ "-/+u8", "turn on/off UTF-8 mode (implies wide-characters)" }, 1213d522f475Smrg#endif 1214d522f475Smrg#if OPT_LUIT_PROG 1215d522f475Smrg{ "-/+lc", "turn on/off locale mode using luit" }, 1216d522f475Smrg{ "-lcc path", "filename of locale converter (" DEFLOCALEFILTER ")" }, 1217d522f475Smrg#endif 12182eaa94a1Schristos{ "-/+uc", "turn on/off underline cursor" }, 1219d522f475Smrg{ "-/+ulc", "turn off/on display of underline as color" }, 1220d522f475Smrg{ "-/+ulit", "turn off/on display of underline as italics" }, 1221d522f475Smrg#ifdef HAVE_UTMP 1222d522f475Smrg{ "-/+ut", "turn on/off utmp support" }, 1223d522f475Smrg#else 1224d522f475Smrg{ "-/+ut", "turn on/off utmp support (not available)" }, 1225d522f475Smrg#endif 1226d522f475Smrg{ "-/+vb", "turn on/off visual bell" }, 1227d522f475Smrg{ "-/+pob", "turn on/off pop on bell" }, 1228d522f475Smrg#if OPT_WIDE_CHARS 1229d522f475Smrg{ "-/+wc", "turn on/off wide-character mode" }, 1230d522f475Smrg{ "-/+mk_width", "turn on/off simple width convention" }, 1231d522f475Smrg{ "-/+cjk_width", "turn on/off legacy CJK width convention" }, 1232d522f475Smrg#endif 1233d522f475Smrg{ "-/+wf", "turn on/off wait for map before command exec" }, 1234d522f475Smrg{ "-e command args ...", "command to execute" }, 1235d522f475Smrg#if OPT_TEK4014 1236d522f475Smrg{ "%geom", "Tek window geometry" }, 1237d522f475Smrg#endif 1238d522f475Smrg{ "#geom", "icon window geometry" }, 1239d522f475Smrg{ "-T string", "title name for window" }, 1240d522f475Smrg{ "-n string", "icon name for window" }, 1241d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 1242d522f475Smrg{ "-C", "intercept console messages" }, 1243d522f475Smrg#else 1244d522f475Smrg{ "-C", "intercept console messages (not supported)" }, 1245d522f475Smrg#endif 1246d522f475Smrg{ "-Sccn", "slave mode on \"ttycc\", file descriptor \"n\"" }, 1247d522f475Smrg{ "-into windowId", "use the window id given to -into as the parent window rather than the default root window" }, 1248d522f475Smrg#if OPT_ZICONBEEP 1249d522f475Smrg{ "-ziconbeep percent", "beep and flag icon of window having hidden output" }, 1250d522f475Smrg#endif 1251d522f475Smrg#if OPT_SAME_NAME 1252d522f475Smrg{ "-/+samename", "turn on/off the no-flicker option for title and icon name" }, 1253d522f475Smrg#endif 1254d522f475Smrg#if OPT_SESSION_MGT 1255d522f475Smrg{ "-/+sm", "turn on/off the session-management support" }, 1256d522f475Smrg#endif 1257956cc18dSsnj#if OPT_MAXIMIZE 1258956cc18dSsnj{"-/+maximized", "turn on/off maxmize on startup" }, 1259956cc18dSsnj#endif 1260d522f475Smrg{ NULL, NULL }}; 1261d522f475Smrg/* *INDENT-ON* */ 1262d522f475Smrg 126320d2c4d2Smrgstatic const char *message[] = 1264d522f475Smrg{ 1265d522f475Smrg "Fonts should be fixed width and, if both normal and bold are specified, should", 1266d522f475Smrg "have the same size. If only a normal font is specified, it will be used for", 1267d522f475Smrg "both normal and bold text (by doing overstriking). The -e option, if given,", 1268d522f475Smrg "must appear at the end of the command line, otherwise the user's default shell", 1269d522f475Smrg "will be started. Options that start with a plus sign (+) restore the default.", 1270d522f475Smrg NULL}; 1271d522f475Smrg 1272d522f475Smrg/* 1273d522f475Smrg * Decode a key-definition. This combines the termcap and ttyModes, for 1274d522f475Smrg * comparison. Note that octal escapes in ttyModes are done by the normal 1275d522f475Smrg * resource translation. Also, ttyModes allows '^-' as a synonym for disabled. 1276d522f475Smrg */ 1277d522f475Smrgstatic int 1278d522f475Smrgdecode_keyvalue(char **ptr, int termcap) 1279d522f475Smrg{ 1280d522f475Smrg char *string = *ptr; 1281d522f475Smrg int value = -1; 1282d522f475Smrg 128320d2c4d2Smrg TRACE(("decode_keyvalue '%s'\n", string)); 1284d522f475Smrg if (*string == '^') { 1285d522f475Smrg switch (*++string) { 1286d522f475Smrg case '?': 1287d522f475Smrg value = A2E(ANSI_DEL); 1288d522f475Smrg break; 1289d522f475Smrg case '-': 1290d522f475Smrg if (!termcap) { 1291d522f475Smrg errno = 0; 1292d522f475Smrg#if defined(_POSIX_VDISABLE) && defined(HAVE_UNISTD_H) 1293d522f475Smrg value = _POSIX_VDISABLE; 1294d522f475Smrg#endif 1295d522f475Smrg#if defined(_PC_VDISABLE) 1296d522f475Smrg if (value == -1) { 129720d2c4d2Smrg value = (int) fpathconf(0, _PC_VDISABLE); 1298d522f475Smrg if (value == -1) { 1299d522f475Smrg if (errno != 0) 1300d522f475Smrg break; /* skip this (error) */ 1301d522f475Smrg value = 0377; 1302d522f475Smrg } 1303d522f475Smrg } 1304d522f475Smrg#elif defined(VDISABLE) 1305d522f475Smrg if (value == -1) 1306d522f475Smrg value = VDISABLE; 1307d522f475Smrg#endif 1308d522f475Smrg break; 1309d522f475Smrg } 1310d522f475Smrg /* FALLTHRU */ 1311d522f475Smrg default: 1312d522f475Smrg value = CONTROL(*string); 1313d522f475Smrg break; 1314d522f475Smrg } 1315d522f475Smrg ++string; 1316d522f475Smrg } else if (termcap && (*string == '\\')) { 1317d522f475Smrg char *d; 131820d2c4d2Smrg int temp = (int) strtol(string + 1, &d, 8); 1319d522f475Smrg if (temp > 0 && d != string) { 1320d522f475Smrg value = temp; 1321d522f475Smrg string = d; 1322d522f475Smrg } 1323d522f475Smrg } else { 1324d522f475Smrg value = CharOf(*string); 1325d522f475Smrg ++string; 1326d522f475Smrg } 1327d522f475Smrg *ptr = string; 132820d2c4d2Smrg TRACE(("...decode_keyvalue %#x\n", value)); 1329d522f475Smrg return value; 1330d522f475Smrg} 1331d522f475Smrg 1332d522f475Smrgstatic int 133320d2c4d2Smrgabbrev(const char *tst, const char *cmp, size_t need) 1334d522f475Smrg{ 1335d522f475Smrg size_t len = strlen(tst); 1336d522f475Smrg return ((len >= need) && (!strncmp(tst, cmp, len))); 1337d522f475Smrg} 1338d522f475Smrg 1339d522f475Smrgstatic void 1340d522f475SmrgSyntax(char *badOption) 1341d522f475Smrg{ 1342d522f475Smrg OptionHelp *opt; 1343d522f475Smrg OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList)); 1344d522f475Smrg int col; 1345d522f475Smrg 1346d522f475Smrg fprintf(stderr, "%s: bad command line option \"%s\"\r\n\n", 1347d522f475Smrg ProgramName, badOption); 1348d522f475Smrg 1349d522f475Smrg fprintf(stderr, "usage: %s", ProgramName); 1350956cc18dSsnj col = 8 + (int) strlen(ProgramName); 1351d522f475Smrg for (opt = list; opt->opt; opt++) { 1352956cc18dSsnj int len = 3 + (int) strlen(opt->opt); /* space [ string ] */ 1353d522f475Smrg if (col + len > 79) { 1354d522f475Smrg fprintf(stderr, "\r\n "); /* 3 spaces */ 1355d522f475Smrg col = 3; 1356d522f475Smrg } 1357d522f475Smrg fprintf(stderr, " [%s]", opt->opt); 1358d522f475Smrg col += len; 1359d522f475Smrg } 1360d522f475Smrg 1361d522f475Smrg fprintf(stderr, "\r\n\nType %s -help for a full description.\r\n\n", 1362d522f475Smrg ProgramName); 1363d522f475Smrg exit(1); 1364d522f475Smrg} 1365d522f475Smrg 1366d522f475Smrgstatic void 1367d522f475SmrgVersion(void) 1368d522f475Smrg{ 1369d522f475Smrg printf("%s\n", xtermVersion()); 1370d522f475Smrg fflush(stdout); 1371d522f475Smrg} 1372d522f475Smrg 1373d522f475Smrgstatic void 1374d522f475SmrgHelp(void) 1375d522f475Smrg{ 1376d522f475Smrg OptionHelp *opt; 1377d522f475Smrg OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList)); 137820d2c4d2Smrg const char **cpp; 1379d522f475Smrg 1380d522f475Smrg printf("%s usage:\n %s [-options ...] [-e command args]\n\n", 1381d522f475Smrg xtermVersion(), ProgramName); 1382d522f475Smrg printf("where options include:\n"); 1383d522f475Smrg for (opt = list; opt->opt; opt++) { 1384d522f475Smrg printf(" %-28s %s\n", opt->opt, opt->desc); 1385d522f475Smrg } 1386d522f475Smrg 1387d522f475Smrg putchar('\n'); 1388d522f475Smrg for (cpp = message; *cpp; cpp++) 1389d522f475Smrg puts(*cpp); 1390d522f475Smrg putchar('\n'); 1391d522f475Smrg fflush(stdout); 1392d522f475Smrg} 1393d522f475Smrg 1394d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 1395d522f475Smrg/* ARGSUSED */ 1396d522f475Smrgstatic Boolean 1397d522f475SmrgConvertConsoleSelection(Widget w GCC_UNUSED, 1398d522f475Smrg Atom * selection GCC_UNUSED, 1399d522f475Smrg Atom * target GCC_UNUSED, 1400d522f475Smrg Atom * type GCC_UNUSED, 1401d522f475Smrg XtPointer *value GCC_UNUSED, 1402d522f475Smrg unsigned long *length GCC_UNUSED, 1403d522f475Smrg int *format GCC_UNUSED) 1404d522f475Smrg{ 1405d522f475Smrg /* we don't save console output, so can't offer it */ 1406d522f475Smrg return False; 1407d522f475Smrg} 1408d522f475Smrg#endif /* TIOCCONS */ 1409d522f475Smrg 1410d522f475Smrg#if OPT_SESSION_MGT 1411d522f475Smrgstatic void 1412d522f475Smrgdie_callback(Widget w GCC_UNUSED, 1413d522f475Smrg XtPointer client_data GCC_UNUSED, 1414d522f475Smrg XtPointer call_data GCC_UNUSED) 1415d522f475Smrg{ 1416d522f475Smrg Cleanup(0); 1417d522f475Smrg} 1418d522f475Smrg 1419d522f475Smrgstatic void 1420d522f475Smrgsave_callback(Widget w GCC_UNUSED, 1421d522f475Smrg XtPointer client_data GCC_UNUSED, 1422d522f475Smrg XtPointer call_data) 1423d522f475Smrg{ 1424d522f475Smrg XtCheckpointToken token = (XtCheckpointToken) call_data; 1425d522f475Smrg /* we have nothing to save */ 1426d522f475Smrg token->save_success = True; 1427d522f475Smrg} 1428d522f475Smrg 1429d522f475Smrgstatic void 1430d522f475Smrgicewatch(IceConn iceConn, 1431d522f475Smrg IcePointer clientData GCC_UNUSED, 1432d522f475Smrg Bool opening, 1433d522f475Smrg IcePointer * watchData GCC_UNUSED) 1434d522f475Smrg{ 1435d522f475Smrg if (opening) { 1436d522f475Smrg ice_fd = IceConnectionNumber(iceConn); 1437d522f475Smrg TRACE(("got IceConnectionNumber %d\n", ice_fd)); 1438d522f475Smrg } else { 1439d522f475Smrg ice_fd = -1; 1440d522f475Smrg TRACE(("reset IceConnectionNumber\n")); 1441d522f475Smrg } 1442d522f475Smrg} 1443d522f475Smrg 1444d522f475Smrg#endif /* OPT_SESSION_MGT */ 1445d522f475Smrg 1446d522f475Smrg/* 1447d522f475Smrg * DeleteWindow(): Action proc to implement ICCCM delete_window. 1448d522f475Smrg */ 1449d522f475Smrg/* ARGSUSED */ 1450d522f475Smrgstatic void 1451d522f475SmrgDeleteWindow(Widget w, 1452d522f475Smrg XEvent * event GCC_UNUSED, 1453d522f475Smrg String * params GCC_UNUSED, 1454d522f475Smrg Cardinal *num_params GCC_UNUSED) 1455d522f475Smrg{ 1456d522f475Smrg#if OPT_TEK4014 1457d522f475Smrg if (w == toplevel) { 1458d522f475Smrg if (TEK4014_SHOWN(term)) 1459d522f475Smrg hide_vt_window(); 1460d522f475Smrg else 1461d522f475Smrg do_hangup(w, (XtPointer) 0, (XtPointer) 0); 146220d2c4d2Smrg } else if (TScreenOf(term)->Vshow) 1463d522f475Smrg hide_tek_window(); 1464d522f475Smrg else 1465d522f475Smrg#endif 1466d522f475Smrg do_hangup(w, (XtPointer) 0, (XtPointer) 0); 1467d522f475Smrg} 1468d522f475Smrg 1469d522f475Smrg/* ARGSUSED */ 1470d522f475Smrgstatic void 1471d522f475SmrgKeyboardMapping(Widget w GCC_UNUSED, 1472d522f475Smrg XEvent * event, 1473d522f475Smrg String * params GCC_UNUSED, 1474d522f475Smrg Cardinal *num_params GCC_UNUSED) 1475d522f475Smrg{ 1476d522f475Smrg switch (event->type) { 1477d522f475Smrg case MappingNotify: 1478d522f475Smrg XRefreshKeyboardMapping(&event->xmapping); 1479d522f475Smrg break; 1480d522f475Smrg } 1481d522f475Smrg} 1482d522f475Smrg 1483d522f475Smrgstatic XtActionsRec actionProcs[] = 1484d522f475Smrg{ 1485d522f475Smrg {"DeleteWindow", DeleteWindow}, 1486d522f475Smrg {"KeyboardMapping", KeyboardMapping}, 1487d522f475Smrg}; 1488d522f475Smrg 1489d522f475Smrg/* 1490d522f475Smrg * Some platforms use names such as /dev/tty01, others /dev/pts/1. Parse off 1491d522f475Smrg * the "tty01" or "pts/1" portion, and return that for use as an identifier for 1492d522f475Smrg * utmp. 1493d522f475Smrg */ 1494d522f475Smrgstatic char * 1495d522f475Smrgmy_pty_name(char *device) 1496d522f475Smrg{ 1497d522f475Smrg size_t len = strlen(device); 1498d522f475Smrg Bool name = False; 1499d522f475Smrg 1500d522f475Smrg while (len != 0) { 1501d522f475Smrg int ch = device[len - 1]; 1502d522f475Smrg if (isdigit(ch)) { 1503d522f475Smrg len--; 1504d522f475Smrg } else if (ch == '/') { 1505d522f475Smrg if (name) 1506d522f475Smrg break; 1507d522f475Smrg len--; 1508d522f475Smrg } else if (isalpha(ch)) { 1509d522f475Smrg name = True; 1510d522f475Smrg len--; 1511d522f475Smrg } else { 1512d522f475Smrg break; 1513d522f475Smrg } 1514d522f475Smrg } 1515d522f475Smrg TRACE(("my_pty_name(%s) -> '%s'\n", device, device + len)); 1516d522f475Smrg return device + len; 1517d522f475Smrg} 1518d522f475Smrg 1519d522f475Smrg/* 1520d522f475Smrg * If the name contains a '/', it is a "pts/1" case. Otherwise, return the 1521d522f475Smrg * last few characters for a utmp identifier. 1522d522f475Smrg */ 1523d522f475Smrgstatic char * 1524d522f475Smrgmy_pty_id(char *device) 1525d522f475Smrg{ 1526d522f475Smrg char *name = my_pty_name(device); 1527d522f475Smrg char *leaf = x_basename(name); 1528d522f475Smrg 1529d522f475Smrg if (name == leaf) { /* no '/' in the name */ 1530956cc18dSsnj int len = (int) strlen(leaf); 1531d522f475Smrg if (PTYCHARLEN < len) 1532d522f475Smrg leaf = leaf + (len - PTYCHARLEN); 1533d522f475Smrg } 1534d522f475Smrg TRACE(("my_pty_id (%s) -> '%s'\n", device, leaf)); 1535d522f475Smrg return leaf; 1536d522f475Smrg} 1537d522f475Smrg 1538d522f475Smrg/* 1539d522f475Smrg * Set the tty/pty identifier 1540d522f475Smrg */ 1541d522f475Smrgstatic void 1542d522f475Smrgset_pty_id(char *device, char *id) 1543d522f475Smrg{ 1544d522f475Smrg char *name = my_pty_name(device); 1545d522f475Smrg char *leaf = x_basename(name); 1546d522f475Smrg 1547d522f475Smrg if (name == leaf) { 1548d522f475Smrg strcpy(my_pty_id(device), id); 1549d522f475Smrg } else { 1550d522f475Smrg strcpy(leaf, id); 1551d522f475Smrg } 1552d522f475Smrg TRACE(("set_pty_id(%s) -> '%s'\n", id, device)); 1553d522f475Smrg} 1554d522f475Smrg 1555d522f475Smrg/* 1556d522f475Smrg * The original -S option accepts two characters to identify the pty, and a 1557d522f475Smrg * file-descriptor (assumed to be nonzero). That is not general enough, so we 1558d522f475Smrg * check first if the option contains a '/' to delimit the two fields, and if 1559d522f475Smrg * not, fall-thru to the original logic. 1560d522f475Smrg */ 1561d522f475Smrgstatic Bool 1562d522f475SmrgParseSccn(char *option) 1563d522f475Smrg{ 1564d522f475Smrg char *leaf = x_basename(option); 1565d522f475Smrg Bool code = False; 1566d522f475Smrg 1567d522f475Smrg if (leaf != option) { 1568d522f475Smrg if (leaf - option > 0 1569d522f475Smrg && isdigit(CharOf(*leaf)) 1570d522f475Smrg && sscanf(leaf, "%d", &am_slave) == 1) { 1571956cc18dSsnj size_t len = (size_t) (leaf - option - 1); 1572d522f475Smrg /* 1573d522f475Smrg * If we have a slash, we only care about the part after the slash, 1574d522f475Smrg * which is a file-descriptor. The part before the slash can be 1575d522f475Smrg * the /dev/pts/XXX value, but since we do not need to reopen it, 1576d522f475Smrg * it is useful mainly for display in a "ps -ef". 1577d522f475Smrg */ 1578d522f475Smrg strncpy(passedPty, option, len); 1579d522f475Smrg passedPty[len] = 0; 1580d522f475Smrg code = True; 1581d522f475Smrg } 1582d522f475Smrg } else { 1583d522f475Smrg code = (sscanf(option, "%c%c%d", 1584d522f475Smrg passedPty, passedPty + 1, &am_slave) == 3); 1585d522f475Smrg } 1586d522f475Smrg TRACE(("ParseSccn(%s) = '%s' %d (%s)\n", option, 1587d522f475Smrg passedPty, am_slave, code ? "OK" : "ERR")); 1588d522f475Smrg return code; 1589d522f475Smrg} 1590d522f475Smrg 1591d522f475Smrg#if defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 1592d522f475Smrg/* 1593d522f475Smrg * From "man utmp": 1594d522f475Smrg * xterm and other terminal emulators directly create a USER_PROCESS record 1595d522f475Smrg * and generate the ut_id by using the last two letters of /dev/ttyp%c or by 1596d522f475Smrg * using p%d for /dev/pts/%d. If they find a DEAD_PROCESS for this id, they 1597d522f475Smrg * recycle it, otherwise they create a new entry. If they can, they will mark 1598d522f475Smrg * it as DEAD_PROCESS on exiting and it is advised that they null ut_line, 1599d522f475Smrg * ut_time, ut_user and ut_host as well. 1600d522f475Smrg * 1601d522f475Smrg * Generally ut_id allows no more than 3 characters (plus null), even if the 1602d522f475Smrg * pty implementation allows more than 3 digits. 1603d522f475Smrg */ 1604d522f475Smrgstatic char * 1605d522f475Smrgmy_utmp_id(char *device) 1606d522f475Smrg{ 1607d522f475Smrg typedef struct UTMP_STR UTMP_STRUCT; 1608d522f475Smrg#define UTIDSIZE (sizeof(((UTMP_STRUCT *)NULL)->ut_id)) 1609d522f475Smrg static char result[UTIDSIZE + 1]; 1610d522f475Smrg 1611d522f475Smrg#if defined(__SCO__) || defined(__UNIXWARE__) 1612d522f475Smrg /* 1613d522f475Smrg * Legend does not support old-style pty's, has no related compatibility 1614d522f475Smrg * issues, and can use the available space in ut_id differently from the 1615d522f475Smrg * default convention. 1616d522f475Smrg * 1617d522f475Smrg * This scheme is intended to avoid conflicts both with other users of 1618d522f475Smrg * utmpx as well as between multiple xterms. First, Legend uses all of the 1619d522f475Smrg * characters of ut_id, and adds no terminating NUL is required (the 1620d522f475Smrg * default scheme may add a trailing NUL). Second, all xterm entries will 1621d522f475Smrg * start with the letter 'x' followed by three digits, which will be the 1622d522f475Smrg * last three digits of the device name, regardless of the format of the 1623d522f475Smrg * device name, with leading 0's added where necessary. For instance, an 1624d522f475Smrg * xterm on /dev/pts/3 will have a ut_id of x003; an xterm on /dev/pts123 1625d522f475Smrg * will have a ut_id of x123. Under the other convention, /dev/pts/3 would 1626d522f475Smrg * have a ut_id of p3 and /dev/pts123 would have a ut_id of p123. 1627d522f475Smrg */ 1628d522f475Smrg int len, n; 1629d522f475Smrg 1630d522f475Smrg len = strlen(device); 1631d522f475Smrg n = UTIDSIZE; 1632d522f475Smrg result[n] = '\0'; 1633d522f475Smrg while ((n > 0) && (len > 0) && isdigit(device[len - 1])) 1634d522f475Smrg result[--n] = device[--len]; 1635d522f475Smrg while (n > 0) 1636d522f475Smrg result[--n] = '0'; 1637d522f475Smrg result[0] = 'x'; 1638d522f475Smrg#else 1639d522f475Smrg char *name = my_pty_name(device); 1640d522f475Smrg char *leaf = x_basename(name); 1641d522f475Smrg size_t len = strlen(leaf); 1642d522f475Smrg 1643d522f475Smrg if ((UTIDSIZE - 1) < len) 1644d522f475Smrg leaf = leaf + (len - (UTIDSIZE - 1)); 1645d522f475Smrg sprintf(result, "p%s", leaf); 1646d522f475Smrg#endif 1647d522f475Smrg 1648d522f475Smrg TRACE(("my_utmp_id (%s) -> '%s'\n", device, result)); 1649d522f475Smrg return result; 1650d522f475Smrg} 1651d522f475Smrg#endif /* USE_SYSV_UTMP */ 1652d522f475Smrg 1653d522f475Smrg#ifdef USE_POSIX_SIGNALS 1654d522f475Smrg 1655d522f475Smrgtypedef void (*sigfunc) (int); 1656d522f475Smrg 1657d522f475Smrg/* make sure we sure we ignore SIGCHLD for the cases parent 1658d522f475Smrg has just been stopped and not actually killed */ 1659d522f475Smrg 1660d522f475Smrgstatic sigfunc 1661d522f475Smrgposix_signal(int signo, sigfunc func) 1662d522f475Smrg{ 1663d522f475Smrg struct sigaction act, oact; 1664d522f475Smrg 1665d522f475Smrg act.sa_handler = func; 1666d522f475Smrg sigemptyset(&act.sa_mask); 1667d522f475Smrg#ifdef SA_RESTART 1668d522f475Smrg act.sa_flags = SA_NOCLDSTOP | SA_RESTART; 1669d522f475Smrg#else 1670d522f475Smrg act.sa_flags = SA_NOCLDSTOP; 1671d522f475Smrg#endif 1672d522f475Smrg if (sigaction(signo, &act, &oact) < 0) 1673d522f475Smrg return (SIG_ERR); 1674d522f475Smrg return (oact.sa_handler); 1675d522f475Smrg} 1676d522f475Smrg 1677d522f475Smrg#endif /* linux && _POSIX_SOURCE */ 1678d522f475Smrg 1679d522f475Smrg#if defined(DISABLE_SETUID) || defined(USE_UTMP_SETGID) 1680d522f475Smrgstatic void 1681d522f475SmrgdisableSetUid(void) 1682d522f475Smrg{ 1683d522f475Smrg TRACE(("process %d disableSetUid\n", (int) getpid())); 1684d522f475Smrg if (setuid(save_ruid) == -1) { 1685d522f475Smrg fprintf(stderr, "%s: unable to reset uid\n", ProgramName); 1686d522f475Smrg exit(1); 1687d522f475Smrg } 1688d522f475Smrg TRACE_IDS; 1689d522f475Smrg} 1690d522f475Smrg#else 1691d522f475Smrg#define disableSetUid() /* nothing */ 1692d522f475Smrg#endif /* DISABLE_SETUID */ 1693d522f475Smrg 1694d522f475Smrg#if defined(DISABLE_SETGID) || defined(USE_UTMP_SETGID) 1695d522f475Smrgstatic void 1696d522f475SmrgdisableSetGid(void) 1697d522f475Smrg{ 1698d522f475Smrg TRACE(("process %d disableSetGid\n", (int) getpid())); 1699d522f475Smrg if (setegid(save_rgid) == -1) { 1700d522f475Smrg fprintf(stderr, "%s: unable to reset effective gid\n", ProgramName); 1701d522f475Smrg exit(1); 1702d522f475Smrg } 1703d522f475Smrg TRACE_IDS; 1704d522f475Smrg} 1705d522f475Smrg#else 1706d522f475Smrg#define disableSetGid() /* nothing */ 1707d522f475Smrg#endif /* DISABLE_SETGID */ 1708d522f475Smrg 1709d522f475Smrg#if defined(HAVE_POSIX_SAVED_IDS) 1710d522f475Smrg#if (!defined(USE_UTEMPTER) || !defined(DISABLE_SETGID)) 1711d522f475Smrgstatic void 1712d522f475SmrgsetEffectiveGroup(gid_t group) 1713d522f475Smrg{ 1714d522f475Smrg TRACE(("process %d setEffectiveGroup(%d)\n", (int) getpid(), (int) group)); 1715d522f475Smrg if (setegid(group) == -1) { 1716d522f475Smrg#ifdef __MVS__ 1717d522f475Smrg if (!(errno == EMVSERR)) /* could happen if _BPX_SHAREAS=REUSE */ 1718d522f475Smrg#endif 1719d522f475Smrg { 1720d522f475Smrg (void) fprintf(stderr, "setegid(%d): %s\n", 1721d522f475Smrg (int) group, strerror(errno)); 1722d522f475Smrg } 1723d522f475Smrg } 1724d522f475Smrg TRACE_IDS; 1725d522f475Smrg} 1726d522f475Smrg#endif 1727d522f475Smrg 1728d522f475Smrg#if !defined(USE_UTMP_SETGID) && (!defined(USE_UTEMPTER) || !defined(DISABLE_SETUID)) 1729d522f475Smrgstatic void 1730d522f475SmrgsetEffectiveUser(uid_t user) 1731d522f475Smrg{ 1732d522f475Smrg TRACE(("process %d setEffectiveUser(%d)\n", (int) getpid(), (int) user)); 1733d522f475Smrg if (seteuid(user) == -1) { 1734d522f475Smrg#ifdef __MVS__ 1735d522f475Smrg if (!(errno == EMVSERR)) 1736d522f475Smrg#endif 1737d522f475Smrg { 1738d522f475Smrg (void) fprintf(stderr, "seteuid(%d): %s\n", 1739d522f475Smrg (int) user, strerror(errno)); 1740d522f475Smrg } 1741d522f475Smrg } 1742d522f475Smrg TRACE_IDS; 1743d522f475Smrg} 1744d522f475Smrg#endif 1745d522f475Smrg#endif /* HAVE_POSIX_SAVED_IDS */ 1746d522f475Smrg 1747d522f475Smrgint 1748d522f475Smrgmain(int argc, char *argv[]ENVP_ARG) 1749d522f475Smrg{ 1750d522f475Smrg Widget form_top, menu_top; 1751d522f475Smrg Dimension menu_high; 1752d522f475Smrg TScreen *screen; 1753d522f475Smrg int mode; 1754d522f475Smrg char *my_class = DEFCLASS; 1755d522f475Smrg Window winToEmbedInto = None; 1756d522f475Smrg#if OPT_COLOR_RES 1757d522f475Smrg Bool reversed = False; 1758d522f475Smrg#endif 1759d522f475Smrg 1760d522f475Smrg ProgramName = argv[0]; 1761d522f475Smrg 1762d522f475Smrg#ifdef HAVE_POSIX_SAVED_IDS 1763d522f475Smrg save_euid = geteuid(); 1764d522f475Smrg save_egid = getegid(); 1765d522f475Smrg#endif 1766d522f475Smrg 1767d522f475Smrg save_ruid = getuid(); 1768d522f475Smrg save_rgid = getgid(); 1769d522f475Smrg 1770d522f475Smrg#if defined(DISABLE_SETUID) || defined(DISABLE_SETGID) 1771d522f475Smrg#if defined(DISABLE_SETUID) 1772d522f475Smrg disableSetUid(); 1773d522f475Smrg#endif 1774d522f475Smrg#if defined(DISABLE_SETGID) 1775d522f475Smrg disableSetGid(); 1776d522f475Smrg#endif 1777d522f475Smrg TRACE_IDS; 1778d522f475Smrg#endif 1779d522f475Smrg 1780d522f475Smrg /* extra length in case longer tty name like /dev/ttyq255 */ 1781d522f475Smrg ttydev = TypeMallocN(char, sizeof(TTYDEV) + 80); 1782d522f475Smrg#ifdef USE_PTY_DEVICE 1783d522f475Smrg ptydev = TypeMallocN(char, sizeof(PTYDEV) + 80); 1784d522f475Smrg if (!ttydev || !ptydev) 1785d522f475Smrg#else 1786d522f475Smrg if (!ttydev) 1787d522f475Smrg#endif 1788d522f475Smrg { 1789d522f475Smrg fprintf(stderr, 1790d522f475Smrg "%s: unable to allocate memory for ttydev or ptydev\n", 1791d522f475Smrg ProgramName); 1792d522f475Smrg exit(1); 1793d522f475Smrg } 1794d522f475Smrg strcpy(ttydev, TTYDEV); 1795d522f475Smrg#ifdef USE_PTY_DEVICE 1796d522f475Smrg strcpy(ptydev, PTYDEV); 1797d522f475Smrg#endif 1798d522f475Smrg 1799d522f475Smrg#if defined(USE_UTMP_SETGID) 1800d522f475Smrg get_pty(NULL, NULL); 1801d522f475Smrg disableSetUid(); 1802d522f475Smrg disableSetGid(); 1803d522f475Smrg TRACE_IDS; 1804d522f475Smrg#define get_pty(pty, from) really_get_pty(pty, from) 1805d522f475Smrg#endif 1806d522f475Smrg 1807d522f475Smrg /* Do these first, since we may not be able to open the display */ 1808d522f475Smrg TRACE_OPTS(xtermOptions, optionDescList, XtNumber(optionDescList)); 1809d522f475Smrg TRACE_ARGV("Before XtOpenApplication", argv); 1810d522f475Smrg if (argc > 1) { 1811d522f475Smrg int n; 1812956cc18dSsnj size_t unique = 2; 1813d522f475Smrg Bool quit = True; 1814d522f475Smrg 1815d522f475Smrg for (n = 1; n < argc; n++) { 1816d522f475Smrg TRACE(("parsing %s\n", argv[n])); 1817d522f475Smrg if (abbrev(argv[n], "-version", unique)) { 1818d522f475Smrg Version(); 1819d522f475Smrg } else if (abbrev(argv[n], "-help", unique)) { 1820d522f475Smrg Help(); 182120d2c4d2Smrg } else if (abbrev(argv[n], "-class", (size_t) 3)) { 1822d522f475Smrg if ((my_class = argv[++n]) == 0) { 1823d522f475Smrg Help(); 1824d522f475Smrg } else { 1825d522f475Smrg quit = False; 1826d522f475Smrg } 1827d522f475Smrg unique = 3; 1828d522f475Smrg } else { 1829d522f475Smrg#if OPT_COLOR_RES 183020d2c4d2Smrg if (abbrev(argv[n], "-reverse", (size_t) 2) 1831d522f475Smrg || !strcmp("-rv", argv[n])) { 1832d522f475Smrg reversed = True; 1833d522f475Smrg } else if (!strcmp("+rv", argv[n])) { 1834d522f475Smrg reversed = False; 1835d522f475Smrg } 1836d522f475Smrg#endif 1837d522f475Smrg quit = False; 1838d522f475Smrg unique = 3; 1839d522f475Smrg } 1840d522f475Smrg } 1841d522f475Smrg if (quit) 1842d522f475Smrg exit(0); 1843d522f475Smrg } 1844d522f475Smrg 1845d522f475Smrg /* This dumps core on HP-UX 9.05 with X11R5 */ 1846d522f475Smrg#if OPT_I18N_SUPPORT 1847d522f475Smrg XtSetLanguageProc(NULL, NULL, NULL); 1848d522f475Smrg#endif 1849d522f475Smrg 1850d522f475Smrg#ifdef TERMIO_STRUCT /* { */ 1851d522f475Smrg /* Initialization is done here rather than above in order 1852d522f475Smrg * to prevent any assumptions about the order of the contents 1853d522f475Smrg * of the various terminal structures (which may change from 1854d522f475Smrg * implementation to implementation). 1855d522f475Smrg */ 1856d522f475Smrg memset(&d_tio, 0, sizeof(d_tio)); 1857d522f475Smrg d_tio.c_iflag = ICRNL | IXON; 1858d522f475Smrg#ifdef TAB3 1859d522f475Smrg d_tio.c_oflag = OPOST | ONLCR | TAB3; 1860d522f475Smrg#else 1861d522f475Smrg#ifdef ONLCR 1862d522f475Smrg d_tio.c_oflag = OPOST | ONLCR; 1863d522f475Smrg#else 1864d522f475Smrg d_tio.c_oflag = OPOST; 1865d522f475Smrg#endif 1866d522f475Smrg#endif 1867d522f475Smrg { 1868d522f475Smrg Cardinal nn; 1869d522f475Smrg 1870d522f475Smrg /* fill in default-values */ 1871d522f475Smrg for (nn = 0; nn < XtNumber(known_ttyChars); ++nn) { 1872d522f475Smrg if (validTtyChar(d_tio, nn)) { 1873d522f475Smrg d_tio.c_cc[known_ttyChars[nn].sysMode] = 1874d522f475Smrg known_ttyChars[nn].myDefault; 1875d522f475Smrg } 1876d522f475Smrg } 1877d522f475Smrg } 1878d522f475Smrg#if defined(macII) || defined(ATT) || defined(CRAY) /* { */ 1879d522f475Smrg d_tio.c_cflag = VAL_LINE_SPEED | CS8 | CREAD | PARENB | HUPCL; 1880d522f475Smrg d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK; 1881d522f475Smrg#ifdef ECHOKE 1882d522f475Smrg d_tio.c_lflag |= ECHOKE | IEXTEN; 1883d522f475Smrg#endif 1884d522f475Smrg#ifdef ECHOCTL 1885d522f475Smrg d_tio.c_lflag |= ECHOCTL | IEXTEN; 1886d522f475Smrg#endif 1887d522f475Smrg#ifndef USE_TERMIOS /* { */ 1888d522f475Smrg d_tio.c_line = 0; 1889d522f475Smrg#endif /* } */ 1890d522f475Smrg#ifdef HAS_LTCHARS /* { */ 1891d522f475Smrg d_ltc.t_suspc = CSUSP; /* t_suspc */ 1892d522f475Smrg d_ltc.t_dsuspc = CDSUSP; /* t_dsuspc */ 1893d522f475Smrg d_ltc.t_rprntc = CRPRNT; 1894d522f475Smrg d_ltc.t_flushc = CFLUSH; 1895d522f475Smrg d_ltc.t_werasc = CWERASE; 1896d522f475Smrg d_ltc.t_lnextc = CLNEXT; 1897d522f475Smrg#endif /* } HAS_LTCHARS */ 1898d522f475Smrg#ifdef TIOCLSET /* { */ 1899d522f475Smrg d_lmode = 0; 1900d522f475Smrg#endif /* } TIOCLSET */ 1901d522f475Smrg#else /* }{ else !macII, ATT, CRAY */ 1902d522f475Smrg#ifndef USE_POSIX_TERMIOS 1903d522f475Smrg#ifdef BAUD_0 /* { */ 1904d522f475Smrg d_tio.c_cflag = CS8 | CREAD | PARENB | HUPCL; 1905d522f475Smrg#else /* }{ !BAUD_0 */ 1906d522f475Smrg d_tio.c_cflag = VAL_LINE_SPEED | CS8 | CREAD | PARENB | HUPCL; 1907d522f475Smrg#endif /* } !BAUD_0 */ 1908d522f475Smrg#else /* USE_POSIX_TERMIOS */ 1909d522f475Smrg d_tio.c_cflag = CS8 | CREAD | PARENB | HUPCL; 1910d522f475Smrg cfsetispeed(&d_tio, VAL_LINE_SPEED); 1911d522f475Smrg cfsetospeed(&d_tio, VAL_LINE_SPEED); 1912d522f475Smrg#endif 1913d522f475Smrg d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK; 1914d522f475Smrg#ifdef ECHOKE 1915d522f475Smrg d_tio.c_lflag |= ECHOKE | IEXTEN; 1916d522f475Smrg#endif 1917d522f475Smrg#ifdef ECHOCTL 1918d522f475Smrg d_tio.c_lflag |= ECHOCTL | IEXTEN; 1919d522f475Smrg#endif 1920d522f475Smrg#ifndef USE_POSIX_TERMIOS 1921d522f475Smrg#ifdef NTTYDISC 1922d522f475Smrg d_tio.c_line = NTTYDISC; 1923d522f475Smrg#else 1924d522f475Smrg d_tio.c_line = 0; 1925d522f475Smrg#endif 1926d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 1927d522f475Smrg#ifdef __sgi 1928d522f475Smrg d_tio.c_cflag &= ~(HUPCL | PARENB); 1929d522f475Smrg d_tio.c_iflag |= BRKINT | ISTRIP | IGNPAR; 1930d522f475Smrg#endif 1931d522f475Smrg#ifdef __MVS__ 1932d522f475Smrg d_tio.c_cflag &= ~(HUPCL | PARENB); 1933d522f475Smrg#endif 1934d522f475Smrg { 1935d522f475Smrg Cardinal nn; 1936d522f475Smrg int i; 1937d522f475Smrg 1938d522f475Smrg /* try to inherit tty settings */ 1939d522f475Smrg for (i = 0; i <= 2; i++) { 1940d522f475Smrg TERMIO_STRUCT deftio; 1941d522f475Smrg if (ttyGetAttr(i, &deftio) == 0) { 1942d522f475Smrg for (nn = 0; nn < XtNumber(known_ttyChars); ++nn) { 1943d522f475Smrg if (validTtyChar(d_tio, nn)) { 1944d522f475Smrg d_tio.c_cc[known_ttyChars[nn].sysMode] = 1945d522f475Smrg deftio.c_cc[known_ttyChars[nn].sysMode]; 1946d522f475Smrg } 1947d522f475Smrg } 1948d522f475Smrg break; 1949d522f475Smrg } 1950d522f475Smrg } 1951d522f475Smrg } 1952d522f475Smrg#if defined(USE_TERMIOS) || defined(USE_POSIX_TERMIOS) /* { */ 1953d522f475Smrg d_tio.c_cc[VMIN] = 1; 1954d522f475Smrg d_tio.c_cc[VTIME] = 0; 1955d522f475Smrg#endif /* } */ 1956d522f475Smrg#ifdef HAS_LTCHARS /* { */ 1957d522f475Smrg d_ltc.t_suspc = CharOf('\000'); /* t_suspc */ 1958d522f475Smrg d_ltc.t_dsuspc = CharOf('\000'); /* t_dsuspc */ 1959d522f475Smrg d_ltc.t_rprntc = CharOf('\377'); /* reserved... */ 1960d522f475Smrg d_ltc.t_flushc = CharOf('\377'); 1961d522f475Smrg d_ltc.t_werasc = CharOf('\377'); 1962d522f475Smrg d_ltc.t_lnextc = CharOf('\377'); 1963d522f475Smrg#endif /* } HAS_LTCHARS */ 1964d522f475Smrg 1965d522f475Smrg#ifdef TIOCLSET /* { */ 1966d522f475Smrg d_lmode = 0; 1967d522f475Smrg#endif /* } TIOCLSET */ 1968d522f475Smrg#endif /* } macII, ATT, CRAY */ 1969d522f475Smrg#endif /* } TERMIO_STRUCT */ 1970d522f475Smrg 1971d522f475Smrg /* Init the Toolkit. */ 1972d522f475Smrg { 1973d522f475Smrg#if defined(HAVE_POSIX_SAVED_IDS) && !defined(USE_UTMP_SETGID) && !defined(USE_UTEMPTER) 1974d522f475Smrg setEffectiveGroup(save_rgid); 1975d522f475Smrg setEffectiveUser(save_ruid); 1976d522f475Smrg TRACE_IDS; 1977d522f475Smrg#endif 1978d522f475Smrg 1979d522f475Smrg XtSetErrorHandler(xt_error); 1980d522f475Smrg#if OPT_SESSION_MGT 1981d522f475Smrg toplevel = XtOpenApplication(&app_con, my_class, 1982d522f475Smrg optionDescList, 1983d522f475Smrg XtNumber(optionDescList), 1984d522f475Smrg &argc, argv, fallback_resources, 1985d522f475Smrg sessionShellWidgetClass, 1986d522f475Smrg NULL, 0); 1987d522f475Smrg IceAddConnectionWatch(icewatch, NULL); 1988d522f475Smrg#else 1989d522f475Smrg toplevel = XtAppInitialize(&app_con, my_class, 1990d522f475Smrg optionDescList, 1991d522f475Smrg XtNumber(optionDescList), 1992d522f475Smrg &argc, argv, fallback_resources, 1993d522f475Smrg NULL, 0); 1994d522f475Smrg#endif /* OPT_SESSION_MGT */ 1995d522f475Smrg XtSetErrorHandler((XtErrorHandler) 0); 1996d522f475Smrg 1997d522f475Smrg XtGetApplicationResources(toplevel, (XtPointer) &resource, 1998d522f475Smrg application_resources, 1999d522f475Smrg XtNumber(application_resources), NULL, 0); 2000d522f475Smrg TRACE_XRES(); 2001d522f475Smrg#if OPT_PTY_HANDSHAKE 2002d522f475Smrg resource.wait_for_map0 = resource.wait_for_map; 2003d522f475Smrg#endif 2004d522f475Smrg 2005d522f475Smrg#if defined(HAVE_POSIX_SAVED_IDS) && !defined(USE_UTMP_SETGID) 2006d522f475Smrg#if !defined(DISABLE_SETUID) || !defined(DISABLE_SETGID) 2007d522f475Smrg#if !defined(DISABLE_SETUID) 2008d522f475Smrg setEffectiveUser(save_euid); 2009d522f475Smrg#endif 2010d522f475Smrg#if !defined(DISABLE_SETGID) 2011d522f475Smrg setEffectiveGroup(save_egid); 2012d522f475Smrg#endif 2013d522f475Smrg TRACE_IDS; 2014d522f475Smrg#endif 2015d522f475Smrg#endif 2016d522f475Smrg } 2017d522f475Smrg 2018d522f475Smrg /* 2019d522f475Smrg * ICCCM delete_window. 2020d522f475Smrg */ 2021d522f475Smrg XtAppAddActions(app_con, actionProcs, XtNumber(actionProcs)); 2022d522f475Smrg 2023d522f475Smrg /* 2024d522f475Smrg * fill in terminal modes 2025d522f475Smrg */ 2026d522f475Smrg if (resource.tty_modes) { 2027d522f475Smrg int n = parse_tty_modes(resource.tty_modes, ttymodelist); 2028d522f475Smrg if (n < 0) { 2029d522f475Smrg fprintf(stderr, "%s: bad tty modes \"%s\"\n", 2030d522f475Smrg ProgramName, resource.tty_modes); 2031d522f475Smrg } else if (n > 0) { 2032d522f475Smrg override_tty_modes = True; 2033d522f475Smrg } 2034d522f475Smrg } 2035d522f475Smrg#if OPT_ZICONBEEP 2036d522f475Smrg if (resource.zIconBeep > 100 || resource.zIconBeep < -100) { 2037d522f475Smrg resource.zIconBeep = 0; /* was 100, but I prefer to defaulting off. */ 2038d522f475Smrg fprintf(stderr, 2039d522f475Smrg "a number between -100 and 100 is required for zIconBeep. 0 used by default\n"); 2040d522f475Smrg } 2041d522f475Smrg#endif /* OPT_ZICONBEEP */ 2042d522f475Smrg hold_screen = resource.hold_screen ? 1 : 0; 2043d522f475Smrg xterm_name = resource.xterm_name; 2044d522f475Smrg if (strcmp(xterm_name, "-") == 0) 2045d522f475Smrg xterm_name = DFT_TERMTYPE; 2046d522f475Smrg if (resource.icon_geometry != NULL) { 2047d522f475Smrg int scr, junk; 2048d522f475Smrg int ix, iy; 2049d522f475Smrg Arg args[2]; 2050d522f475Smrg 2051d522f475Smrg for (scr = 0; /* yyuucchh */ 2052d522f475Smrg XtScreen(toplevel) != ScreenOfDisplay(XtDisplay(toplevel), scr); 2053d522f475Smrg scr++) ; 2054d522f475Smrg 2055d522f475Smrg args[0].name = XtNiconX; 2056d522f475Smrg args[1].name = XtNiconY; 2057d522f475Smrg XGeometry(XtDisplay(toplevel), scr, resource.icon_geometry, "", 2058d522f475Smrg 0, 0, 0, 0, 0, &ix, &iy, &junk, &junk); 2059d522f475Smrg args[0].value = (XtArgVal) ix; 2060d522f475Smrg args[1].value = (XtArgVal) iy; 2061d522f475Smrg XtSetValues(toplevel, args, 2); 2062d522f475Smrg } 2063d522f475Smrg 2064d522f475Smrg XtSetValues(toplevel, ourTopLevelShellArgs, 2065d522f475Smrg number_ourTopLevelShellArgs); 2066d522f475Smrg 2067d522f475Smrg#if OPT_WIDE_CHARS 2068d522f475Smrg /* seems as good a place as any */ 2069d522f475Smrg init_classtab(); 2070d522f475Smrg#endif 2071d522f475Smrg 2072d522f475Smrg /* Parse the rest of the command line */ 2073d522f475Smrg TRACE_ARGV("After XtOpenApplication", argv); 2074d522f475Smrg for (argc--, argv++; argc > 0; argc--, argv++) { 2075d522f475Smrg#ifdef VMS 2076d522f475Smrg if (**argv != '-') 2077d522f475Smrg Syntax(*argv); 2078d522f475Smrg#else 2079d522f475Smrg if (**argv != '-') { 2080d522f475Smrg if (argc > 1) 2081d522f475Smrg Syntax(*argv); 2082d522f475Smrg if (command_to_exec == 0) /* if no "-e" option */ 2083d522f475Smrg explicit_shname = xtermFindShell(*argv, True); 2084d522f475Smrg continue; 2085d522f475Smrg } 2086d522f475Smrg#endif 2087d522f475Smrg 2088d522f475Smrg TRACE(("parsing %s\n", argv[0])); 2089d522f475Smrg switch (argv[0][1]) { 2090d522f475Smrg case 'h': /* -help */ 2091d522f475Smrg Help(); 2092d522f475Smrg continue; 2093d522f475Smrg case 'v': /* -version */ 2094d522f475Smrg Version(); 2095d522f475Smrg continue; 2096d522f475Smrg case 'C': 2097d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 2098d522f475Smrg#ifndef __sgi 2099d522f475Smrg { 2100d522f475Smrg struct stat sbuf; 2101d522f475Smrg 2102d522f475Smrg /* Must be owner and have read/write permission. 2103d522f475Smrg xdm cooperates to give the console the right user. */ 2104d522f475Smrg if (!stat("/dev/console", &sbuf) && 2105d522f475Smrg (sbuf.st_uid == save_ruid) && 2106d522f475Smrg !access("/dev/console", R_OK | W_OK)) { 2107d522f475Smrg Console = True; 2108d522f475Smrg } else 2109d522f475Smrg Console = False; 2110d522f475Smrg } 2111d522f475Smrg#else /* __sgi */ 2112d522f475Smrg Console = True; 2113d522f475Smrg#endif /* __sgi */ 2114d522f475Smrg#endif /* TIOCCONS */ 2115d522f475Smrg continue; 2116d522f475Smrg case 'S': 2117d522f475Smrg if (!ParseSccn(*argv + 2)) 2118d522f475Smrg Syntax(*argv); 2119d522f475Smrg continue; 2120d522f475Smrg#ifdef DEBUG 2121d522f475Smrg case 'D': 2122d522f475Smrg debug = True; 2123d522f475Smrg continue; 2124d522f475Smrg#endif /* DEBUG */ 2125d522f475Smrg case 'c': /* -class param */ 2126d522f475Smrg if (strcmp(argv[0] + 1, "class") == 0) 2127d522f475Smrg argc--, argv++; 2128d522f475Smrg else 2129d522f475Smrg Syntax(*argv); 2130d522f475Smrg continue; 2131d522f475Smrg case 'e': 2132d522f475Smrg if (argc <= 1) 2133d522f475Smrg Syntax(*argv); 2134d522f475Smrg command_to_exec = ++argv; 2135d522f475Smrg break; 2136d522f475Smrg case 'i': 2137d522f475Smrg if (argc <= 1) { 2138d522f475Smrg Syntax(*argv); 2139d522f475Smrg } else { 2140d522f475Smrg char *endPtr; 2141d522f475Smrg --argc; 2142d522f475Smrg ++argv; 2143d522f475Smrg winToEmbedInto = (Window) strtol(argv[0], &endPtr, 10); 2144d522f475Smrg } 2145d522f475Smrg continue; 2146d522f475Smrg 2147d522f475Smrg default: 2148d522f475Smrg Syntax(*argv); 2149d522f475Smrg } 2150d522f475Smrg break; 2151d522f475Smrg } 2152d522f475Smrg 2153d522f475Smrg SetupMenus(toplevel, &form_top, &menu_top, &menu_high); 2154d522f475Smrg 2155d522f475Smrg term = (XtermWidget) XtVaCreateManagedWidget("vt100", xtermWidgetClass, 2156d522f475Smrg form_top, 2157d522f475Smrg#if OPT_TOOLBAR 2158d522f475Smrg XtNmenuBar, menu_top, 2159d522f475Smrg XtNresizable, True, 2160d522f475Smrg XtNfromVert, menu_top, 2161d522f475Smrg XtNleft, XawChainLeft, 2162d522f475Smrg XtNright, XawChainRight, 2163d522f475Smrg XtNtop, XawChainTop, 2164d522f475Smrg XtNbottom, XawChainBottom, 2165d522f475Smrg XtNmenuHeight, menu_high, 2166d522f475Smrg#endif 2167d522f475Smrg (XtPointer) 0); 2168d522f475Smrg decode_keyboard_type(term, &resource); 2169d522f475Smrg 2170d522f475Smrg screen = TScreenOf(term); 2171d522f475Smrg screen->inhibit = 0; 2172d522f475Smrg 2173d522f475Smrg#ifdef ALLOWLOGGING 2174d522f475Smrg if (term->misc.logInhibit) 2175d522f475Smrg screen->inhibit |= I_LOG; 2176d522f475Smrg#endif 2177d522f475Smrg if (term->misc.signalInhibit) 2178d522f475Smrg screen->inhibit |= I_SIGNAL; 2179d522f475Smrg#if OPT_TEK4014 2180d522f475Smrg if (term->misc.tekInhibit) 2181d522f475Smrg screen->inhibit |= I_TEK; 2182d522f475Smrg#endif 2183d522f475Smrg 2184d522f475Smrg /* 2185d522f475Smrg * We might start by showing the tek4014 window. 2186d522f475Smrg */ 2187d522f475Smrg#if OPT_TEK4014 2188d522f475Smrg if (screen->inhibit & I_TEK) 2189d522f475Smrg TEK4014_ACTIVE(term) = False; 2190d522f475Smrg 2191d522f475Smrg if (TEK4014_ACTIVE(term) && !TekInit()) 2192d522f475Smrg SysError(ERROR_INIT); 2193d522f475Smrg#endif 2194d522f475Smrg 2195d522f475Smrg /* 2196d522f475Smrg * Start the toolbar at this point, after the first window has been setup. 2197d522f475Smrg */ 2198d522f475Smrg#if OPT_TOOLBAR 2199d522f475Smrg ShowToolbar(resource.toolBar); 2200d522f475Smrg#endif 2201d522f475Smrg 2202d522f475Smrg#if OPT_SESSION_MGT 2203d522f475Smrg if (resource.sessionMgt) { 2204d522f475Smrg TRACE(("Enabling session-management callbacks\n")); 2205d522f475Smrg XtAddCallback(toplevel, XtNdieCallback, die_callback, NULL); 2206d522f475Smrg XtAddCallback(toplevel, XtNsaveCallback, save_callback, NULL); 2207d522f475Smrg } 2208d522f475Smrg#endif 2209d522f475Smrg 2210d522f475Smrg /* 2211d522f475Smrg * Set title and icon name if not specified 2212d522f475Smrg */ 2213d522f475Smrg if (command_to_exec) { 2214d522f475Smrg Arg args[2]; 2215d522f475Smrg 2216d522f475Smrg if (!resource.title) { 2217d522f475Smrg if (command_to_exec) { 2218d522f475Smrg resource.title = x_basename(command_to_exec[0]); 2219d522f475Smrg } /* else not reached */ 2220d522f475Smrg } 2221d522f475Smrg 2222d522f475Smrg if (!resource.icon_name) 2223d522f475Smrg resource.icon_name = resource.title; 2224d522f475Smrg XtSetArg(args[0], XtNtitle, resource.title); 2225d522f475Smrg XtSetArg(args[1], XtNiconName, resource.icon_name); 2226d522f475Smrg 2227d522f475Smrg TRACE(("setting:\n\ttitle \"%s\"\n\ticon \"%s\"\n\tbased on command \"%s\"\n", 2228d522f475Smrg resource.title, 2229d522f475Smrg resource.icon_name, 2230d522f475Smrg *command_to_exec)); 2231d522f475Smrg 2232d522f475Smrg XtSetValues(toplevel, args, 2); 2233d522f475Smrg } 2234d522f475Smrg#if OPT_LUIT_PROG 2235d522f475Smrg if (term->misc.callfilter) { 2236d522f475Smrg int u = (term->misc.use_encoding ? 2 : 0); 2237d522f475Smrg if (command_to_exec) { 2238d522f475Smrg int n; 2239d522f475Smrg char **c; 2240d522f475Smrg for (n = 0, c = command_to_exec; *c; n++, c++) ; 2241956cc18dSsnj c = TypeMallocN(char *, (unsigned) (n + 3 + u)); 2242d522f475Smrg if (c == NULL) 2243d522f475Smrg SysError(ERROR_LUMALLOC); 2244956cc18dSsnj memcpy(c + 2 + u, command_to_exec, (unsigned) (n + 1) * sizeof(char *)); 2245d522f475Smrg c[0] = term->misc.localefilter; 2246d522f475Smrg if (u) { 2247d522f475Smrg c[1] = "-encoding"; 2248d522f475Smrg c[2] = term->misc.locale_str; 2249d522f475Smrg } 2250d522f475Smrg c[1 + u] = "--"; 2251d522f475Smrg command_to_exec_with_luit = c; 2252d522f475Smrg } else { 22532eaa94a1Schristos static char *luit[6]; 2254d522f475Smrg luit[0] = term->misc.localefilter; 2255d522f475Smrg if (u) { 2256d522f475Smrg luit[1] = "-encoding"; 2257d522f475Smrg luit[2] = term->misc.locale_str; 2258d522f475Smrg luit[3] = NULL; 2259d522f475Smrg } else 2260d522f475Smrg luit[1] = NULL; 2261d522f475Smrg command_to_exec_with_luit = luit; 2262d522f475Smrg } 2263d522f475Smrg } 2264d522f475Smrg#endif 2265d522f475Smrg 2266d522f475Smrg#ifdef DEBUG 2267d522f475Smrg { 2268d522f475Smrg /* Set up stderr properly. Opening this log file cannot be 2269d522f475Smrg done securely by a privileged xterm process (although we try), 2270d522f475Smrg so the debug feature is disabled by default. */ 2271d522f475Smrg char dbglogfile[45]; 2272d522f475Smrg int i = -1; 2273d522f475Smrg if (debug) { 2274d522f475Smrg timestamp_filename(dbglogfile, "xterm.debug.log."); 2275d522f475Smrg if (creat_as(save_ruid, save_rgid, False, dbglogfile, 0666) > 0) { 2276d522f475Smrg i = open(dbglogfile, O_WRONLY | O_TRUNC); 2277d522f475Smrg } 2278d522f475Smrg } 2279d522f475Smrg if (i >= 0) { 2280d522f475Smrg dup2(i, 2); 2281d522f475Smrg 2282d522f475Smrg /* mark this file as close on exec */ 2283d522f475Smrg (void) fcntl(i, F_SETFD, 1); 2284d522f475Smrg } 2285d522f475Smrg } 2286d522f475Smrg#endif /* DEBUG */ 2287d522f475Smrg 2288d522f475Smrg spawnXTerm(term); 2289d522f475Smrg 2290d522f475Smrg#ifndef VMS 2291d522f475Smrg /* Child process is out there, let's catch its termination */ 2292d522f475Smrg 2293d522f475Smrg#ifdef USE_POSIX_SIGNALS 2294d522f475Smrg (void) posix_signal(SIGCHLD, reapchild); 2295d522f475Smrg#else 2296d522f475Smrg (void) signal(SIGCHLD, reapchild); 2297d522f475Smrg#endif 2298d522f475Smrg /* Realize procs have now been executed */ 2299d522f475Smrg 2300d522f475Smrg if (am_slave >= 0) { /* Write window id so master end can read and use */ 2301d522f475Smrg char buf[80]; 2302d522f475Smrg 2303d522f475Smrg buf[0] = '\0'; 2304d522f475Smrg sprintf(buf, "%lx\n", XtWindow(SHELL_OF(CURRENT_EMU()))); 230520d2c4d2Smrg IGNORE_RC(write(screen->respond, buf, strlen(buf))); 2306d522f475Smrg } 2307d522f475Smrg#ifdef AIXV3 2308d522f475Smrg#if (OSMAJORVERSION < 4) 2309d522f475Smrg /* In AIXV3, xterms started from /dev/console have CLOCAL set. 2310d522f475Smrg * This means we need to clear CLOCAL so that SIGHUP gets sent 2311d522f475Smrg * to the slave-pty process when xterm exits. 2312d522f475Smrg */ 2313d522f475Smrg 2314d522f475Smrg { 2315d522f475Smrg TERMIO_STRUCT tio; 2316d522f475Smrg 2317d522f475Smrg if (ttyGetAttr(screen->respond, &tio) == -1) 2318d522f475Smrg SysError(ERROR_TIOCGETP); 2319d522f475Smrg 2320d522f475Smrg tio.c_cflag &= ~(CLOCAL); 2321d522f475Smrg 2322d522f475Smrg if (ttySetAttr(screen->respond, &tio) == -1) 2323d522f475Smrg SysError(ERROR_TIOCSETP); 2324d522f475Smrg } 2325d522f475Smrg#endif 2326d522f475Smrg#endif 2327d522f475Smrg#if defined(USE_ANY_SYSV_TERMIO) || defined(__MVS__) 2328d522f475Smrg if (0 > (mode = fcntl(screen->respond, F_GETFL, 0))) 2329d522f475Smrg SysError(ERROR_F_GETFL); 2330d522f475Smrg#ifdef O_NDELAY 2331d522f475Smrg mode |= O_NDELAY; 2332d522f475Smrg#else 2333d522f475Smrg mode |= O_NONBLOCK; 2334d522f475Smrg#endif /* O_NDELAY */ 2335d522f475Smrg if (fcntl(screen->respond, F_SETFL, mode)) 2336d522f475Smrg SysError(ERROR_F_SETFL); 2337d522f475Smrg#else /* !USE_ANY_SYSV_TERMIO */ 2338d522f475Smrg mode = 1; 2339d522f475Smrg if (ioctl(screen->respond, FIONBIO, (char *) &mode) == -1) 2340d522f475Smrg SysError(ERROR_FIONBIO); 2341d522f475Smrg#endif /* USE_ANY_SYSV_TERMIO, etc */ 2342d522f475Smrg 2343d522f475Smrg /* The erase character is used to delete the current completion */ 2344d522f475Smrg#if OPT_DABBREV 2345d522f475Smrg#ifdef TERMIO_STRUCT 2346d522f475Smrg screen->dabbrev_erase_char = d_tio.c_cc[VERASE]; 2347d522f475Smrg#else 2348d522f475Smrg screen->dabbrev_erase_char = d_sg.sg_erase; 2349d522f475Smrg#endif 2350d522f475Smrg TRACE(("set dabbrev erase_char %#x\n", screen->dabbrev_erase_char)); 2351d522f475Smrg#endif 2352d522f475Smrg 2353d522f475Smrg FD_ZERO(&pty_mask); 2354d522f475Smrg FD_ZERO(&X_mask); 2355d522f475Smrg FD_ZERO(&Select_mask); 2356d522f475Smrg FD_SET(screen->respond, &pty_mask); 2357d522f475Smrg FD_SET(ConnectionNumber(screen->display), &X_mask); 2358d522f475Smrg FD_SET(screen->respond, &Select_mask); 2359d522f475Smrg FD_SET(ConnectionNumber(screen->display), &Select_mask); 2360d522f475Smrg max_plus1 = ((screen->respond < ConnectionNumber(screen->display)) 2361d522f475Smrg ? (1 + ConnectionNumber(screen->display)) 2362d522f475Smrg : (1 + screen->respond)); 2363d522f475Smrg 2364d522f475Smrg#endif /* !VMS */ 2365d522f475Smrg#ifdef DEBUG 2366d522f475Smrg if (debug) 2367d522f475Smrg printf("debugging on\n"); 2368d522f475Smrg#endif /* DEBUG */ 2369d522f475Smrg XSetErrorHandler(xerror); 2370d522f475Smrg XSetIOErrorHandler(xioerror); 2371d522f475Smrg 2372d522f475Smrg initPtyData(&VTbuffer); 2373d522f475Smrg#ifdef ALLOWLOGGING 2374d522f475Smrg if (term->misc.log_on) { 237520d2c4d2Smrg StartLog(term); 2376d522f475Smrg } 2377d522f475Smrg#endif 2378d522f475Smrg 2379d522f475Smrg if (winToEmbedInto != None) { 2380d522f475Smrg XtRealizeWidget(toplevel); 2381d522f475Smrg /* 2382d522f475Smrg * This should probably query the tree or check the attributes of 2383d522f475Smrg * winToEmbedInto in order to verify that it exists, but I'm still not 2384d522f475Smrg * certain what is the best way to do it -GPS 2385d522f475Smrg */ 2386d522f475Smrg XReparentWindow(XtDisplay(toplevel), 2387d522f475Smrg XtWindow(toplevel), 2388d522f475Smrg winToEmbedInto, 0, 0); 2389d522f475Smrg } 2390d522f475Smrg#if OPT_COLOR_RES 2391d522f475Smrg TRACE(("checking resource values rv %s fg %s, bg %s\n", 2392d522f475Smrg BtoS(term->misc.re_verse0), 239320d2c4d2Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_FG].resource), 239420d2c4d2Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_BG].resource))); 2395d522f475Smrg 2396d522f475Smrg if ((reversed && term->misc.re_verse0) 239720d2c4d2Smrg && ((TScreenOf(term)->Tcolors[TEXT_FG].resource 239820d2c4d2Smrg && !isDefaultForeground(TScreenOf(term)->Tcolors[TEXT_FG].resource)) 239920d2c4d2Smrg || (TScreenOf(term)->Tcolors[TEXT_BG].resource 240020d2c4d2Smrg && !isDefaultBackground(TScreenOf(term)->Tcolors[TEXT_BG].resource)) 2401d522f475Smrg )) 2402d522f475Smrg ReverseVideo(term); 2403d522f475Smrg#endif /* OPT_COLOR_RES */ 2404d522f475Smrg 2405956cc18dSsnj#if OPT_MAXIMIZE 2406956cc18dSsnj if (resource.maximized) 2407956cc18dSsnj RequestMaximize(term, True); 2408956cc18dSsnj#endif 2409d522f475Smrg for (;;) { 2410d522f475Smrg#if OPT_TEK4014 2411d522f475Smrg if (TEK4014_ACTIVE(term)) 2412d522f475Smrg TekRun(); 2413d522f475Smrg else 2414d522f475Smrg#endif 2415956cc18dSsnj VTRun(term); 2416d522f475Smrg } 2417d522f475Smrg} 2418d522f475Smrg 2419956cc18dSsnj#if defined(__osf__) || (defined(__GLIBC__) && !defined(USE_USG_PTYS)) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) 2420d522f475Smrg#define USE_OPENPTY 1 2421d522f475Smrgstatic int opened_tty = -1; 2422d522f475Smrg#endif 2423d522f475Smrg 2424d522f475Smrg/* 2425d522f475Smrg * This function opens up a pty master and stuffs its value into pty. 2426d522f475Smrg * 2427d522f475Smrg * If it finds one, it returns a value of 0. If it does not find one, 2428d522f475Smrg * it returns a value of !0. This routine is designed to be re-entrant, 2429d522f475Smrg * so that if a pty master is found and later, we find that the slave 2430d522f475Smrg * has problems, we can re-enter this function and get another one. 2431d522f475Smrg */ 2432d522f475Smrgstatic int 2433d522f475Smrgget_pty(int *pty, char *from GCC_UNUSED) 2434d522f475Smrg{ 2435d522f475Smrg int result = 1; 2436d522f475Smrg 2437d522f475Smrg#if defined(PUCC_PTYD) 2438d522f475Smrg 2439d522f475Smrg result = ((*pty = openrpty(ttydev, ptydev, 2440d522f475Smrg (resource.utmpInhibit ? OPTY_NOP : OPTY_LOGIN), 2441d522f475Smrg save_ruid, from)) < 0); 2442d522f475Smrg 2443d522f475Smrg#elif defined(USE_OPENPTY) 2444d522f475Smrg 2445d522f475Smrg result = openpty(pty, &opened_tty, ttydev, NULL, NULL); 2446d522f475Smrg 2447d522f475Smrg#elif defined(__QNXNTO__) 2448d522f475Smrg 2449d522f475Smrg result = pty_search(pty); 2450d522f475Smrg 2451d522f475Smrg#else 2452d522f475Smrg#if defined(USE_ISPTS_FLAG) 2453d522f475Smrg 2454d522f475Smrg /* 2455d522f475Smrg The order of this code is *important*. On SYSV/386 we want to open 2456d522f475Smrg a /dev/ttyp? first if at all possible. If none are available, then 2457d522f475Smrg we'll try to open a /dev/pts??? device. 2458d522f475Smrg 2459d522f475Smrg The reason for this is because /dev/ttyp? works correctly, where 2460d522f475Smrg as /dev/pts??? devices have a number of bugs, (won't update 2461d522f475Smrg screen correcly, will hang -- it more or less works, but you 2462d522f475Smrg really don't want to use it). 2463d522f475Smrg 2464d522f475Smrg Most importantly, for boxes of this nature, one of the major 2465d522f475Smrg "features" is that you can emulate a 8086 by spawning off a UNIX 2466d522f475Smrg program on 80386/80486 in v86 mode. In other words, you can spawn 2467d522f475Smrg off multiple MS-DOS environments. On ISC the program that does 2468d522f475Smrg this is named "vpix." The catcher is that "vpix" will *not* work 2469d522f475Smrg with a /dev/pts??? device, will only work with a /dev/ttyp? device. 2470d522f475Smrg 2471d522f475Smrg Since we can open either a /dev/ttyp? or a /dev/pts??? device, 2472d522f475Smrg the flag "IsPts" is set here so that we know which type of 2473d522f475Smrg device we're dealing with in routine spawnXTerm(). That's the reason 2474d522f475Smrg for the "if (IsPts)" statement in spawnXTerm(); we have two different 2475d522f475Smrg device types which need to be handled differently. 2476d522f475Smrg */ 2477d522f475Smrg result = pty_search(pty); 2478d522f475Smrg if (!result) 2479d522f475Smrg IsPts = 0; 2480d522f475Smrg 2481d522f475Smrg#endif 2482d522f475Smrg#if defined(USE_USG_PTYS) || defined(__CYGWIN__) 2483d522f475Smrg#ifdef __GLIBC__ /* if __GLIBC__ and USE_USG_PTYS, we know glibc >= 2.1 */ 2484d522f475Smrg /* GNU libc 2 allows us to abstract away from having to know the 2485d522f475Smrg master pty device name. */ 2486d522f475Smrg if ((*pty = getpt()) >= 0) { 2487d522f475Smrg char *name = ptsname(*pty); 2488d522f475Smrg if (name != 0) { /* if filesystem is trashed, this may be null */ 2489d522f475Smrg strcpy(ttydev, name); 2490d522f475Smrg result = 0; 2491d522f475Smrg } 2492d522f475Smrg } 2493d522f475Smrg#elif defined(__MVS__) 2494d522f475Smrg result = pty_search(pty); 2495d522f475Smrg#else 2496d522f475Smrg#if defined(USE_ISPTS_FLAG) 2497d522f475Smrg if (result) { 2498d522f475Smrg#endif 2499d522f475Smrg result = ((*pty = open("/dev/ptmx", O_RDWR)) < 0); 2500d522f475Smrg#endif 2501d522f475Smrg#if defined(SVR4) || defined(__SCO__) || defined(USE_ISPTS_FLAG) 2502d522f475Smrg if (!result) 2503d522f475Smrg strcpy(ttydev, ptsname(*pty)); 2504d522f475Smrg#ifdef USE_ISPTS_FLAG 2505d522f475Smrg IsPts = !result; /* true if we're successful */ 2506d522f475Smrg } 2507d522f475Smrg#endif 2508d522f475Smrg#endif 2509d522f475Smrg 2510d522f475Smrg#elif defined(AIXV3) 2511d522f475Smrg 2512d522f475Smrg if ((*pty = open("/dev/ptc", O_RDWR)) >= 0) { 2513d522f475Smrg strcpy(ttydev, ttyname(*pty)); 2514d522f475Smrg result = 0; 2515d522f475Smrg } 2516d522f475Smrg#elif defined(__convex__) 2517d522f475Smrg 2518d522f475Smrg char *pty_name; 2519d522f475Smrg extern char *getpty(void); 2520d522f475Smrg 2521d522f475Smrg while ((pty_name = getpty()) != NULL) { 2522d522f475Smrg if ((*pty = open(pty_name, O_RDWR)) >= 0) { 2523d522f475Smrg strcpy(ptydev, pty_name); 2524d522f475Smrg strcpy(ttydev, pty_name); 2525d522f475Smrg *x_basename(ttydev) = 't'; 2526d522f475Smrg result = 0; 2527d522f475Smrg break; 2528d522f475Smrg } 2529d522f475Smrg } 2530d522f475Smrg 2531d522f475Smrg#elif defined(sequent) 2532d522f475Smrg 2533d522f475Smrg result = ((*pty = getpseudotty(&ttydev, &ptydev)) < 0); 2534d522f475Smrg 2535d522f475Smrg#elif defined(__sgi) && (OSMAJORVERSION >= 4) 2536d522f475Smrg 2537d522f475Smrg char *tty_name; 2538d522f475Smrg 2539d522f475Smrg tty_name = _getpty(pty, O_RDWR, 0622, 0); 2540d522f475Smrg if (tty_name != 0) { 2541d522f475Smrg strcpy(ttydev, tty_name); 2542d522f475Smrg result = 0; 2543d522f475Smrg } 2544d522f475Smrg#elif (defined(__sgi) && (OSMAJORVERSION < 4)) || (defined(umips) && defined (SYSTYPE_SYSV)) 2545d522f475Smrg 2546d522f475Smrg struct stat fstat_buf; 2547d522f475Smrg 2548d522f475Smrg *pty = open("/dev/ptc", O_RDWR); 2549d522f475Smrg if (*pty >= 0 && (fstat(*pty, &fstat_buf)) >= 0) { 2550d522f475Smrg result = 0; 2551d522f475Smrg sprintf(ttydev, "/dev/ttyq%d", minor(fstat_buf.st_rdev)); 2552d522f475Smrg } 2553d522f475Smrg#elif defined(__hpux) 2554d522f475Smrg 2555d522f475Smrg /* 2556d522f475Smrg * Use the clone device if it works, otherwise use pty_search logic. 2557d522f475Smrg */ 2558d522f475Smrg if ((*pty = open("/dev/ptym/clone", O_RDWR)) >= 0) { 2559d522f475Smrg char *name = ptsname(*pty); 2560d522f475Smrg if (name != 0) { 2561d522f475Smrg strcpy(ttydev, name); 2562d522f475Smrg result = 0; 2563d522f475Smrg } else { /* permissions, or other unexpected problem */ 2564d522f475Smrg close(*pty); 2565d522f475Smrg *pty = -1; 2566d522f475Smrg result = pty_search(pty); 2567d522f475Smrg } 2568d522f475Smrg } else { 2569d522f475Smrg result = pty_search(pty); 2570d522f475Smrg } 2571d522f475Smrg 2572d522f475Smrg#else 2573d522f475Smrg 2574d522f475Smrg result = pty_search(pty); 2575d522f475Smrg 2576d522f475Smrg#endif 2577d522f475Smrg#endif 2578d522f475Smrg 2579d522f475Smrg TRACE(("get_pty(ttydev=%s, ptydev=%s) %s fd=%d\n", 2580d522f475Smrg ttydev != 0 ? ttydev : "?", 2581d522f475Smrg ptydev != 0 ? ptydev : "?", 2582d522f475Smrg result ? "FAIL" : "OK", 2583d522f475Smrg pty != 0 ? *pty : -1)); 2584d522f475Smrg return result; 2585d522f475Smrg} 2586d522f475Smrg 2587d522f475Smrgstatic void 2588d522f475Smrgset_pty_permissions(uid_t uid, gid_t gid, mode_t mode) 2589d522f475Smrg{ 2590d522f475Smrg#ifdef USE_TTY_GROUP 2591d522f475Smrg struct group *ttygrp; 2592d522f475Smrg 2593d522f475Smrg if ((ttygrp = getgrnam(TTY_GROUP_NAME)) != 0) { 2594d522f475Smrg gid = ttygrp->gr_gid; 2595d522f475Smrg mode &= 0660U; 2596d522f475Smrg } 2597d522f475Smrg endgrent(); 2598d522f475Smrg#endif /* USE_TTY_GROUP */ 2599d522f475Smrg 2600d522f475Smrg TRACE_IDS; 2601d522f475Smrg set_owner(ttydev, uid, gid, mode); 2602d522f475Smrg} 2603d522f475Smrg 2604d522f475Smrg#ifdef get_pty /* USE_UTMP_SETGID */ 2605d522f475Smrg#undef get_pty 2606d522f475Smrg/* 2607d522f475Smrg * Call the real get_pty() before relinquishing root-setuid, caching the 2608d522f475Smrg * result. 2609d522f475Smrg */ 2610d522f475Smrgstatic int 2611d522f475Smrgget_pty(int *pty, char *from) 2612d522f475Smrg{ 2613d522f475Smrg static int m_pty = -1; 2614d522f475Smrg int result = -1; 2615d522f475Smrg 2616d522f475Smrg if (pty == NULL) { 2617d522f475Smrg result = really_get_pty(&m_pty, from); 2618d522f475Smrg 2619d522f475Smrg seteuid(0); 2620d522f475Smrg set_pty_permissions(save_ruid, save_rgid, 0600U); 2621d522f475Smrg seteuid(save_ruid); 2622d522f475Smrg TRACE_IDS; 2623d522f475Smrg 2624d522f475Smrg#ifdef USE_OPENPTY 2625d522f475Smrg if (opened_tty >= 0) { 2626d522f475Smrg close(opened_tty); 2627d522f475Smrg opened_tty = -1; 2628d522f475Smrg } 2629d522f475Smrg#endif 2630d522f475Smrg } else if (m_pty != -1) { 2631d522f475Smrg *pty = m_pty; 2632d522f475Smrg result = 0; 2633d522f475Smrg } else { 2634d522f475Smrg result = -1; 2635d522f475Smrg } 2636d522f475Smrg return result; 2637d522f475Smrg} 2638d522f475Smrg#endif 2639d522f475Smrg 2640d522f475Smrg/* 2641d522f475Smrg * Called from get_pty to iterate over likely pseudo terminals 2642d522f475Smrg * we might allocate. Used on those systems that do not have 2643d522f475Smrg * a functional interface for allocating a pty. 2644d522f475Smrg * Returns 0 if found a pty, 1 if fails. 2645d522f475Smrg */ 2646d522f475Smrg#ifdef USE_PTY_SEARCH 2647d522f475Smrgstatic int 2648d522f475Smrgpty_search(int *pty) 2649d522f475Smrg{ 2650d522f475Smrg static int devindex = 0, letter = 0; 2651d522f475Smrg 2652d522f475Smrg#if defined(CRAY) || defined(__MVS__) 2653d522f475Smrg while (devindex < MAXPTTYS) { 2654d522f475Smrg sprintf(ttydev, TTYFORMAT, devindex); 2655d522f475Smrg sprintf(ptydev, PTYFORMAT, devindex); 2656d522f475Smrg devindex++; 2657d522f475Smrg 2658d522f475Smrg TRACE(("pty_search(ttydev=%s, ptydev=%s)\n", ttydev, ptydev)); 2659d522f475Smrg if ((*pty = open(ptydev, O_RDWR)) >= 0) { 2660d522f475Smrg return 0; 2661d522f475Smrg } 2662d522f475Smrg } 2663d522f475Smrg#else /* CRAY || __MVS__ */ 2664d522f475Smrg while (PTYCHAR1[letter]) { 2665d522f475Smrg ttydev[strlen(ttydev) - 2] = 2666d522f475Smrg ptydev[strlen(ptydev) - 2] = PTYCHAR1[letter]; 2667d522f475Smrg 2668d522f475Smrg while (PTYCHAR2[devindex]) { 2669d522f475Smrg ttydev[strlen(ttydev) - 1] = 2670d522f475Smrg ptydev[strlen(ptydev) - 1] = PTYCHAR2[devindex]; 2671d522f475Smrg devindex++; 2672d522f475Smrg 2673d522f475Smrg TRACE(("pty_search(ttydev=%s, ptydev=%s)\n", ttydev, ptydev)); 2674d522f475Smrg if ((*pty = open(ptydev, O_RDWR)) >= 0) { 2675d522f475Smrg#ifdef sun 2676d522f475Smrg /* Need to check the process group of the pty. 2677d522f475Smrg * If it exists, then the slave pty is in use, 2678d522f475Smrg * and we need to get another one. 2679d522f475Smrg */ 2680d522f475Smrg int pgrp_rtn; 2681d522f475Smrg if (ioctl(*pty, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) { 2682d522f475Smrg close(*pty); 2683d522f475Smrg continue; 2684d522f475Smrg } 2685d522f475Smrg#endif /* sun */ 2686d522f475Smrg return 0; 2687d522f475Smrg } 2688d522f475Smrg } 2689d522f475Smrg devindex = 0; 2690d522f475Smrg letter++; 2691d522f475Smrg } 2692d522f475Smrg#endif /* CRAY else */ 2693d522f475Smrg /* 2694d522f475Smrg * We were unable to allocate a pty master! Return an error 2695d522f475Smrg * condition and let our caller terminate cleanly. 2696d522f475Smrg */ 2697d522f475Smrg return 1; 2698d522f475Smrg} 2699d522f475Smrg#endif /* USE_PTY_SEARCH */ 2700d522f475Smrg 2701d522f475Smrg/* 2702d522f475Smrg * The only difference in /etc/termcap between 4014 and 4015 is that 2703d522f475Smrg * the latter has support for switching character sets. We support the 2704d522f475Smrg * 4015 protocol, but ignore the character switches. Therefore, we 2705d522f475Smrg * choose 4014 over 4015. 2706d522f475Smrg * 2707d522f475Smrg * Features of the 4014 over the 4012: larger (19") screen, 12-bit 2708d522f475Smrg * graphics addressing (compatible with 4012 10-bit addressing), 2709d522f475Smrg * special point plot mode, incremental plot mode (not implemented in 2710d522f475Smrg * later Tektronix terminals), and 4 character sizes. 2711d522f475Smrg * All of these are supported by xterm. 2712d522f475Smrg */ 2713d522f475Smrg 2714d522f475Smrg#if OPT_TEK4014 271520d2c4d2Smrgstatic const char *tekterm[] = 2716d522f475Smrg{ 2717d522f475Smrg "tek4014", 2718d522f475Smrg "tek4015", /* 4014 with APL character set support */ 2719d522f475Smrg "tek4012", /* 4010 with lower case */ 2720d522f475Smrg "tek4013", /* 4012 with APL character set support */ 2721d522f475Smrg "tek4010", /* small screen, upper-case only */ 2722d522f475Smrg "dumb", 2723d522f475Smrg 0 2724d522f475Smrg}; 2725d522f475Smrg#endif 2726d522f475Smrg 2727d522f475Smrg/* The VT102 is a VT100 with the Advanced Video Option included standard. 2728d522f475Smrg * It also adds Escape sequences for insert/delete character/line. 2729d522f475Smrg * The VT220 adds 8-bit character sets, selective erase. 2730d522f475Smrg * The VT320 adds a 25th status line, terminal state interrogation. 2731d522f475Smrg * The VT420 has up to 48 lines on the screen. 2732d522f475Smrg */ 2733d522f475Smrg 273420d2c4d2Smrgstatic const char *vtterm[] = 2735d522f475Smrg{ 2736d522f475Smrg#ifdef USE_X11TERM 2737d522f475Smrg "x11term", /* for people who want special term name */ 2738d522f475Smrg#endif 2739d522f475Smrg DFT_TERMTYPE, /* for people who want special term name */ 2740d522f475Smrg "xterm", /* the prefered name, should be fastest */ 2741d522f475Smrg "vt102", 2742d522f475Smrg "vt100", 2743d522f475Smrg "ansi", 2744d522f475Smrg "dumb", 2745d522f475Smrg 0 2746d522f475Smrg}; 2747d522f475Smrg 2748d522f475Smrg/* ARGSUSED */ 2749d522f475Smrgstatic SIGNAL_T 2750d522f475Smrghungtty(int i GCC_UNUSED) 2751d522f475Smrg{ 2752d522f475Smrg siglongjmp(env, 1); 2753d522f475Smrg SIGNAL_RETURN; 2754d522f475Smrg} 2755d522f475Smrg 2756d522f475Smrg#if OPT_PTY_HANDSHAKE 2757d522f475Smrg#define NO_FDS {-1, -1} 2758d522f475Smrg 2759d522f475Smrgstatic int cp_pipe[2] = NO_FDS; /* this pipe is used for child to parent transfer */ 2760d522f475Smrgstatic int pc_pipe[2] = NO_FDS; /* this pipe is used for parent to child transfer */ 2761d522f475Smrg 2762d522f475Smrgtypedef enum { /* c == child, p == parent */ 2763d522f475Smrg PTY_BAD, /* c->p: can't open pty slave for some reason */ 2764d522f475Smrg PTY_FATALERROR, /* c->p: we had a fatal error with the pty */ 2765d522f475Smrg PTY_GOOD, /* c->p: we have a good pty, let's go on */ 2766d522f475Smrg PTY_NEW, /* p->c: here is a new pty slave, try this */ 2767d522f475Smrg PTY_NOMORE, /* p->c; no more pty's, terminate */ 2768d522f475Smrg UTMP_ADDED, /* c->p: utmp entry has been added */ 2769d522f475Smrg UTMP_TTYSLOT, /* c->p: here is my ttyslot */ 2770d522f475Smrg PTY_EXEC /* p->c: window has been mapped the first time */ 2771d522f475Smrg} status_t; 2772d522f475Smrg 2773d522f475Smrgtypedef struct { 2774d522f475Smrg status_t status; 2775d522f475Smrg int error; 2776d522f475Smrg int fatal_error; 2777d522f475Smrg int tty_slot; 2778d522f475Smrg int rows; 2779d522f475Smrg int cols; 2780d522f475Smrg char buffer[1024]; 2781d522f475Smrg} handshake_t; 2782d522f475Smrg 2783d522f475Smrg#if OPT_TRACE 2784d522f475Smrgstatic void 2785d522f475Smrgtrace_handshake(const char *tag, handshake_t * data) 2786d522f475Smrg{ 2787d522f475Smrg const char *status = "?"; 2788d522f475Smrg switch (data->status) { 2789d522f475Smrg case PTY_BAD: 2790d522f475Smrg status = "PTY_BAD"; 2791d522f475Smrg break; 2792d522f475Smrg case PTY_FATALERROR: 2793d522f475Smrg status = "PTY_FATALERROR"; 2794d522f475Smrg break; 2795d522f475Smrg case PTY_GOOD: 2796d522f475Smrg status = "PTY_GOOD"; 2797d522f475Smrg break; 2798d522f475Smrg case PTY_NEW: 2799d522f475Smrg status = "PTY_NEW"; 2800d522f475Smrg break; 2801d522f475Smrg case PTY_NOMORE: 2802d522f475Smrg status = "PTY_NOMORE"; 2803d522f475Smrg break; 2804d522f475Smrg case UTMP_ADDED: 2805d522f475Smrg status = "UTMP_ADDED"; 2806d522f475Smrg break; 2807d522f475Smrg case UTMP_TTYSLOT: 2808d522f475Smrg status = "UTMP_TTYSLOT"; 2809d522f475Smrg break; 2810d522f475Smrg case PTY_EXEC: 2811d522f475Smrg status = "PTY_EXEC"; 2812d522f475Smrg break; 2813d522f475Smrg } 2814d522f475Smrg TRACE(("handshake %s %s errno=%d, error=%d device \"%s\"\n", 2815d522f475Smrg tag, 2816d522f475Smrg status, 2817d522f475Smrg data->error, 2818d522f475Smrg data->fatal_error, 2819d522f475Smrg data->buffer)); 2820d522f475Smrg} 2821d522f475Smrg#define TRACE_HANDSHAKE(tag, data) trace_handshake(tag, data) 2822d522f475Smrg#else 2823d522f475Smrg#define TRACE_HANDSHAKE(tag, data) /* nothing */ 2824d522f475Smrg#endif 2825d522f475Smrg 2826d522f475Smrg/* HsSysError() 2827d522f475Smrg * 2828d522f475Smrg * This routine does the equivalent of a SysError but it handshakes 2829d522f475Smrg * over the errno and error exit to the master process so that it can 2830d522f475Smrg * display our error message and exit with our exit code so that the 2831d522f475Smrg * user can see it. 2832d522f475Smrg */ 2833d522f475Smrg 2834d522f475Smrgstatic void 2835d522f475SmrgHsSysError(int error) 2836d522f475Smrg{ 2837d522f475Smrg handshake_t handshake; 2838d522f475Smrg 2839d522f475Smrg memset(&handshake, 0, sizeof(handshake)); 2840d522f475Smrg handshake.status = PTY_FATALERROR; 2841d522f475Smrg handshake.error = errno; 2842d522f475Smrg handshake.fatal_error = error; 2843d522f475Smrg strcpy(handshake.buffer, ttydev); 2844d522f475Smrg 2845d522f475Smrg if (resource.ptyHandshake && (cp_pipe[1] >= 0)) { 2846d522f475Smrg TRACE(("HsSysError errno=%d, error=%d device \"%s\"\n", 2847d522f475Smrg handshake.error, 2848d522f475Smrg handshake.fatal_error, 2849d522f475Smrg handshake.buffer)); 2850d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 285120d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], 285220d2c4d2Smrg (const char *) &handshake, 285320d2c4d2Smrg sizeof(handshake))); 2854d522f475Smrg } else { 2855d522f475Smrg fprintf(stderr, 2856d522f475Smrg "%s: fatal pty error errno=%d, error=%d device \"%s\"\n", 2857d522f475Smrg ProgramName, 2858d522f475Smrg handshake.error, 2859d522f475Smrg handshake.fatal_error, 2860d522f475Smrg handshake.buffer); 2861d522f475Smrg fprintf(stderr, "%s\n", SysErrorMsg(handshake.error)); 2862d522f475Smrg fprintf(stderr, "Reason: %s\n", SysReasonMsg(handshake.fatal_error)); 2863d522f475Smrg } 2864d522f475Smrg exit(error); 2865d522f475Smrg} 2866d522f475Smrg 2867d522f475Smrgvoid 2868d522f475Smrgfirst_map_occurred(void) 2869d522f475Smrg{ 2870d522f475Smrg if (resource.wait_for_map) { 2871d522f475Smrg handshake_t handshake; 2872d522f475Smrg TScreen *screen = TScreenOf(term); 2873d522f475Smrg 2874d522f475Smrg memset(&handshake, 0, sizeof(handshake)); 2875d522f475Smrg handshake.status = PTY_EXEC; 2876d522f475Smrg handshake.rows = screen->max_row; 2877d522f475Smrg handshake.cols = screen->max_col; 2878d522f475Smrg 2879d522f475Smrg if (pc_pipe[1] >= 0) { 2880d522f475Smrg TRACE(("first_map_occurred: %dx%d\n", handshake.rows, handshake.cols)); 2881d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 288220d2c4d2Smrg IGNORE_RC(write(pc_pipe[1], 288320d2c4d2Smrg (const char *) &handshake, 288420d2c4d2Smrg sizeof(handshake))); 2885d522f475Smrg close(cp_pipe[0]); 2886d522f475Smrg close(pc_pipe[1]); 2887d522f475Smrg } 2888d522f475Smrg resource.wait_for_map = False; 2889d522f475Smrg } 2890d522f475Smrg} 2891d522f475Smrg#else 2892d522f475Smrg/* 2893d522f475Smrg * temporary hack to get xterm working on att ptys 2894d522f475Smrg */ 2895d522f475Smrgstatic void 2896d522f475SmrgHsSysError(int error) 2897d522f475Smrg{ 2898d522f475Smrg fprintf(stderr, "%s: fatal pty error %d (errno=%d) on tty %s\n", 2899d522f475Smrg ProgramName, error, errno, ttydev); 2900d522f475Smrg exit(error); 2901d522f475Smrg} 2902d522f475Smrg#endif /* OPT_PTY_HANDSHAKE else !OPT_PTY_HANDSHAKE */ 2903d522f475Smrg 2904d522f475Smrg#ifndef VMS 2905d522f475Smrgstatic void 2906d522f475Smrgset_owner(char *device, uid_t uid, gid_t gid, mode_t mode) 2907d522f475Smrg{ 2908d522f475Smrg int why; 2909d522f475Smrg 2910d522f475Smrg TRACE_IDS; 291120d2c4d2Smrg TRACE(("set_owner(%s, uid=%d, gid=%d, mode=%#o\n", 291220d2c4d2Smrg device, uid, gid, (unsigned) mode)); 2913d522f475Smrg 2914d522f475Smrg if (chown(device, uid, gid) < 0) { 2915d522f475Smrg why = errno; 2916d522f475Smrg if (why != ENOENT 2917d522f475Smrg && save_ruid == 0) { 2918d522f475Smrg fprintf(stderr, "Cannot chown %s to %ld,%ld: %s\n", 2919d522f475Smrg device, (long) uid, (long) gid, 2920d522f475Smrg strerror(why)); 2921d522f475Smrg } 2922d522f475Smrg TRACE(("...chown failed: %s\n", strerror(why))); 2923d522f475Smrg } 2924d522f475Smrg if (chmod(device, mode) < 0) { 2925d522f475Smrg why = errno; 2926d522f475Smrg if (why != ENOENT) { 2927d522f475Smrg struct stat sb; 2928d522f475Smrg if (stat(device, &sb) < 0) { 2929d522f475Smrg fprintf(stderr, "Cannot chmod %s to %03o: %s\n", 2930d522f475Smrg device, (unsigned) mode, 2931d522f475Smrg strerror(why)); 2932d522f475Smrg } else if (mode != (sb.st_mode & 0777U)) { 2933d522f475Smrg fprintf(stderr, 2934d522f475Smrg "Cannot chmod %s to %03lo currently %03lo: %s\n", 2935d522f475Smrg device, 2936d522f475Smrg (unsigned long) mode, 2937d522f475Smrg (unsigned long) (sb.st_mode & 0777U), 2938d522f475Smrg strerror(why)); 2939d522f475Smrg TRACE(("...stat uid=%d, gid=%d, mode=%#o\n", 294020d2c4d2Smrg sb.st_uid, sb.st_gid, (unsigned) sb.st_mode)); 2941d522f475Smrg } 2942d522f475Smrg } 2943d522f475Smrg TRACE(("...chmod failed: %s\n", strerror(why))); 2944d522f475Smrg } 2945d522f475Smrg} 2946d522f475Smrg 2947d522f475Smrg#if defined(HAVE_UTMP) && defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 2948d522f475Smrg/* 2949d522f475Smrg * getutid() only looks at ut_type and ut_id. 2950d522f475Smrg * But we'll also check ut_line in find_utmp(). 2951d522f475Smrg */ 2952d522f475Smrgstatic void 2953d522f475Smrginit_utmp(int type, struct UTMP_STR *tofind) 2954d522f475Smrg{ 2955d522f475Smrg memset(tofind, 0, sizeof(*tofind)); 2956d522f475Smrg tofind->ut_type = type; 2957d522f475Smrg (void) strncpy(tofind->ut_id, my_utmp_id(ttydev), sizeof(tofind->ut_id)); 2958d522f475Smrg (void) strncpy(tofind->ut_line, my_pty_name(ttydev), sizeof(tofind->ut_line)); 2959d522f475Smrg} 2960d522f475Smrg 2961d522f475Smrg/* 2962d522f475Smrg * We could use getutline() if we didn't support old systems. 2963d522f475Smrg */ 2964d522f475Smrgstatic struct UTMP_STR * 2965d522f475Smrgfind_utmp(struct UTMP_STR *tofind) 2966d522f475Smrg{ 2967d522f475Smrg struct UTMP_STR *result; 2968d522f475Smrg struct UTMP_STR working; 2969d522f475Smrg 2970d522f475Smrg for (;;) { 2971d522f475Smrg memset(&working, 0, sizeof(working)); 2972d522f475Smrg working.ut_type = tofind->ut_type; 2973d522f475Smrg memcpy(working.ut_id, tofind->ut_id, sizeof(tofind->ut_id)); 2974d522f475Smrg#if defined(__digital__) && defined(__unix__) && (defined(OSMAJORVERSION) && OSMAJORVERSION < 5) 2975d522f475Smrg working.ut_type = 0; 2976d522f475Smrg#endif 2977d522f475Smrg if ((result = call_getutid(&working)) == 0) 2978d522f475Smrg break; 2979d522f475Smrg if (!strcmp(result->ut_line, tofind->ut_line)) 2980d522f475Smrg break; 2981d522f475Smrg /* 2982d522f475Smrg * Solaris, IRIX64 and HPUX manpages say to fill the static area 2983d522f475Smrg * pointed to by the return-value to zeros if searching for multiple 2984d522f475Smrg * occurrences. Otherwise it will continue to return the same value. 2985d522f475Smrg */ 2986d522f475Smrg memset(result, 0, sizeof(*result)); 2987d522f475Smrg } 2988d522f475Smrg return result; 2989d522f475Smrg} 2990d522f475Smrg#endif /* HAVE_UTMP... */ 2991d522f475Smrg 2992d522f475Smrg#define close_fd(fd) close(fd), fd = -1 2993d522f475Smrg 299420d2c4d2Smrg#if defined(TIOCNOTTY) && (!defined(__GLIBC__) || (__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))) 299520d2c4d2Smrg#define USE_NO_DEV_TTY 1 299620d2c4d2Smrg#else 299720d2c4d2Smrg#define USE_NO_DEV_TTY 0 299820d2c4d2Smrg#endif 299920d2c4d2Smrg 3000d522f475Smrg/* 3001d522f475Smrg * Inits pty and tty and forks a login process. 3002d522f475Smrg * Does not close fd Xsocket. 3003d522f475Smrg * If slave, the pty named in passedPty is already open for use 3004d522f475Smrg */ 3005d522f475Smrgstatic int 3006d522f475SmrgspawnXTerm(XtermWidget xw) 3007d522f475Smrg{ 3008d522f475Smrg TScreen *screen = TScreenOf(xw); 3009d522f475Smrg Cardinal nn; 3010d522f475Smrg#if OPT_PTY_HANDSHAKE 3011d522f475Smrg Bool got_handshake_size = False; 3012d522f475Smrg handshake_t handshake; 3013d522f475Smrg int done; 3014d522f475Smrg#endif 3015d522f475Smrg#if OPT_INITIAL_ERASE 3016d522f475Smrg int initial_erase = VAL_INITIAL_ERASE; 3017d522f475Smrg Bool setInitialErase; 3018d522f475Smrg#endif 3019d522f475Smrg int rc = 0; 3020d522f475Smrg int ttyfd = -1; 3021d522f475Smrg Bool ok_termcap; 3022d522f475Smrg char *newtc; 3023d522f475Smrg 3024d522f475Smrg#ifdef TERMIO_STRUCT 3025d522f475Smrg TERMIO_STRUCT tio; 3026d522f475Smrg#ifdef __MVS__ 3027d522f475Smrg TERMIO_STRUCT gio; 3028d522f475Smrg#endif /* __MVS__ */ 3029d522f475Smrg#ifdef TIOCLSET 3030d522f475Smrg unsigned lmode; 3031d522f475Smrg#endif /* TIOCLSET */ 3032d522f475Smrg#ifdef HAS_LTCHARS 3033d522f475Smrg struct ltchars ltc; 3034d522f475Smrg#endif /* HAS_LTCHARS */ 3035d522f475Smrg#else /* !TERMIO_STRUCT */ 3036d522f475Smrg int ldisc = 0; 3037d522f475Smrg int discipline; 3038d522f475Smrg unsigned lmode; 3039d522f475Smrg struct tchars tc; 3040d522f475Smrg struct ltchars ltc; 3041d522f475Smrg struct sgttyb sg; 3042d522f475Smrg#ifdef sony 3043d522f475Smrg int jmode; 3044d522f475Smrg struct jtchars jtc; 3045d522f475Smrg#endif /* sony */ 3046d522f475Smrg#endif /* TERMIO_STRUCT */ 3047d522f475Smrg 3048d522f475Smrg char *ptr, *shname, *shname_minus; 304920d2c4d2Smrg int i; 305020d2c4d2Smrg#if USE_NO_DEV_TTY 305120d2c4d2Smrg int no_dev_tty = False; 305220d2c4d2Smrg#endif 305320d2c4d2Smrg const char **envnew; /* new environment */ 3054d522f475Smrg char buf[64]; 3055d522f475Smrg char *TermName = NULL; 3056d522f475Smrg#ifdef TTYSIZE_STRUCT 3057d522f475Smrg TTYSIZE_STRUCT ts; 3058d522f475Smrg#endif 3059d522f475Smrg struct passwd *pw = NULL; 3060d522f475Smrg char *login_name = NULL; 3061d522f475Smrg#ifndef USE_UTEMPTER 3062d522f475Smrg#ifdef HAVE_UTMP 3063d522f475Smrg struct UTMP_STR utmp; 3064d522f475Smrg#ifdef USE_SYSV_UTMP 3065d522f475Smrg struct UTMP_STR *utret = NULL; 3066d522f475Smrg#endif 3067d522f475Smrg#ifdef USE_LASTLOG 3068d522f475Smrg struct lastlog lastlog; 3069d522f475Smrg#endif 3070d522f475Smrg#ifdef USE_LASTLOGX 3071d522f475Smrg struct lastlogx lastlogx; 3072d522f475Smrg#endif /* USE_LASTLOG */ 3073d522f475Smrg#endif /* HAVE_UTMP */ 3074d522f475Smrg#endif /* !USE_UTEMPTER */ 3075d522f475Smrg 3076d522f475Smrg /* Noisy compilers (suppress some unused-variable warnings) */ 3077d522f475Smrg (void) rc; 3078d522f475Smrg#if defined(HAVE_UTMP) && defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 3079d522f475Smrg (void) utret; 3080d522f475Smrg#endif 3081d522f475Smrg 3082d522f475Smrg screen->uid = save_ruid; 3083d522f475Smrg screen->gid = save_rgid; 3084d522f475Smrg 3085d522f475Smrg#ifdef SIGTTOU 3086d522f475Smrg /* so that TIOCSWINSZ || TIOCSIZE doesn't block */ 3087d522f475Smrg signal(SIGTTOU, SIG_IGN); 3088d522f475Smrg#endif 3089d522f475Smrg 3090d522f475Smrg#if OPT_PTY_HANDSHAKE 3091d522f475Smrg memset(&handshake, 0, sizeof(handshake)); 3092d522f475Smrg#endif 3093d522f475Smrg 3094d522f475Smrg if (am_slave >= 0) { 3095d522f475Smrg screen->respond = am_slave; 3096d522f475Smrg set_pty_id(ttydev, passedPty); 3097d522f475Smrg#ifdef USE_PTY_DEVICE 3098d522f475Smrg set_pty_id(ptydev, passedPty); 3099d522f475Smrg#endif 3100d522f475Smrg if (xtermResetIds(screen) < 0) 3101d522f475Smrg exit(1); 3102d522f475Smrg } else { 3103d522f475Smrg Bool tty_got_hung; 3104d522f475Smrg 3105d522f475Smrg /* 3106d522f475Smrg * Sometimes /dev/tty hangs on open (as in the case of a pty 3107d522f475Smrg * that has gone away). Simply make up some reasonable 3108d522f475Smrg * defaults. 3109d522f475Smrg */ 3110d522f475Smrg 3111d522f475Smrg signal(SIGALRM, hungtty); 3112d522f475Smrg alarm(2); /* alarm(1) might return too soon */ 3113d522f475Smrg if (!sigsetjmp(env, 1)) { 3114d522f475Smrg ttyfd = open("/dev/tty", O_RDWR); 3115d522f475Smrg alarm(0); 3116d522f475Smrg tty_got_hung = False; 3117d522f475Smrg } else { 3118d522f475Smrg tty_got_hung = True; 3119d522f475Smrg ttyfd = -1; 3120d522f475Smrg errno = ENXIO; 3121d522f475Smrg } 3122d522f475Smrg pw = NULL; 3123d522f475Smrg#if OPT_PTY_HANDSHAKE 3124d522f475Smrg got_handshake_size = False; 3125d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 3126d522f475Smrg#if OPT_INITIAL_ERASE 3127d522f475Smrg initial_erase = VAL_INITIAL_ERASE; 3128d522f475Smrg#endif 3129d522f475Smrg signal(SIGALRM, SIG_DFL); 3130d522f475Smrg 3131d522f475Smrg /* 3132d522f475Smrg * Check results and ignore current control terminal if 3133d522f475Smrg * necessary. ENXIO is what is normally returned if there is 3134d522f475Smrg * no controlling terminal, but some systems (e.g. SunOS 4.0) 3135d522f475Smrg * seem to return EIO. Solaris 2.3 is said to return EINVAL. 3136d522f475Smrg * Cygwin returns ENOENT. 3137d522f475Smrg */ 313820d2c4d2Smrg#if USE_NO_DEV_TTY 3139d522f475Smrg no_dev_tty = False; 314020d2c4d2Smrg#endif 3141d522f475Smrg if (ttyfd < 0) { 3142d522f475Smrg if (tty_got_hung || errno == ENXIO || errno == EIO || 3143d522f475Smrg#ifdef ENODEV 3144d522f475Smrg errno == ENODEV || 3145d522f475Smrg#endif 3146d522f475Smrg#ifdef __CYGWIN__ 3147d522f475Smrg errno == ENOENT || 3148d522f475Smrg#endif 3149d522f475Smrg errno == EINVAL || errno == ENOTTY || errno == EACCES) { 315020d2c4d2Smrg#if USE_NO_DEV_TTY 3151d522f475Smrg no_dev_tty = True; 315220d2c4d2Smrg#endif 3153d522f475Smrg#ifdef HAS_LTCHARS 3154d522f475Smrg ltc = d_ltc; 3155d522f475Smrg#endif /* HAS_LTCHARS */ 3156d522f475Smrg#ifdef TIOCLSET 3157d522f475Smrg lmode = d_lmode; 3158d522f475Smrg#endif /* TIOCLSET */ 3159d522f475Smrg#ifdef TERMIO_STRUCT 3160d522f475Smrg tio = d_tio; 3161d522f475Smrg#else /* !TERMIO_STRUCT */ 3162d522f475Smrg sg = d_sg; 3163d522f475Smrg tc = d_tc; 3164d522f475Smrg discipline = d_disipline; 3165d522f475Smrg#ifdef sony 3166d522f475Smrg jmode = d_jmode; 3167d522f475Smrg jtc = d_jtc; 3168d522f475Smrg#endif /* sony */ 3169d522f475Smrg#endif /* TERMIO_STRUCT */ 3170d522f475Smrg } else { 3171d522f475Smrg SysError(ERROR_OPDEVTTY); 3172d522f475Smrg } 3173d522f475Smrg } else { 3174d522f475Smrg 3175d522f475Smrg /* Get a copy of the current terminal's state, 3176d522f475Smrg * if we can. Some systems (e.g., SVR4 and MacII) 3177d522f475Smrg * may not have a controlling terminal at this point 3178d522f475Smrg * if started directly from xdm or xinit, 3179d522f475Smrg * in which case we just use the defaults as above. 3180d522f475Smrg */ 3181d522f475Smrg#ifdef HAS_LTCHARS 3182d522f475Smrg if (ioctl(ttyfd, TIOCGLTC, <c) == -1) 3183d522f475Smrg ltc = d_ltc; 3184d522f475Smrg#endif /* HAS_LTCHARS */ 3185d522f475Smrg#ifdef TIOCLSET 3186d522f475Smrg if (ioctl(ttyfd, TIOCLGET, &lmode) == -1) 3187d522f475Smrg lmode = d_lmode; 3188d522f475Smrg#endif /* TIOCLSET */ 3189d522f475Smrg#ifdef TERMIO_STRUCT 319020d2c4d2Smrg rc = ttyGetAttr(ttyfd, &tio); 319120d2c4d2Smrg if (rc == -1) 3192d522f475Smrg tio = d_tio; 3193d522f475Smrg#else /* !TERMIO_STRUCT */ 319420d2c4d2Smrg rc = ioctl(ttyfd, TIOCGETP, (char *) &sg); 319520d2c4d2Smrg if (rc == -1) 3196d522f475Smrg sg = d_sg; 3197d522f475Smrg if (ioctl(ttyfd, TIOCGETC, (char *) &tc) == -1) 3198d522f475Smrg tc = d_tc; 3199d522f475Smrg if (ioctl(ttyfd, TIOCGETD, (char *) &discipline) == -1) 3200d522f475Smrg discipline = d_disipline; 3201d522f475Smrg#ifdef sony 3202d522f475Smrg if (ioctl(ttyfd, TIOCKGET, (char *) &jmode) == -1) 3203d522f475Smrg jmode = d_jmode; 3204d522f475Smrg if (ioctl(ttyfd, TIOCKGETC, (char *) &jtc) == -1) 3205d522f475Smrg jtc = d_jtc; 3206d522f475Smrg#endif /* sony */ 3207d522f475Smrg#endif /* TERMIO_STRUCT */ 3208d522f475Smrg 3209d522f475Smrg /* 3210d522f475Smrg * If ptyInitialErase is set, we want to get the pty's 3211d522f475Smrg * erase value. Just in case that will fail, first get 3212d522f475Smrg * the value from /dev/tty, so we will have something 3213d522f475Smrg * at least. 3214d522f475Smrg */ 3215d522f475Smrg#if OPT_INITIAL_ERASE 3216d522f475Smrg if (resource.ptyInitialErase) { 3217d522f475Smrg#ifdef TERMIO_STRUCT 3218d522f475Smrg initial_erase = tio.c_cc[VERASE]; 3219d522f475Smrg#else /* !TERMIO_STRUCT */ 3220d522f475Smrg initial_erase = sg.sg_erase; 3221d522f475Smrg#endif /* TERMIO_STRUCT */ 3222d522f475Smrg TRACE(("%s initial_erase:%d (from /dev/tty)\n", 3223d522f475Smrg rc == 0 ? "OK" : "FAIL", 3224d522f475Smrg initial_erase)); 3225d522f475Smrg } 3226d522f475Smrg#endif 3227d522f475Smrg#ifdef __MVS__ 3228d522f475Smrg if (ttyGetAttr(ttyfd, &gio) == 0) { 3229d522f475Smrg gio.c_cflag &= ~(HUPCL | PARENB); 3230d522f475Smrg ttySetAttr(ttyfd, &gio); 3231d522f475Smrg } 3232d522f475Smrg#endif /* __MVS__ */ 3233d522f475Smrg 3234d522f475Smrg close_fd(ttyfd); 3235d522f475Smrg } 3236d522f475Smrg 3237d522f475Smrg if (get_pty(&screen->respond, XDisplayString(screen->display))) { 3238d522f475Smrg SysError(ERROR_PTYS); 3239d522f475Smrg } 3240d522f475Smrg#if OPT_INITIAL_ERASE 3241d522f475Smrg if (resource.ptyInitialErase) { 3242d522f475Smrg#ifdef TERMIO_STRUCT 3243d522f475Smrg TERMIO_STRUCT my_tio; 324420d2c4d2Smrg rc = ttyGetAttr(screen->respond, &my_tio); 324520d2c4d2Smrg if (rc == 0) 3246d522f475Smrg initial_erase = my_tio.c_cc[VERASE]; 3247d522f475Smrg#else /* !TERMIO_STRUCT */ 3248d522f475Smrg struct sgttyb my_sg; 324920d2c4d2Smrg rc = ioctl(screen->respond, TIOCGETP, (char *) &my_sg); 325020d2c4d2Smrg if (rc == 0) 3251d522f475Smrg initial_erase = my_sg.sg_erase; 3252d522f475Smrg#endif /* TERMIO_STRUCT */ 3253d522f475Smrg TRACE(("%s initial_erase:%d (from pty)\n", 3254d522f475Smrg (rc == 0) ? "OK" : "FAIL", 3255d522f475Smrg initial_erase)); 3256d522f475Smrg } 3257d522f475Smrg#endif /* OPT_INITIAL_ERASE */ 3258d522f475Smrg } 3259d522f475Smrg 3260d522f475Smrg /* avoid double MapWindow requests */ 3261d522f475Smrg XtSetMappedWhenManaged(SHELL_OF(CURRENT_EMU()), False); 3262d522f475Smrg 3263d522f475Smrg wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", 3264d522f475Smrg False); 3265d522f475Smrg 3266d522f475Smrg if (!TEK4014_ACTIVE(xw)) 3267956cc18dSsnj VTInit(xw); /* realize now so know window size for tty driver */ 3268d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 3269d522f475Smrg if (Console) { 3270d522f475Smrg /* 3271d522f475Smrg * Inform any running xconsole program 3272d522f475Smrg * that we are going to steal the console. 3273d522f475Smrg */ 3274d522f475Smrg XmuGetHostname(mit_console_name + MIT_CONSOLE_LEN, 255); 3275d522f475Smrg mit_console = XInternAtom(screen->display, mit_console_name, False); 3276d522f475Smrg /* the user told us to be the console, so we can use CurrentTime */ 3277d522f475Smrg XtOwnSelection(SHELL_OF(CURRENT_EMU()), 3278d522f475Smrg mit_console, CurrentTime, 3279d522f475Smrg ConvertConsoleSelection, NULL, NULL); 3280d522f475Smrg } 3281d522f475Smrg#endif 3282d522f475Smrg#if OPT_TEK4014 3283d522f475Smrg if (TEK4014_ACTIVE(xw)) { 3284d522f475Smrg envnew = tekterm; 3285d522f475Smrg } else 3286d522f475Smrg#endif 3287d522f475Smrg { 3288d522f475Smrg envnew = vtterm; 3289d522f475Smrg } 3290d522f475Smrg 3291d522f475Smrg /* 3292d522f475Smrg * This used to exit if no termcap entry was found for the specified 3293d522f475Smrg * terminal name. That's a little unfriendly, so instead we'll allow 3294d522f475Smrg * the program to proceed (but not to set $TERMCAP) if the termcap 3295d522f475Smrg * entry is not found. 3296d522f475Smrg */ 3297d522f475Smrg ok_termcap = True; 329820d2c4d2Smrg if (!get_termcap(xw, TermName = resource.term_name)) { 329920d2c4d2Smrg const char *last = NULL; 330020d2c4d2Smrg char *next; 330120d2c4d2Smrg 330220d2c4d2Smrg TermName = x_strdup(*envnew); 3303d522f475Smrg ok_termcap = False; 3304d522f475Smrg while (*envnew != NULL) { 330520d2c4d2Smrg if (last == NULL || strcmp(last, *envnew)) { 330620d2c4d2Smrg next = x_strdup(*envnew); 330720d2c4d2Smrg if (get_termcap(xw, next)) { 330820d2c4d2Smrg free(TermName); 330920d2c4d2Smrg TermName = next; 331020d2c4d2Smrg ok_termcap = True; 331120d2c4d2Smrg break; 331220d2c4d2Smrg } else { 331320d2c4d2Smrg free(next); 331420d2c4d2Smrg } 3315d522f475Smrg } 3316d522f475Smrg last = *envnew; 3317d522f475Smrg envnew++; 3318d522f475Smrg } 3319d522f475Smrg } 3320d522f475Smrg if (ok_termcap) { 332120d2c4d2Smrg resize_termcap(xw); 3322d522f475Smrg } 3323d522f475Smrg 3324d522f475Smrg /* 3325d522f475Smrg * Check if ptyInitialErase is not set. If so, we rely on the termcap 3326d522f475Smrg * (or terminfo) to tell us what the erase mode should be set to. 3327d522f475Smrg */ 3328d522f475Smrg#if OPT_INITIAL_ERASE 3329d522f475Smrg TRACE(("resource ptyInitialErase is %sset\n", 3330d522f475Smrg resource.ptyInitialErase ? "" : "not ")); 3331d522f475Smrg setInitialErase = False; 3332d522f475Smrg if (override_tty_modes && ttymodelist[XTTYMODE_erase].set) { 3333d522f475Smrg initial_erase = ttymodelist[XTTYMODE_erase].value; 3334d522f475Smrg setInitialErase = True; 3335d522f475Smrg } else if (resource.ptyInitialErase) { 3336d522f475Smrg ; 3337d522f475Smrg } else if (ok_termcap) { 333820d2c4d2Smrg char *s = get_tcap_erase(xw); 3339d522f475Smrg TRACE(("...extracting initial_erase value from termcap\n")); 3340d522f475Smrg if (s != 0) { 334120d2c4d2Smrg char *save = s; 3342d522f475Smrg initial_erase = decode_keyvalue(&s, True); 3343d522f475Smrg setInitialErase = True; 334420d2c4d2Smrg free(save); 3345d522f475Smrg } 3346d522f475Smrg } 3347d522f475Smrg TRACE(("...initial_erase:%d\n", initial_erase)); 3348d522f475Smrg 3349d522f475Smrg TRACE(("resource backarrowKeyIsErase is %sset\n", 3350d522f475Smrg resource.backarrow_is_erase ? "" : "not ")); 3351d522f475Smrg if (resource.backarrow_is_erase) { /* see input.c */ 3352d522f475Smrg if (initial_erase == ANSI_DEL) { 335320d2c4d2Smrg UIntClr(xw->keyboard.flags, MODE_DECBKM); 3354d522f475Smrg } else { 3355d522f475Smrg xw->keyboard.flags |= MODE_DECBKM; 3356d522f475Smrg xw->keyboard.reset_DECBKM = 1; 3357d522f475Smrg } 3358d522f475Smrg TRACE(("...sets DECBKM %s\n", 3359d522f475Smrg (xw->keyboard.flags & MODE_DECBKM) ? "on" : "off")); 3360d522f475Smrg } else { 3361d522f475Smrg xw->keyboard.reset_DECBKM = 2; 3362d522f475Smrg } 3363d522f475Smrg#endif /* OPT_INITIAL_ERASE */ 3364d522f475Smrg 3365d522f475Smrg#ifdef TTYSIZE_STRUCT 3366d522f475Smrg /* tell tty how big window is */ 3367d522f475Smrg#if OPT_TEK4014 3368d522f475Smrg if (TEK4014_ACTIVE(xw)) { 3369d522f475Smrg TTYSIZE_ROWS(ts) = 38; 3370d522f475Smrg TTYSIZE_COLS(ts) = 81; 3371d522f475Smrg#if defined(USE_STRUCT_WINSIZE) 337220d2c4d2Smrg ts.ws_xpixel = TFullWidth(TekScreenOf(tekWidget)); 337320d2c4d2Smrg ts.ws_ypixel = TFullHeight(TekScreenOf(tekWidget)); 3374d522f475Smrg#endif 3375d522f475Smrg } else 3376d522f475Smrg#endif 3377d522f475Smrg { 337820d2c4d2Smrg TTYSIZE_ROWS(ts) = (ttySize_t) MaxRows(screen); 337920d2c4d2Smrg TTYSIZE_COLS(ts) = (ttySize_t) MaxCols(screen); 3380d522f475Smrg#if defined(USE_STRUCT_WINSIZE) 338120d2c4d2Smrg ts.ws_xpixel = (ttySize_t) FullWidth(screen); 338220d2c4d2Smrg ts.ws_ypixel = (ttySize_t) FullHeight(screen); 3383d522f475Smrg#endif 3384d522f475Smrg } 338520d2c4d2Smrg TRACE_RC(i, SET_TTYSIZE(screen->respond, ts)); 3386d522f475Smrg TRACE(("spawn SET_TTYSIZE %dx%d return %d\n", 3387d522f475Smrg TTYSIZE_ROWS(ts), 3388d522f475Smrg TTYSIZE_COLS(ts), i)); 3389d522f475Smrg#endif /* TTYSIZE_STRUCT */ 3390d522f475Smrg 3391d522f475Smrg added_utmp_entry = False; 3392d522f475Smrg#if defined(USE_UTEMPTER) 3393d522f475Smrg#undef UTMP 3394d522f475Smrg if (!resource.utmpInhibit) { 3395d522f475Smrg struct UTMP_STR dummy; 3396d522f475Smrg 3397d522f475Smrg /* Note: utempter may trim it anyway */ 3398d522f475Smrg SetUtmpHost(dummy.ut_host, screen); 3399d522f475Smrg addToUtmp(ttydev, dummy.ut_host, screen->respond); 3400d522f475Smrg added_utmp_entry = True; 3401d522f475Smrg } 3402d522f475Smrg#endif 3403d522f475Smrg 3404d522f475Smrg if (am_slave < 0) { 3405d522f475Smrg#if OPT_PTY_HANDSHAKE 3406d522f475Smrg if (resource.ptyHandshake && (pipe(pc_pipe) || pipe(cp_pipe))) 3407d522f475Smrg SysError(ERROR_FORK); 3408d522f475Smrg#endif 3409d522f475Smrg TRACE(("Forking...\n")); 3410d522f475Smrg if ((screen->pid = fork()) == -1) 3411d522f475Smrg SysError(ERROR_FORK); 3412d522f475Smrg 3413d522f475Smrg if (screen->pid == 0) { 3414d522f475Smrg#ifdef USE_USG_PTYS 341520d2c4d2Smrg int ptyfd = -1; 3416d522f475Smrg char *pty_name; 3417d522f475Smrg#endif 3418d522f475Smrg /* 3419d522f475Smrg * now in child process 3420d522f475Smrg */ 3421d522f475Smrg#if defined(_POSIX_SOURCE) || defined(SVR4) || defined(__convex__) || defined(__SCO__) || defined(__QNX__) 3422d522f475Smrg int pgrp = setsid(); /* variable may not be used... */ 3423d522f475Smrg#else 3424d522f475Smrg int pgrp = getpid(); 3425d522f475Smrg#endif 3426d522f475Smrg TRACE_CHILD 3427d522f475Smrg 3428d522f475Smrg#ifdef USE_USG_PTYS 3429d522f475Smrg#ifdef USE_ISPTS_FLAG 3430d522f475Smrg if (IsPts) { /* SYSV386 supports both, which did we open? */ 3431d522f475Smrg#endif 3432d522f475Smrg setpgrp(); 3433d522f475Smrg grantpt(screen->respond); 3434d522f475Smrg unlockpt(screen->respond); 3435d522f475Smrg if ((pty_name = ptsname(screen->respond)) == 0) { 3436d522f475Smrg SysError(ERROR_PTSNAME); 343720d2c4d2Smrg } else if ((ptyfd = open(pty_name, O_RDWR)) < 0) { 3438d522f475Smrg SysError(ERROR_OPPTSNAME); 3439d522f475Smrg } 3440d522f475Smrg#ifdef I_PUSH 344120d2c4d2Smrg else if (ioctl(ptyfd, I_PUSH, "ptem") < 0) { 3442d522f475Smrg SysError(ERROR_PTEM); 3443d522f475Smrg } 3444d522f475Smrg#if !defined(SVR4) && !(defined(SYSV) && defined(i386)) 344520d2c4d2Smrg else if (!x_getenv("CONSEM") 344620d2c4d2Smrg && ioctl(ptyfd, I_PUSH, "consem") < 0) { 3447d522f475Smrg SysError(ERROR_CONSEM); 3448d522f475Smrg } 3449d522f475Smrg#endif /* !SVR4 */ 345020d2c4d2Smrg else if (ioctl(ptyfd, I_PUSH, "ldterm") < 0) { 3451d522f475Smrg SysError(ERROR_LDTERM); 3452d522f475Smrg } 3453d522f475Smrg#ifdef SVR4 /* from Sony */ 345420d2c4d2Smrg else if (ioctl(ptyfd, I_PUSH, "ttcompat") < 0) { 3455d522f475Smrg SysError(ERROR_TTCOMPAT); 3456d522f475Smrg } 3457d522f475Smrg#endif /* SVR4 */ 3458d522f475Smrg#endif /* I_PUSH */ 3459d522f475Smrg ttyfd = ptyfd; 3460d522f475Smrg#ifndef __MVS__ 3461d522f475Smrg close_fd(screen->respond); 3462d522f475Smrg#endif /* __MVS__ */ 3463d522f475Smrg 3464d522f475Smrg#ifdef TTYSIZE_STRUCT 3465d522f475Smrg /* tell tty how big window is */ 3466d522f475Smrg#if OPT_TEK4014 3467d522f475Smrg if (TEK4014_ACTIVE(xw)) { 3468d522f475Smrg TTYSIZE_ROWS(ts) = 24; 3469d522f475Smrg TTYSIZE_COLS(ts) = 80; 3470d522f475Smrg#ifdef USE_STRUCT_WINSIZE 347120d2c4d2Smrg ts.ws_xpixel = TFullWidth(TekScreenOf(tekWidget)); 347220d2c4d2Smrg ts.ws_ypixel = TFullHeight(TekScreenOf(tekWidget)); 3473d522f475Smrg#endif 3474d522f475Smrg } else 3475d522f475Smrg#endif /* OPT_TEK4014 */ 3476d522f475Smrg { 347720d2c4d2Smrg TTYSIZE_ROWS(ts) = (ttySize_t) MaxRows(screen); 347820d2c4d2Smrg TTYSIZE_COLS(ts) = (ttySize_t) MaxCols(screen); 3479d522f475Smrg#ifdef USE_STRUCT_WINSIZE 348020d2c4d2Smrg ts.ws_xpixel = (ttySize_t) FullWidth(screen); 348120d2c4d2Smrg ts.ws_ypixel = (ttySize_t) FullHeight(screen); 3482d522f475Smrg#endif 3483d522f475Smrg } 3484d522f475Smrg#endif /* TTYSIZE_STRUCT */ 3485d522f475Smrg 3486d522f475Smrg#ifdef USE_ISPTS_FLAG 3487d522f475Smrg } else { /* else pty, not pts */ 3488d522f475Smrg#endif 3489d522f475Smrg#endif /* USE_USG_PTYS */ 3490d522f475Smrg 3491d522f475Smrg (void) pgrp; /* not all branches use this variable */ 3492d522f475Smrg 3493d522f475Smrg#if OPT_PTY_HANDSHAKE /* warning, goes for a long ways */ 3494d522f475Smrg if (resource.ptyHandshake) { 3495d522f475Smrg /* close parent's sides of the pipes */ 3496d522f475Smrg close(cp_pipe[0]); 3497d522f475Smrg close(pc_pipe[1]); 3498d522f475Smrg 3499d522f475Smrg /* Make sure that our sides of the pipes are not in the 3500d522f475Smrg * 0, 1, 2 range so that we don't fight with stdin, out 3501d522f475Smrg * or err. 3502d522f475Smrg */ 3503d522f475Smrg if (cp_pipe[1] <= 2) { 3504d522f475Smrg if ((i = fcntl(cp_pipe[1], F_DUPFD, 3)) >= 0) { 350520d2c4d2Smrg IGNORE_RC(close(cp_pipe[1])); 3506d522f475Smrg cp_pipe[1] = i; 3507d522f475Smrg } 3508d522f475Smrg } 3509d522f475Smrg if (pc_pipe[0] <= 2) { 3510d522f475Smrg if ((i = fcntl(pc_pipe[0], F_DUPFD, 3)) >= 0) { 351120d2c4d2Smrg IGNORE_RC(close(pc_pipe[0])); 3512d522f475Smrg pc_pipe[0] = i; 3513d522f475Smrg } 3514d522f475Smrg } 3515d522f475Smrg 3516d522f475Smrg /* we don't need the socket, or the pty master anymore */ 3517d522f475Smrg close(ConnectionNumber(screen->display)); 3518d522f475Smrg#ifndef __MVS__ 351920d2c4d2Smrg if (screen->respond >= 0) 352020d2c4d2Smrg close(screen->respond); 3521d522f475Smrg#endif /* __MVS__ */ 3522d522f475Smrg 3523d522f475Smrg /* Now is the time to set up our process group and 3524d522f475Smrg * open up the pty slave. 3525d522f475Smrg */ 3526d522f475Smrg#ifdef USE_SYSV_PGRP 3527d522f475Smrg#if defined(CRAY) && (OSMAJORVERSION > 5) 352820d2c4d2Smrg IGNORE_RC(setsid()); 3529d522f475Smrg#else 353020d2c4d2Smrg IGNORE_RC(setpgrp()); 3531d522f475Smrg#endif 3532d522f475Smrg#endif /* USE_SYSV_PGRP */ 3533d522f475Smrg 3534d522f475Smrg#if defined(__QNX__) && !defined(__QNXNTO__) 3535d522f475Smrg qsetlogin(getlogin(), ttydev); 3536d522f475Smrg#endif 3537d522f475Smrg if (ttyfd >= 0) { 3538d522f475Smrg#ifdef __MVS__ 3539d522f475Smrg if (ttyGetAttr(ttyfd, &gio) == 0) { 3540d522f475Smrg gio.c_cflag &= ~(HUPCL | PARENB); 3541d522f475Smrg ttySetAttr(ttyfd, &gio); 3542d522f475Smrg } 3543d522f475Smrg#else /* !__MVS__ */ 3544d522f475Smrg close_fd(ttyfd); 3545d522f475Smrg#endif /* __MVS__ */ 3546d522f475Smrg } 3547d522f475Smrg 3548d522f475Smrg while (1) { 354920d2c4d2Smrg#if USE_NO_DEV_TTY 3550d522f475Smrg if (!no_dev_tty 3551d522f475Smrg && (ttyfd = open("/dev/tty", O_RDWR)) >= 0) { 3552d522f475Smrg ioctl(ttyfd, TIOCNOTTY, (char *) NULL); 3553d522f475Smrg close_fd(ttyfd); 3554d522f475Smrg } 355520d2c4d2Smrg#endif /* USE_NO_DEV_TTY */ 3556d522f475Smrg#ifdef CSRG_BASED 355720d2c4d2Smrg IGNORE_RC(revoke(ttydev)); 3558d522f475Smrg#endif 3559d522f475Smrg if ((ttyfd = open(ttydev, O_RDWR)) >= 0) { 3560d522f475Smrg#if defined(CRAY) && defined(TCSETCTTY) 3561d522f475Smrg /* make /dev/tty work */ 3562d522f475Smrg ioctl(ttyfd, TCSETCTTY, 0); 3563d522f475Smrg#endif 3564d522f475Smrg#if ((defined(__GLIBC__) && defined(__FreeBSD_kernel__)) || defined(__GNU__)) && defined(TIOCSCTTY) 3565d522f475Smrg /* make /dev/tty work */ 3566d522f475Smrg ioctl(ttyfd, TIOCSCTTY, 0); 3567d522f475Smrg#endif 3568d522f475Smrg#ifdef USE_SYSV_PGRP 3569d522f475Smrg /* We need to make sure that we are actually 3570d522f475Smrg * the process group leader for the pty. If 3571d522f475Smrg * we are, then we should now be able to open 3572d522f475Smrg * /dev/tty. 3573d522f475Smrg */ 3574d522f475Smrg if ((i = open("/dev/tty", O_RDWR)) >= 0) { 3575d522f475Smrg /* success! */ 3576d522f475Smrg close(i); 3577d522f475Smrg break; 3578d522f475Smrg } 3579d522f475Smrg#else /* USE_SYSV_PGRP */ 3580d522f475Smrg break; 3581d522f475Smrg#endif /* USE_SYSV_PGRP */ 3582d522f475Smrg } 3583d522f475Smrg perror("open ttydev"); 3584d522f475Smrg#ifdef TIOCSCTTY 3585d522f475Smrg ioctl(ttyfd, TIOCSCTTY, 0); 3586d522f475Smrg#endif 3587d522f475Smrg /* let our master know that the open failed */ 3588d522f475Smrg handshake.status = PTY_BAD; 3589d522f475Smrg handshake.error = errno; 3590d522f475Smrg strcpy(handshake.buffer, ttydev); 3591d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 359220d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], 359320d2c4d2Smrg (const char *) &handshake, 359420d2c4d2Smrg sizeof(handshake))); 3595d522f475Smrg 3596d522f475Smrg /* get reply from parent */ 359720d2c4d2Smrg i = (int) read(pc_pipe[0], (char *) &handshake, 359820d2c4d2Smrg sizeof(handshake)); 3599d522f475Smrg if (i <= 0) { 3600d522f475Smrg /* parent terminated */ 3601d522f475Smrg exit(1); 3602d522f475Smrg } 3603d522f475Smrg 3604d522f475Smrg if (handshake.status == PTY_NOMORE) { 3605d522f475Smrg /* No more ptys, let's shutdown. */ 3606d522f475Smrg exit(1); 3607d522f475Smrg } 3608d522f475Smrg 3609d522f475Smrg /* We have a new pty to try */ 3610d522f475Smrg free(ttydev); 361120d2c4d2Smrg ttydev = x_strdup(handshake.buffer); 3612d522f475Smrg } 3613d522f475Smrg 3614d522f475Smrg /* use the same tty name that everyone else will use 3615d522f475Smrg * (from ttyname) 3616d522f475Smrg */ 3617d522f475Smrg if ((ptr = ttyname(ttyfd)) != 0) { 361820d2c4d2Smrg free(ttydev); 361920d2c4d2Smrg ttydev = x_strdup(ptr); 3620d522f475Smrg } 3621d522f475Smrg } 3622d522f475Smrg#endif /* OPT_PTY_HANDSHAKE -- from near fork */ 3623d522f475Smrg 3624d522f475Smrg#ifdef USE_ISPTS_FLAG 3625d522f475Smrg } /* end of IsPts else clause */ 3626d522f475Smrg#endif 3627d522f475Smrg 3628d522f475Smrg set_pty_permissions(screen->uid, 3629d522f475Smrg screen->gid, 3630d522f475Smrg (resource.messages 3631d522f475Smrg ? 0622U 3632d522f475Smrg : 0600U)); 3633d522f475Smrg 3634d522f475Smrg /* 3635d522f475Smrg * set up the tty modes 3636d522f475Smrg */ 3637d522f475Smrg { 3638d522f475Smrg#ifdef TERMIO_STRUCT 3639d522f475Smrg#if defined(umips) || defined(CRAY) || defined(linux) 3640d522f475Smrg /* If the control tty had its modes screwed around with, 3641d522f475Smrg eg. by lineedit in the shell, or emacs, etc. then tio 3642d522f475Smrg will have bad values. Let's just get termio from the 3643d522f475Smrg new tty and tailor it. */ 3644d522f475Smrg if (ttyGetAttr(ttyfd, &tio) == -1) 3645d522f475Smrg SysError(ERROR_TIOCGETP); 3646d522f475Smrg tio.c_lflag |= ECHOE; 3647d522f475Smrg#endif /* umips */ 3648d522f475Smrg /* Now is also the time to change the modes of the 3649d522f475Smrg * child pty. 3650d522f475Smrg */ 3651d522f475Smrg /* input: nl->nl, don't ignore cr, cr->nl */ 365220d2c4d2Smrg UIntClr(tio.c_iflag, (INLCR | IGNCR)); 3653d522f475Smrg tio.c_iflag |= ICRNL; 3654d522f475Smrg#if OPT_WIDE_CHARS && defined(linux) && defined(IUTF8) 3655d522f475Smrg#if OPT_LUIT_PROG 3656d522f475Smrg if (command_to_exec_with_luit == 0) 3657d522f475Smrg#endif 3658d522f475Smrg if (screen->utf8_mode) 3659d522f475Smrg tio.c_iflag |= IUTF8; 3660d522f475Smrg#endif 3661d522f475Smrg /* ouput: cr->cr, nl is not return, no delays, ln->cr/nl */ 3662d522f475Smrg#ifndef USE_POSIX_TERMIOS 366320d2c4d2Smrg UIntClr(tio.c_oflag, 366420d2c4d2Smrg (OCRNL 366520d2c4d2Smrg | ONLRET 366620d2c4d2Smrg | NLDLY 366720d2c4d2Smrg | CRDLY 366820d2c4d2Smrg | TABDLY 366920d2c4d2Smrg | BSDLY 367020d2c4d2Smrg | VTDLY 367120d2c4d2Smrg | FFDLY)); 3672d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 3673d522f475Smrg#ifdef ONLCR 3674d522f475Smrg tio.c_oflag |= ONLCR; 3675d522f475Smrg#endif /* ONLCR */ 3676d522f475Smrg#ifdef OPOST 3677d522f475Smrg tio.c_oflag |= OPOST; 3678d522f475Smrg#endif /* OPOST */ 3679d522f475Smrg#ifndef USE_POSIX_TERMIOS 3680d522f475Smrg# if defined(Lynx) && !defined(CBAUD) 3681d522f475Smrg# define CBAUD V_CBAUD 3682d522f475Smrg# endif 368320d2c4d2Smrg UIntClr(tio.c_cflag, CBAUD); 3684d522f475Smrg#ifdef BAUD_0 3685d522f475Smrg /* baud rate is 0 (don't care) */ 3686d522f475Smrg#elif defined(HAVE_TERMIO_C_ISPEED) 3687d522f475Smrg tio.c_ispeed = tio.c_ospeed = VAL_LINE_SPEED; 3688d522f475Smrg#else /* !BAUD_0 */ 3689d522f475Smrg tio.c_cflag |= VAL_LINE_SPEED; 3690d522f475Smrg#endif /* !BAUD_0 */ 3691d522f475Smrg#else /* USE_POSIX_TERMIOS */ 3692d522f475Smrg cfsetispeed(&tio, VAL_LINE_SPEED); 3693d522f475Smrg cfsetospeed(&tio, VAL_LINE_SPEED); 3694d522f475Smrg#ifdef __MVS__ 3695d522f475Smrg /* turn off bits that can't be set from the slave side */ 3696d522f475Smrg tio.c_cflag &= ~(PACKET | PKT3270 | PTU3270 | PKTXTND); 3697d522f475Smrg#endif /* __MVS__ */ 3698d522f475Smrg /* Clear CLOCAL so that SIGHUP is sent to us 3699d522f475Smrg when the xterm ends */ 3700d522f475Smrg tio.c_cflag &= ~CLOCAL; 3701d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 3702d522f475Smrg /* enable signals, canonical processing (erase, kill, etc), 3703d522f475Smrg * echo 3704d522f475Smrg */ 3705d522f475Smrg tio.c_lflag |= ISIG | ICANON | ECHO | ECHOE | ECHOK; 3706d522f475Smrg#ifdef ECHOKE 3707d522f475Smrg tio.c_lflag |= ECHOKE | IEXTEN; 3708d522f475Smrg#endif 3709d522f475Smrg#ifdef ECHOCTL 3710d522f475Smrg tio.c_lflag |= ECHOCTL | IEXTEN; 3711d522f475Smrg#endif 3712d522f475Smrg for (nn = 0; nn < XtNumber(known_ttyChars); ++nn) { 3713d522f475Smrg if (validTtyChar(tio, nn)) { 3714d522f475Smrg int sysMode = known_ttyChars[nn].sysMode; 3715d522f475Smrg#ifdef __MVS__ 3716d522f475Smrg if (tio.c_cc[sysMode] != 0) { 3717d522f475Smrg switch (sysMode) { 3718d522f475Smrg case VEOL: 3719d522f475Smrg case VEOF: 3720d522f475Smrg continue; 3721d522f475Smrg } 3722d522f475Smrg } 3723d522f475Smrg#endif 3724d522f475Smrg tio.c_cc[sysMode] = known_ttyChars[nn].myDefault; 3725d522f475Smrg } 3726d522f475Smrg } 3727d522f475Smrg 3728d522f475Smrg if (override_tty_modes) { 3729d522f475Smrg for (nn = 0; nn < XtNumber(known_ttyChars); ++nn) { 3730d522f475Smrg if (validTtyChar(tio, nn)) { 3731d522f475Smrg TMODE(known_ttyChars[nn].myMode, 3732d522f475Smrg tio.c_cc[known_ttyChars[nn].sysMode]); 3733d522f475Smrg } 3734d522f475Smrg } 3735d522f475Smrg#ifdef HAS_LTCHARS 3736d522f475Smrg /* both SYSV and BSD have ltchars */ 3737d522f475Smrg TMODE(XTTYMODE_susp, ltc.t_suspc); 3738d522f475Smrg TMODE(XTTYMODE_dsusp, ltc.t_dsuspc); 3739d522f475Smrg TMODE(XTTYMODE_rprnt, ltc.t_rprntc); 3740d522f475Smrg TMODE(XTTYMODE_flush, ltc.t_flushc); 3741d522f475Smrg TMODE(XTTYMODE_weras, ltc.t_werasc); 3742d522f475Smrg TMODE(XTTYMODE_lnext, ltc.t_lnextc); 3743d522f475Smrg#endif 3744d522f475Smrg } 3745d522f475Smrg#ifdef HAS_LTCHARS 3746d522f475Smrg#ifdef __hpux 3747d522f475Smrg /* ioctl chokes when the "reserved" process group controls 3748d522f475Smrg * are not set to _POSIX_VDISABLE */ 3749d522f475Smrg ltc.t_rprntc = ltc.t_rprntc = ltc.t_flushc = 3750d522f475Smrg ltc.t_werasc = ltc.t_lnextc = _POSIX_VDISABLE; 3751d522f475Smrg#endif /* __hpux */ 3752d522f475Smrg if (ioctl(ttyfd, TIOCSLTC, <c) == -1) 3753d522f475Smrg HsSysError(ERROR_TIOCSETC); 3754d522f475Smrg#endif /* HAS_LTCHARS */ 3755d522f475Smrg#ifdef TIOCLSET 3756d522f475Smrg if (ioctl(ttyfd, TIOCLSET, (char *) &lmode) == -1) 3757d522f475Smrg HsSysError(ERROR_TIOCLSET); 3758d522f475Smrg#endif /* TIOCLSET */ 3759d522f475Smrg if (ttySetAttr(ttyfd, &tio) == -1) 3760d522f475Smrg HsSysError(ERROR_TIOCSETP); 3761d522f475Smrg 3762d522f475Smrg /* ignore errors here - some platforms don't work */ 376320d2c4d2Smrg UIntClr(tio.c_cflag, CSIZE); 3764d522f475Smrg if (screen->input_eight_bits) 3765d522f475Smrg tio.c_cflag |= CS8; 3766d522f475Smrg else 3767d522f475Smrg tio.c_cflag |= CS7; 3768d522f475Smrg (void) ttySetAttr(ttyfd, &tio); 3769d522f475Smrg 3770d522f475Smrg#else /* !TERMIO_STRUCT */ 3771d522f475Smrg sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW); 3772d522f475Smrg sg.sg_flags |= ECHO | CRMOD; 3773d522f475Smrg /* make sure speed is set on pty so that editors work right */ 3774d522f475Smrg sg.sg_ispeed = VAL_LINE_SPEED; 3775d522f475Smrg sg.sg_ospeed = VAL_LINE_SPEED; 3776d522f475Smrg /* reset t_brkc to default value */ 3777d522f475Smrg tc.t_brkc = -1; 3778d522f475Smrg#ifdef LPASS8 3779d522f475Smrg if (screen->input_eight_bits) 3780d522f475Smrg lmode |= LPASS8; 3781d522f475Smrg else 3782d522f475Smrg lmode &= ~(LPASS8); 3783d522f475Smrg#endif 3784d522f475Smrg#ifdef sony 3785d522f475Smrg jmode &= ~KM_KANJI; 3786d522f475Smrg#endif /* sony */ 3787d522f475Smrg 3788d522f475Smrg ltc = d_ltc; 3789d522f475Smrg 3790d522f475Smrg if (override_tty_modes) { 3791d522f475Smrg TMODE(XTTYMODE_intr, tc.t_intrc); 3792d522f475Smrg TMODE(XTTYMODE_quit, tc.t_quitc); 3793d522f475Smrg TMODE(XTTYMODE_erase, sg.sg_erase); 3794d522f475Smrg TMODE(XTTYMODE_kill, sg.sg_kill); 3795d522f475Smrg TMODE(XTTYMODE_eof, tc.t_eofc); 3796d522f475Smrg TMODE(XTTYMODE_start, tc.t_startc); 3797d522f475Smrg TMODE(XTTYMODE_stop, tc.t_stopc); 3798d522f475Smrg TMODE(XTTYMODE_brk, tc.t_brkc); 3799d522f475Smrg /* both SYSV and BSD have ltchars */ 3800d522f475Smrg TMODE(XTTYMODE_susp, ltc.t_suspc); 3801d522f475Smrg TMODE(XTTYMODE_dsusp, ltc.t_dsuspc); 3802d522f475Smrg TMODE(XTTYMODE_rprnt, ltc.t_rprntc); 3803d522f475Smrg TMODE(XTTYMODE_flush, ltc.t_flushc); 3804d522f475Smrg TMODE(XTTYMODE_weras, ltc.t_werasc); 3805d522f475Smrg TMODE(XTTYMODE_lnext, ltc.t_lnextc); 3806d522f475Smrg } 3807d522f475Smrg 3808d522f475Smrg if (ioctl(ttyfd, TIOCSETP, (char *) &sg) == -1) 3809d522f475Smrg HsSysError(ERROR_TIOCSETP); 3810d522f475Smrg if (ioctl(ttyfd, TIOCSETC, (char *) &tc) == -1) 3811d522f475Smrg HsSysError(ERROR_TIOCSETC); 3812d522f475Smrg if (ioctl(ttyfd, TIOCSETD, (char *) &discipline) == -1) 3813d522f475Smrg HsSysError(ERROR_TIOCSETD); 3814d522f475Smrg if (ioctl(ttyfd, TIOCSLTC, (char *) <c) == -1) 3815d522f475Smrg HsSysError(ERROR_TIOCSLTC); 3816d522f475Smrg if (ioctl(ttyfd, TIOCLSET, (char *) &lmode) == -1) 3817d522f475Smrg HsSysError(ERROR_TIOCLSET); 3818d522f475Smrg#ifdef sony 3819d522f475Smrg if (ioctl(ttyfd, TIOCKSET, (char *) &jmode) == -1) 3820d522f475Smrg HsSysError(ERROR_TIOCKSET); 3821d522f475Smrg if (ioctl(ttyfd, TIOCKSETC, (char *) &jtc) == -1) 3822d522f475Smrg HsSysError(ERROR_TIOCKSETC); 3823d522f475Smrg#endif /* sony */ 3824d522f475Smrg#endif /* TERMIO_STRUCT */ 3825d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 3826d522f475Smrg if (Console) { 3827d522f475Smrg#ifdef TIOCCONS 3828d522f475Smrg int on = 1; 3829d522f475Smrg if (ioctl(ttyfd, TIOCCONS, (char *) &on) == -1) 3830d522f475Smrg fprintf(stderr, "%s: cannot open console: %s\n", 3831d522f475Smrg ProgramName, strerror(errno)); 3832d522f475Smrg#endif 3833d522f475Smrg#ifdef SRIOCSREDIR 3834d522f475Smrg int fd = open("/dev/console", O_RDWR); 3835d522f475Smrg if (fd == -1 || ioctl(fd, SRIOCSREDIR, ttyfd) == -1) 3836d522f475Smrg fprintf(stderr, "%s: cannot open console: %s\n", 3837d522f475Smrg ProgramName, strerror(errno)); 383820d2c4d2Smrg IGNORE_RC(close(fd)); 3839d522f475Smrg#endif 3840d522f475Smrg } 3841d522f475Smrg#endif /* TIOCCONS */ 3842d522f475Smrg } 3843d522f475Smrg 3844d522f475Smrg signal(SIGCHLD, SIG_DFL); 3845d522f475Smrg#ifdef USE_SYSV_SIGHUP 3846d522f475Smrg /* watch out for extra shells (I don't understand either) */ 3847d522f475Smrg signal(SIGHUP, SIG_DFL); 3848d522f475Smrg#else 3849d522f475Smrg signal(SIGHUP, SIG_IGN); 3850d522f475Smrg#endif 3851d522f475Smrg /* restore various signals to their defaults */ 3852d522f475Smrg signal(SIGINT, SIG_DFL); 3853d522f475Smrg signal(SIGQUIT, SIG_DFL); 3854d522f475Smrg signal(SIGTERM, SIG_DFL); 3855d522f475Smrg 3856d522f475Smrg /* 3857d522f475Smrg * If we're not asked to let the parent process set the terminal's 3858d522f475Smrg * erase mode, or if we had the ttyModes erase resource, then set 3859d522f475Smrg * the terminal's erase mode from our best guess. 3860d522f475Smrg */ 3861d522f475Smrg#if OPT_INITIAL_ERASE 3862d522f475Smrg TRACE(("check if we should set erase to %d:%s\n\tptyInitialErase:%d,\n\toveride_tty_modes:%d,\n\tXTTYMODE_erase:%d\n", 3863d522f475Smrg initial_erase, 3864d522f475Smrg setInitialErase ? "YES" : "NO", 3865d522f475Smrg resource.ptyInitialErase, 3866d522f475Smrg override_tty_modes, 3867d522f475Smrg ttymodelist[XTTYMODE_erase].set)); 3868d522f475Smrg if (setInitialErase) { 3869d522f475Smrg#if OPT_TRACE 3870d522f475Smrg int old_erase; 3871d522f475Smrg#endif 3872d522f475Smrg#ifdef TERMIO_STRUCT 3873d522f475Smrg if (ttyGetAttr(ttyfd, &tio) == -1) 3874d522f475Smrg tio = d_tio; 3875d522f475Smrg#if OPT_TRACE 3876d522f475Smrg old_erase = tio.c_cc[VERASE]; 3877d522f475Smrg#endif 3878d522f475Smrg tio.c_cc[VERASE] = initial_erase; 387920d2c4d2Smrg TRACE_RC(rc, ttySetAttr(ttyfd, &tio)); 3880d522f475Smrg#else /* !TERMIO_STRUCT */ 3881d522f475Smrg if (ioctl(ttyfd, TIOCGETP, (char *) &sg) == -1) 3882d522f475Smrg sg = d_sg; 3883d522f475Smrg#if OPT_TRACE 3884d522f475Smrg old_erase = sg.sg_erase; 3885d522f475Smrg#endif 3886d522f475Smrg sg.sg_erase = initial_erase; 3887d522f475Smrg rc = ioctl(ttyfd, TIOCSETP, (char *) &sg); 3888d522f475Smrg#endif /* TERMIO_STRUCT */ 3889d522f475Smrg TRACE(("%s setting erase to %d (was %d)\n", 3890d522f475Smrg rc ? "FAIL" : "OK", initial_erase, old_erase)); 3891d522f475Smrg } 3892d522f475Smrg#endif 3893d522f475Smrg 3894d522f475Smrg xtermCopyEnv(environ); 3895d522f475Smrg 3896d522f475Smrg xtermSetenv("TERM", TermName); 3897d522f475Smrg if (!TermName) 389820d2c4d2Smrg *get_tcap_buffer(xw) = 0; 3899d522f475Smrg 3900d522f475Smrg sprintf(buf, "%lu", 3901d522f475Smrg ((unsigned long) XtWindow(SHELL_OF(CURRENT_EMU())))); 3902d522f475Smrg xtermSetenv("WINDOWID", buf); 3903d522f475Smrg 3904d522f475Smrg /* put the display into the environment of the shell */ 3905d522f475Smrg xtermSetenv("DISPLAY", XDisplayString(screen->display)); 3906d522f475Smrg 3907d522f475Smrg xtermSetenv("XTERM_VERSION", xtermVersion()); 3908d522f475Smrg xtermSetenv("XTERM_LOCALE", xtermEnvLocale()); 3909d522f475Smrg 3910d522f475Smrg signal(SIGTERM, SIG_DFL); 3911d522f475Smrg 3912d522f475Smrg /* this is the time to go and set up stdin, out, and err 3913d522f475Smrg */ 3914d522f475Smrg { 3915d522f475Smrg#if defined(CRAY) && (OSMAJORVERSION >= 6) 3916d522f475Smrg close_fd(ttyfd); 3917d522f475Smrg 391820d2c4d2Smrg IGNORE_RC(close(0)); 3919d522f475Smrg 3920d522f475Smrg if (open("/dev/tty", O_RDWR)) { 3921d522f475Smrg SysError(ERROR_OPDEVTTY); 3922d522f475Smrg } 392320d2c4d2Smrg IGNORE_RC(close(1)); 392420d2c4d2Smrg IGNORE_RC(close(2)); 3925d522f475Smrg dup(0); 3926d522f475Smrg dup(0); 3927d522f475Smrg#else 3928d522f475Smrg /* dup the tty */ 3929d522f475Smrg for (i = 0; i <= 2; i++) 3930d522f475Smrg if (i != ttyfd) { 393120d2c4d2Smrg IGNORE_RC(close(i)); 393220d2c4d2Smrg IGNORE_RC(dup(ttyfd)); 3933d522f475Smrg } 3934d522f475Smrg#ifndef ATT 3935d522f475Smrg /* and close the tty */ 3936d522f475Smrg if (ttyfd > 2) 3937d522f475Smrg close_fd(ttyfd); 3938d522f475Smrg#endif 3939d522f475Smrg#endif /* CRAY */ 3940d522f475Smrg } 3941d522f475Smrg 3942d522f475Smrg#if !defined(USE_SYSV_PGRP) 3943d522f475Smrg#ifdef TIOCSCTTY 3944d522f475Smrg setsid(); 3945d522f475Smrg ioctl(0, TIOCSCTTY, 0); 3946d522f475Smrg#endif 3947d522f475Smrg ioctl(0, TIOCSPGRP, (char *) &pgrp); 3948d522f475Smrg setpgrp(0, 0); 3949d522f475Smrg close(open(ttydev, O_WRONLY)); 3950d522f475Smrg setpgrp(0, pgrp); 3951d522f475Smrg#if defined(__QNX__) 3952d522f475Smrg tcsetpgrp(0, pgrp /*setsid() */ ); 3953d522f475Smrg#endif 3954d522f475Smrg#endif /* !USE_SYSV_PGRP */ 3955d522f475Smrg 3956d522f475Smrg#ifdef Lynx 3957d522f475Smrg { 3958d522f475Smrg TERMIO_STRUCT t; 3959d522f475Smrg if (ttyGetAttr(0, &t) >= 0) { 3960d522f475Smrg /* this gets lost somewhere on our way... */ 3961d522f475Smrg t.c_oflag |= OPOST; 3962d522f475Smrg ttySetAttr(0, &t); 3963d522f475Smrg } 3964d522f475Smrg } 3965d522f475Smrg#endif 3966d522f475Smrg 3967d522f475Smrg#ifdef HAVE_UTMP 3968d522f475Smrg pw = getpwuid(screen->uid); 3969d522f475Smrg login_name = NULL; 3970d522f475Smrg if (pw && pw->pw_name) { 3971d522f475Smrg#ifdef HAVE_GETLOGIN 3972d522f475Smrg /* 3973d522f475Smrg * If the value from getlogin() differs from the value we 3974d522f475Smrg * get by looking in the password file, check if it does 3975d522f475Smrg * correspond to the same uid. If so, allow that as an 3976d522f475Smrg * alias for the uid. 3977d522f475Smrg * 3978d522f475Smrg * Of course getlogin() will fail if we're started from 3979d522f475Smrg * a window-manager, since there's no controlling terminal 3980d522f475Smrg * to fuss with. In that case, try to get something useful 3981d522f475Smrg * from the user's $LOGNAME or $USER environment variables. 3982d522f475Smrg */ 3983d522f475Smrg if (((login_name = getlogin()) != NULL 3984d522f475Smrg || (login_name = x_getenv("LOGNAME")) != NULL 3985d522f475Smrg || (login_name = x_getenv("USER")) != NULL) 3986d522f475Smrg && strcmp(login_name, pw->pw_name)) { 3987d522f475Smrg struct passwd *pw2 = getpwnam(login_name); 3988d522f475Smrg if (pw2 != 0) { 3989d522f475Smrg uid_t uid2 = pw2->pw_uid; 3990d522f475Smrg pw = getpwuid(screen->uid); 3991d522f475Smrg if ((uid_t) pw->pw_uid != uid2) 3992d522f475Smrg login_name = NULL; 3993d522f475Smrg } else { 3994d522f475Smrg pw = getpwuid(screen->uid); 3995d522f475Smrg } 3996d522f475Smrg } 3997d522f475Smrg#endif 3998d522f475Smrg if (login_name == NULL) 3999d522f475Smrg login_name = pw->pw_name; 4000d522f475Smrg if (login_name != NULL) 4001d522f475Smrg login_name = x_strdup(login_name); 4002d522f475Smrg } 4003d522f475Smrg if (login_name != NULL) { 4004d522f475Smrg xtermSetenv("LOGNAME", login_name); /* for POSIX */ 4005d522f475Smrg } 4006d522f475Smrg#ifndef USE_UTEMPTER 4007d522f475Smrg#ifdef USE_UTMP_SETGID 4008d522f475Smrg setEffectiveGroup(save_egid); 4009d522f475Smrg TRACE_IDS; 4010d522f475Smrg#endif 4011d522f475Smrg#ifdef USE_SYSV_UTMP 4012d522f475Smrg /* Set up our utmp entry now. We need to do it here 4013d522f475Smrg * for the following reasons: 4014d522f475Smrg * - It needs to have our correct process id (for 4015d522f475Smrg * login). 4016d522f475Smrg * - If our parent was to set it after the fork(), 4017d522f475Smrg * it might make it out before we need it. 4018d522f475Smrg * - We need to do it before we go and change our 4019d522f475Smrg * user and group id's. 4020d522f475Smrg */ 4021d522f475Smrg (void) call_setutent(); 4022d522f475Smrg init_utmp(DEAD_PROCESS, &utmp); 4023d522f475Smrg 4024d522f475Smrg /* position to entry in utmp file */ 4025d522f475Smrg /* Test return value: beware of entries left behind: PSz 9 Mar 00 */ 402620d2c4d2Smrg utret = find_utmp(&utmp); 402720d2c4d2Smrg if (utret == 0) { 4028d522f475Smrg (void) call_setutent(); 4029d522f475Smrg init_utmp(USER_PROCESS, &utmp); 403020d2c4d2Smrg utret = find_utmp(&utmp); 403120d2c4d2Smrg if (utret == 0) { 4032d522f475Smrg (void) call_setutent(); 4033d522f475Smrg } 4034d522f475Smrg } 4035d522f475Smrg#if OPT_TRACE 4036d522f475Smrg if (!utret) 4037d522f475Smrg TRACE(("getutid: NULL\n")); 4038d522f475Smrg else 4039d522f475Smrg TRACE(("getutid: pid=%d type=%d user=%s line=%s id=%s\n", 404020d2c4d2Smrg (int) utret->ut_pid, utret->ut_type, utret->ut_user, 4041d522f475Smrg utret->ut_line, utret->ut_id)); 4042d522f475Smrg#endif 4043d522f475Smrg 4044d522f475Smrg /* set up the new entry */ 4045d522f475Smrg utmp.ut_type = USER_PROCESS; 4046d522f475Smrg#ifdef HAVE_UTMP_UT_XSTATUS 4047d522f475Smrg utmp.ut_xstatus = 2; 4048d522f475Smrg#endif 4049d522f475Smrg (void) strncpy(utmp.ut_user, 4050d522f475Smrg (login_name != NULL) ? login_name : "????", 4051d522f475Smrg sizeof(utmp.ut_user)); 4052d522f475Smrg /* why are we copying this string again? (see above) */ 4053d522f475Smrg (void) strncpy(utmp.ut_id, my_utmp_id(ttydev), sizeof(utmp.ut_id)); 4054d522f475Smrg (void) strncpy(utmp.ut_line, 4055d522f475Smrg my_pty_name(ttydev), sizeof(utmp.ut_line)); 4056d522f475Smrg 4057d522f475Smrg#ifdef HAVE_UTMP_UT_HOST 4058d522f475Smrg SetUtmpHost(utmp.ut_host, screen); 4059d522f475Smrg#endif 4060d522f475Smrg#ifdef HAVE_UTMP_UT_SYSLEN 4061d522f475Smrg SetUtmpSysLen(utmp); 4062d522f475Smrg#endif 4063d522f475Smrg 4064d522f475Smrg (void) strncpy(utmp.ut_name, 4065d522f475Smrg (login_name) ? login_name : "????", 4066d522f475Smrg sizeof(utmp.ut_name)); 4067d522f475Smrg 4068d522f475Smrg utmp.ut_pid = getpid(); 4069d522f475Smrg#if defined(HAVE_UTMP_UT_XTIME) 4070d522f475Smrg#if defined(HAVE_UTMP_UT_SESSION) 4071d522f475Smrg utmp.ut_session = getsid(0); 4072d522f475Smrg#endif 4073d522f475Smrg utmp.ut_xtime = time((time_t *) 0); 4074d522f475Smrg utmp.ut_tv.tv_usec = 0; 4075d522f475Smrg#else 4076d522f475Smrg utmp.ut_time = time((time_t *) 0); 4077d522f475Smrg#endif 4078d522f475Smrg 4079d522f475Smrg /* write out the entry */ 4080d522f475Smrg if (!resource.utmpInhibit) { 4081d522f475Smrg errno = 0; 4082d522f475Smrg call_pututline(&utmp); 4083d522f475Smrg TRACE(("pututline: id %s, line %s, pid %ld, errno %d %s\n", 4084d522f475Smrg utmp.ut_id, 4085d522f475Smrg utmp.ut_line, 4086d522f475Smrg (long) utmp.ut_pid, 4087d522f475Smrg errno, (errno != 0) ? strerror(errno) : "")); 4088d522f475Smrg } 4089d522f475Smrg#ifdef WTMP 4090d522f475Smrg#if defined(WTMPX_FILE) && (defined(SVR4) || defined(__SCO__)) 4091d522f475Smrg if (xw->misc.login_shell) 4092d522f475Smrg updwtmpx(WTMPX_FILE, &utmp); 4093d522f475Smrg#elif defined(linux) && defined(__GLIBC__) && (__GLIBC__ >= 2) && !(defined(__powerpc__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)) 4094d522f475Smrg if (xw->misc.login_shell) 4095d522f475Smrg call_updwtmp(etc_wtmp, &utmp); 4096d522f475Smrg#else 4097d522f475Smrg if (xw->misc.login_shell && 4098d522f475Smrg (i = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 4099d522f475Smrg write(i, (char *) &utmp, sizeof(utmp)); 4100d522f475Smrg close(i); 4101d522f475Smrg } 4102d522f475Smrg#endif 4103d522f475Smrg#endif 4104d522f475Smrg /* close the file */ 4105d522f475Smrg (void) call_endutent(); 4106d522f475Smrg 4107d522f475Smrg#else /* USE_SYSV_UTMP */ 4108d522f475Smrg /* We can now get our ttyslot! We can also set the initial 4109d522f475Smrg * utmp entry. 4110d522f475Smrg */ 4111d522f475Smrg tslot = ttyslot(); 4112d522f475Smrg added_utmp_entry = False; 4113d522f475Smrg { 4114d522f475Smrg if (tslot > 0 && pw && !resource.utmpInhibit && 4115d522f475Smrg (i = open(etc_utmp, O_WRONLY)) >= 0) { 4116956cc18dSsnj memset(&utmp, 0, sizeof(utmp)); 4117d522f475Smrg (void) strncpy(utmp.ut_line, 4118d522f475Smrg my_pty_name(ttydev), 4119d522f475Smrg sizeof(utmp.ut_line)); 4120d522f475Smrg (void) strncpy(utmp.ut_name, login_name, 4121d522f475Smrg sizeof(utmp.ut_name)); 4122d522f475Smrg#ifdef HAVE_UTMP_UT_HOST 4123d522f475Smrg SetUtmpHost(utmp.ut_host, screen); 4124d522f475Smrg#endif 4125d522f475Smrg#ifdef HAVE_UTMP_UT_SYSLEN 4126d522f475Smrg SetUtmpSysLen(utmp); 4127d522f475Smrg#endif 4128d522f475Smrg 4129d522f475Smrg utmp.ut_time = time((time_t *) 0); 4130d522f475Smrg lseek(i, (long) (tslot * sizeof(utmp)), 0); 4131d522f475Smrg write(i, (char *) &utmp, sizeof(utmp)); 4132d522f475Smrg close(i); 4133d522f475Smrg added_utmp_entry = True; 4134d522f475Smrg#if defined(WTMP) 4135d522f475Smrg if (xw->misc.login_shell && 4136d522f475Smrg (i = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 4137d522f475Smrg int status; 4138d522f475Smrg status = write(i, (char *) &utmp, sizeof(utmp)); 4139d522f475Smrg status = close(i); 4140d522f475Smrg } 4141d522f475Smrg#elif defined(MNX_LASTLOG) 4142d522f475Smrg if (xw->misc.login_shell && 4143d522f475Smrg (i = open(_U_LASTLOG, O_WRONLY)) >= 0) { 4144d522f475Smrg lseek(i, (long) (screen->uid * 4145d522f475Smrg sizeof(utmp)), 0); 4146d522f475Smrg write(i, (char *) &utmp, sizeof(utmp)); 4147d522f475Smrg close(i); 4148d522f475Smrg } 4149d522f475Smrg#endif /* WTMP or MNX_LASTLOG */ 4150d522f475Smrg } else 4151d522f475Smrg tslot = -tslot; 4152d522f475Smrg } 4153d522f475Smrg 4154d522f475Smrg /* Let's pass our ttyslot to our parent so that it can 4155d522f475Smrg * clean up after us. 4156d522f475Smrg */ 4157d522f475Smrg#if OPT_PTY_HANDSHAKE 4158d522f475Smrg if (resource.ptyHandshake) { 4159d522f475Smrg handshake.tty_slot = tslot; 4160d522f475Smrg } 4161d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4162d522f475Smrg#endif /* USE_SYSV_UTMP */ 4163d522f475Smrg 4164d522f475Smrg#ifdef USE_LASTLOGX 4165d522f475Smrg if (xw->misc.login_shell) { 4166956cc18dSsnj memset(&lastlogx, 0, sizeof(lastlogx)); 4167d522f475Smrg (void) strncpy(lastlogx.ll_line, 4168d522f475Smrg my_pty_name(ttydev), 4169d522f475Smrg sizeof(lastlogx.ll_line)); 4170d522f475Smrg X_GETTIMEOFDAY(&lastlogx.ll_tv); 4171d522f475Smrg SetUtmpHost(lastlogx.ll_host, screen); 4172d522f475Smrg updlastlogx(_PATH_LASTLOGX, screen->uid, &lastlogx); 4173d522f475Smrg } 4174d522f475Smrg#endif 4175d522f475Smrg 4176d522f475Smrg#ifdef USE_LASTLOG 4177d522f475Smrg if (xw->misc.login_shell && 4178d522f475Smrg (i = open(etc_lastlog, O_WRONLY)) >= 0) { 4179d522f475Smrg size_t size = sizeof(struct lastlog); 4180d522f475Smrg off_t offset = (screen->uid * size); 4181d522f475Smrg 4182956cc18dSsnj memset(&lastlog, 0, size); 4183d522f475Smrg (void) strncpy(lastlog.ll_line, 4184d522f475Smrg my_pty_name(ttydev), 4185d522f475Smrg sizeof(lastlog.ll_line)); 4186d522f475Smrg SetUtmpHost(lastlog.ll_host, screen); 4187d522f475Smrg lastlog.ll_time = time((time_t *) 0); 4188d522f475Smrg if (lseek(i, offset, 0) != (off_t) (-1)) { 4189d522f475Smrg write(i, (char *) &lastlog, size); 4190d522f475Smrg } 4191d522f475Smrg close(i); 4192d522f475Smrg } 4193d522f475Smrg#endif /* USE_LASTLOG */ 4194d522f475Smrg 4195d522f475Smrg#if defined(USE_UTMP_SETGID) 4196d522f475Smrg disableSetGid(); 4197d522f475Smrg TRACE_IDS; 4198d522f475Smrg#endif 4199d522f475Smrg 4200d522f475Smrg#if OPT_PTY_HANDSHAKE 4201d522f475Smrg /* Let our parent know that we set up our utmp entry 4202d522f475Smrg * so that it can clean up after us. 4203d522f475Smrg */ 4204d522f475Smrg if (resource.ptyHandshake) { 4205d522f475Smrg handshake.status = UTMP_ADDED; 4206d522f475Smrg handshake.error = 0; 4207d522f475Smrg strcpy(handshake.buffer, ttydev); 4208d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 420920d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], (char *) &handshake, sizeof(handshake))); 4210d522f475Smrg } 4211d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4212d522f475Smrg#endif /* USE_UTEMPTER */ 4213d522f475Smrg#endif /* HAVE_UTMP */ 4214d522f475Smrg 421520d2c4d2Smrg IGNORE_RC(setgid(screen->gid)); 4216d522f475Smrg TRACE_IDS; 4217d522f475Smrg#ifdef HAS_BSD_GROUPS 4218d522f475Smrg if (geteuid() == 0 && pw) { 4219d522f475Smrg if (initgroups(login_name, pw->pw_gid)) { 4220d522f475Smrg perror("initgroups failed"); 4221d522f475Smrg SysError(ERROR_INIGROUPS); 4222d522f475Smrg } 4223d522f475Smrg } 4224d522f475Smrg#endif 4225d522f475Smrg if (setuid(screen->uid)) { 4226d522f475Smrg SysError(ERROR_SETUID); 4227d522f475Smrg } 4228d522f475Smrg TRACE_IDS; 4229d522f475Smrg#if OPT_PTY_HANDSHAKE 4230d522f475Smrg if (resource.ptyHandshake) { 4231d522f475Smrg /* mark the pipes as close on exec */ 4232d522f475Smrg fcntl(cp_pipe[1], F_SETFD, 1); 4233d522f475Smrg fcntl(pc_pipe[0], F_SETFD, 1); 4234d522f475Smrg 4235d522f475Smrg /* We are at the point where we are going to 4236d522f475Smrg * exec our shell (or whatever). Let our parent 4237d522f475Smrg * know we arrived safely. 4238d522f475Smrg */ 4239d522f475Smrg handshake.status = PTY_GOOD; 4240d522f475Smrg handshake.error = 0; 4241d522f475Smrg (void) strcpy(handshake.buffer, ttydev); 4242d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 424320d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], 424420d2c4d2Smrg (const char *) &handshake, 424520d2c4d2Smrg sizeof(handshake))); 4246d522f475Smrg 4247d522f475Smrg if (resource.wait_for_map) { 424820d2c4d2Smrg i = (int) read(pc_pipe[0], (char *) &handshake, 424920d2c4d2Smrg sizeof(handshake)); 4250d522f475Smrg if (i != sizeof(handshake) || 4251d522f475Smrg handshake.status != PTY_EXEC) { 4252d522f475Smrg /* some very bad problem occurred */ 4253d522f475Smrg exit(ERROR_PTY_EXEC); 4254d522f475Smrg } 4255d522f475Smrg if (handshake.rows > 0 && handshake.cols > 0) { 4256d522f475Smrg TRACE(("handshake ttysize: %dx%d\n", 4257d522f475Smrg handshake.rows, handshake.cols)); 4258d522f475Smrg set_max_row(screen, handshake.rows); 4259d522f475Smrg set_max_col(screen, handshake.cols); 4260d522f475Smrg#ifdef TTYSIZE_STRUCT 4261d522f475Smrg got_handshake_size = True; 426220d2c4d2Smrg TTYSIZE_ROWS(ts) = (ttySize_t) MaxRows(screen); 426320d2c4d2Smrg TTYSIZE_COLS(ts) = (ttySize_t) MaxCols(screen); 4264d522f475Smrg#if defined(USE_STRUCT_WINSIZE) 426520d2c4d2Smrg ts.ws_xpixel = (ttySize_t) FullWidth(screen); 426620d2c4d2Smrg ts.ws_ypixel = (ttySize_t) FullHeight(screen); 4267d522f475Smrg#endif 4268d522f475Smrg#endif /* TTYSIZE_STRUCT */ 4269d522f475Smrg } 4270d522f475Smrg } 4271d522f475Smrg } 4272d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4273d522f475Smrg 4274d522f475Smrg#ifdef USE_SYSV_ENVVARS 4275d522f475Smrg { 4276d522f475Smrg char numbuf[12]; 4277d522f475Smrg sprintf(numbuf, "%d", MaxCols(screen)); 4278d522f475Smrg xtermSetenv("COLUMNS", numbuf); 4279d522f475Smrg sprintf(numbuf, "%d", MaxRows(screen)); 4280d522f475Smrg xtermSetenv("LINES", numbuf); 4281d522f475Smrg } 4282d522f475Smrg#ifdef HAVE_UTMP 4283d522f475Smrg if (pw) { /* SVR4 doesn't provide these */ 4284d522f475Smrg if (!x_getenv("HOME")) 4285d522f475Smrg xtermSetenv("HOME", pw->pw_dir); 4286d522f475Smrg if (!x_getenv("SHELL")) 4287d522f475Smrg xtermSetenv("SHELL", pw->pw_shell); 4288d522f475Smrg } 4289d522f475Smrg#endif /* HAVE_UTMP */ 4290d522f475Smrg#ifdef OWN_TERMINFO_DIR 4291d522f475Smrg xtermSetenv("TERMINFO", OWN_TERMINFO_DIR); 4292d522f475Smrg#endif 4293d522f475Smrg#else /* USE_SYSV_ENVVARS */ 429420d2c4d2Smrg if (*(newtc = get_tcap_buffer(xw)) != '\0') { 429520d2c4d2Smrg resize_termcap(xw); 429620d2c4d2Smrg if (xw->misc.titeInhibit && !xw->misc.tiXtraScroll) { 429720d2c4d2Smrg remove_termcap_entry(newtc, "ti="); 429820d2c4d2Smrg remove_termcap_entry(newtc, "te="); 429920d2c4d2Smrg } 430020d2c4d2Smrg /* 430120d2c4d2Smrg * work around broken termcap entries */ 430220d2c4d2Smrg if (resource.useInsertMode) { 430320d2c4d2Smrg remove_termcap_entry(newtc, "ic="); 430420d2c4d2Smrg /* don't get duplicates */ 430520d2c4d2Smrg remove_termcap_entry(newtc, "im="); 430620d2c4d2Smrg remove_termcap_entry(newtc, "ei="); 430720d2c4d2Smrg remove_termcap_entry(newtc, "mi"); 430820d2c4d2Smrg if (*newtc) 430920d2c4d2Smrg strcat(newtc, ":im=\\E[4h:ei=\\E[4l:mi:"); 431020d2c4d2Smrg } 431120d2c4d2Smrg if (*newtc) { 4312d522f475Smrg#if OPT_INITIAL_ERASE 431320d2c4d2Smrg unsigned len; 431420d2c4d2Smrg remove_termcap_entry(newtc, TERMCAP_ERASE "="); 431520d2c4d2Smrg len = (unsigned) strlen(newtc); 431620d2c4d2Smrg if (len != 0 && newtc[len - 1] == ':') 431720d2c4d2Smrg len--; 431820d2c4d2Smrg sprintf(newtc + len, ":%s=\\%03o:", 431920d2c4d2Smrg TERMCAP_ERASE, 432020d2c4d2Smrg CharOf(initial_erase)); 432120d2c4d2Smrg#endif 432220d2c4d2Smrg xtermSetenv("TERMCAP", newtc); 432320d2c4d2Smrg } 4324d522f475Smrg } 4325d522f475Smrg#endif /* USE_SYSV_ENVVARS */ 4326d522f475Smrg 4327d522f475Smrg#if OPT_PTY_HANDSHAKE 4328d522f475Smrg /* 4329d522f475Smrg * Need to reset after all the ioctl bashing we did above. 4330d522f475Smrg * 4331d522f475Smrg * If we expect the waitForMap logic to set the handshake-size, 4332d522f475Smrg * use that to prevent races. 4333d522f475Smrg */ 4334d522f475Smrg if (resource.ptyHandshake 4335d522f475Smrg && resource.ptySttySize 4336d522f475Smrg && (got_handshake_size || !resource.wait_for_map0)) { 4337d522f475Smrg#ifdef TTYSIZE_STRUCT 433820d2c4d2Smrg TRACE_RC(i, SET_TTYSIZE(0, ts)); 4339d522f475Smrg TRACE(("ptyHandshake SET_TTYSIZE %dx%d return %d\n", 4340d522f475Smrg TTYSIZE_ROWS(ts), 4341d522f475Smrg TTYSIZE_COLS(ts), i)); 4342d522f475Smrg#endif /* TTYSIZE_STRUCT */ 4343d522f475Smrg } 4344d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4345d522f475Smrg signal(SIGHUP, SIG_DFL); 4346d522f475Smrg 4347d522f475Smrg if ((ptr = explicit_shname) == NULL) { 4348d522f475Smrg if (((ptr = x_getenv("SHELL")) == NULL) && 4349d522f475Smrg ((pw == NULL && (pw = getpwuid(screen->uid)) == NULL) || 4350d522f475Smrg *(ptr = pw->pw_shell) == 0)) { 435120d2c4d2Smrg ptr = x_strdup("/bin/sh"); 4352d522f475Smrg } 4353d522f475Smrg } else { 4354d522f475Smrg xtermSetenv("SHELL", explicit_shname); 4355d522f475Smrg } 4356d522f475Smrg xtermSetenv("XTERM_SHELL", ptr); 4357d522f475Smrg 4358d522f475Smrg shname = x_basename(ptr); 4359d522f475Smrg TRACE(("shell path '%s' leaf '%s'\n", ptr, shname)); 4360d522f475Smrg 4361d522f475Smrg#if OPT_LUIT_PROG 4362d522f475Smrg /* 4363d522f475Smrg * Use two copies of command_to_exec, in case luit is not actually 4364d522f475Smrg * there, or refuses to run. In that case we will fall-through to 4365d522f475Smrg * to command that the user gave anyway. 4366d522f475Smrg */ 43672eaa94a1Schristos if (command_to_exec_with_luit && command_to_exec) { 4368d522f475Smrg xtermSetenv("XTERM_SHELL", 4369d522f475Smrg xtermFindShell(*command_to_exec_with_luit, False)); 4370d522f475Smrg TRACE(("spawning command \"%s\"\n", *command_to_exec_with_luit)); 4371d522f475Smrg execvp(*command_to_exec_with_luit, command_to_exec_with_luit); 4372d522f475Smrg /* print error message on screen */ 4373d522f475Smrg fprintf(stderr, "%s: Can't execvp %s: %s\n", 4374d522f475Smrg ProgramName, *command_to_exec_with_luit, strerror(errno)); 4375d522f475Smrg fprintf(stderr, "%s: cannot support your locale.\n", 4376d522f475Smrg ProgramName); 4377d522f475Smrg } 4378d522f475Smrg#endif 4379d522f475Smrg if (command_to_exec) { 4380d522f475Smrg xtermSetenv("XTERM_SHELL", 4381d522f475Smrg xtermFindShell(*command_to_exec, False)); 4382d522f475Smrg TRACE(("spawning command \"%s\"\n", *command_to_exec)); 4383d522f475Smrg execvp(*command_to_exec, command_to_exec); 4384d522f475Smrg if (command_to_exec[1] == 0) 4385d522f475Smrg execlp(ptr, shname, "-c", command_to_exec[0], (void *) 0); 4386d522f475Smrg /* print error message on screen */ 4387d522f475Smrg fprintf(stderr, "%s: Can't execvp %s: %s\n", 4388d522f475Smrg ProgramName, *command_to_exec, strerror(errno)); 4389d522f475Smrg } 4390d522f475Smrg#ifdef USE_SYSV_SIGHUP 4391d522f475Smrg /* fix pts sh hanging around */ 4392d522f475Smrg signal(SIGHUP, SIG_DFL); 4393d522f475Smrg#endif 4394d522f475Smrg 4395d522f475Smrg shname_minus = CastMallocN(char, strlen(shname) + 2); 4396d522f475Smrg (void) strcpy(shname_minus, "-"); 4397d522f475Smrg (void) strcat(shname_minus, shname); 4398d522f475Smrg#ifndef TERMIO_STRUCT 4399d522f475Smrg ldisc = XStrCmp("csh", shname + strlen(shname) - 3) == 0 ? 4400d522f475Smrg NTTYDISC : 0; 4401d522f475Smrg ioctl(0, TIOCSETD, (char *) &ldisc); 4402d522f475Smrg#endif /* !TERMIO_STRUCT */ 4403d522f475Smrg 4404d522f475Smrg#ifdef USE_LOGIN_DASH_P 4405d522f475Smrg if (xw->misc.login_shell && pw && added_utmp_entry) 4406d522f475Smrg execl(bin_login, "login", "-p", "-f", login_name, (void *) 0); 4407d522f475Smrg#endif 44082eaa94a1Schristos 44092eaa94a1Schristos#if OPT_LUIT_PROG 44102eaa94a1Schristos if (command_to_exec_with_luit) { 44112eaa94a1Schristos if (xw->misc.login_shell) { 44122eaa94a1Schristos int u; 44132eaa94a1Schristos u = (term->misc.use_encoding ? 2 : 0); 441420d2c4d2Smrg command_to_exec_with_luit[u + 1] = x_strdup("-argv0"); 44152eaa94a1Schristos command_to_exec_with_luit[u + 2] = shname_minus; 44162eaa94a1Schristos command_to_exec_with_luit[u + 3] = NULL; 44172eaa94a1Schristos } 44182eaa94a1Schristos execvp(*command_to_exec_with_luit, command_to_exec_with_luit); 44192eaa94a1Schristos /* Exec failed. */ 44202eaa94a1Schristos fprintf(stderr, "%s: Can't execvp %s: %s\n", ProgramName, 44212eaa94a1Schristos *command_to_exec_with_luit, strerror(errno)); 44222eaa94a1Schristos } 44232eaa94a1Schristos#endif 4424d522f475Smrg execlp(ptr, 4425d522f475Smrg (xw->misc.login_shell ? shname_minus : shname), 4426d522f475Smrg (void *) 0); 4427d522f475Smrg 4428d522f475Smrg /* Exec failed. */ 4429d522f475Smrg fprintf(stderr, "%s: Could not exec %s: %s\n", ProgramName, 4430d522f475Smrg ptr, strerror(errno)); 443120d2c4d2Smrg IGNORE_RC(sleep(5)); 4432d522f475Smrg exit(ERROR_EXEC); 4433d522f475Smrg } 4434d522f475Smrg /* end if in child after fork */ 4435d522f475Smrg#if OPT_PTY_HANDSHAKE 4436d522f475Smrg if (resource.ptyHandshake) { 4437d522f475Smrg /* Parent process. Let's handle handshaked requests to our 4438d522f475Smrg * child process. 4439d522f475Smrg */ 4440d522f475Smrg 4441d522f475Smrg /* close childs's sides of the pipes */ 4442d522f475Smrg close(cp_pipe[1]); 4443d522f475Smrg close(pc_pipe[0]); 4444d522f475Smrg 4445d522f475Smrg for (done = 0; !done;) { 4446d522f475Smrg if (read(cp_pipe[0], 4447d522f475Smrg (char *) &handshake, 4448d522f475Smrg sizeof(handshake)) <= 0) { 4449d522f475Smrg /* Our child is done talking to us. If it terminated 4450d522f475Smrg * due to an error, we will catch the death of child 4451d522f475Smrg * and clean up. 4452d522f475Smrg */ 4453d522f475Smrg break; 4454d522f475Smrg } 4455d522f475Smrg 4456d522f475Smrg TRACE_HANDSHAKE("read", &handshake); 4457d522f475Smrg switch (handshake.status) { 4458d522f475Smrg case PTY_GOOD: 4459d522f475Smrg /* Success! Let's free up resources and 4460d522f475Smrg * continue. 4461d522f475Smrg */ 4462d522f475Smrg done = 1; 4463d522f475Smrg break; 4464d522f475Smrg 4465d522f475Smrg case PTY_BAD: 4466d522f475Smrg /* The open of the pty failed! Let's get 4467d522f475Smrg * another one. 4468d522f475Smrg */ 446920d2c4d2Smrg IGNORE_RC(close(screen->respond)); 4470d522f475Smrg if (get_pty(&screen->respond, XDisplayString(screen->display))) { 4471d522f475Smrg /* no more ptys! */ 4472d522f475Smrg fprintf(stderr, 4473d522f475Smrg "%s: child process can find no available ptys: %s\n", 4474d522f475Smrg ProgramName, strerror(errno)); 4475d522f475Smrg handshake.status = PTY_NOMORE; 4476d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 447720d2c4d2Smrg IGNORE_RC(write(pc_pipe[1], 447820d2c4d2Smrg (const char *) &handshake, 447920d2c4d2Smrg sizeof(handshake))); 4480d522f475Smrg exit(ERROR_PTYS); 4481d522f475Smrg } 4482d522f475Smrg handshake.status = PTY_NEW; 4483d522f475Smrg (void) strcpy(handshake.buffer, ttydev); 4484d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 448520d2c4d2Smrg IGNORE_RC(write(pc_pipe[1], 448620d2c4d2Smrg (const char *) &handshake, 448720d2c4d2Smrg sizeof(handshake))); 4488d522f475Smrg break; 4489d522f475Smrg 4490d522f475Smrg case PTY_FATALERROR: 4491d522f475Smrg errno = handshake.error; 4492d522f475Smrg close(cp_pipe[0]); 4493d522f475Smrg close(pc_pipe[1]); 4494d522f475Smrg SysError(handshake.fatal_error); 4495d522f475Smrg /*NOTREACHED */ 4496d522f475Smrg 4497d522f475Smrg case UTMP_ADDED: 4498d522f475Smrg /* The utmp entry was set by our slave. Remember 4499d522f475Smrg * this so that we can reset it later. 4500d522f475Smrg */ 4501d522f475Smrg added_utmp_entry = True; 4502d522f475Smrg#ifndef USE_SYSV_UTMP 4503d522f475Smrg tslot = handshake.tty_slot; 4504d522f475Smrg#endif /* USE_SYSV_UTMP */ 4505d522f475Smrg free(ttydev); 4506d522f475Smrg ttydev = x_strdup(handshake.buffer); 4507d522f475Smrg break; 4508d522f475Smrg case PTY_NEW: 4509d522f475Smrg case PTY_NOMORE: 4510d522f475Smrg case UTMP_TTYSLOT: 4511d522f475Smrg case PTY_EXEC: 4512d522f475Smrg default: 4513d522f475Smrg fprintf(stderr, "%s: unexpected handshake status %d\n", 4514d522f475Smrg ProgramName, 4515d522f475Smrg (int) handshake.status); 4516d522f475Smrg } 4517d522f475Smrg } 4518d522f475Smrg /* close our sides of the pipes */ 4519d522f475Smrg if (!resource.wait_for_map) { 4520d522f475Smrg close(cp_pipe[0]); 4521d522f475Smrg close(pc_pipe[1]); 4522d522f475Smrg } 4523d522f475Smrg } 4524d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4525d522f475Smrg } 4526d522f475Smrg 4527d522f475Smrg /* end if no slave */ 4528d522f475Smrg /* 4529d522f475Smrg * still in parent (xterm process) 4530d522f475Smrg */ 4531d522f475Smrg#ifdef USE_SYSV_SIGHUP 4532d522f475Smrg /* hung sh problem? */ 4533d522f475Smrg signal(SIGHUP, SIG_DFL); 4534d522f475Smrg#else 4535d522f475Smrg signal(SIGHUP, SIG_IGN); 4536d522f475Smrg#endif 4537d522f475Smrg 4538d522f475Smrg/* 4539d522f475Smrg * Unfortunately, System V seems to have trouble divorcing the child process 4540d522f475Smrg * from the process group of xterm. This is a problem because hitting the 4541d522f475Smrg * INTR or QUIT characters on the keyboard will cause xterm to go away if we 4542d522f475Smrg * don't ignore the signals. This is annoying. 4543d522f475Smrg */ 4544d522f475Smrg 4545d522f475Smrg#if defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP) 4546d522f475Smrg signal(SIGINT, SIG_IGN); 4547d522f475Smrg 4548d522f475Smrg#ifndef SYSV 4549d522f475Smrg /* hung shell problem */ 4550d522f475Smrg signal(SIGQUIT, SIG_IGN); 4551d522f475Smrg#endif 4552d522f475Smrg signal(SIGTERM, SIG_IGN); 4553d522f475Smrg#elif defined(SYSV) || defined(__osf__) 4554d522f475Smrg /* if we were spawned by a jobcontrol smart shell (like ksh or csh), 4555d522f475Smrg * then our pgrp and pid will be the same. If we were spawned by 4556d522f475Smrg * a jobcontrol dumb shell (like /bin/sh), then we will be in our 4557d522f475Smrg * parent's pgrp, and we must ignore keyboard signals, or we will 4558d522f475Smrg * tank on everything. 4559d522f475Smrg */ 4560d522f475Smrg if (getpid() == getpgrp()) { 4561d522f475Smrg (void) signal(SIGINT, Exit); 4562d522f475Smrg (void) signal(SIGQUIT, Exit); 4563d522f475Smrg (void) signal(SIGTERM, Exit); 4564d522f475Smrg } else { 4565d522f475Smrg (void) signal(SIGINT, SIG_IGN); 4566d522f475Smrg (void) signal(SIGQUIT, SIG_IGN); 4567d522f475Smrg (void) signal(SIGTERM, SIG_IGN); 4568d522f475Smrg } 4569d522f475Smrg (void) signal(SIGPIPE, Exit); 4570d522f475Smrg#else /* SYSV */ 4571d522f475Smrg signal(SIGINT, Exit); 4572d522f475Smrg signal(SIGQUIT, Exit); 4573d522f475Smrg signal(SIGTERM, Exit); 4574d522f475Smrg signal(SIGPIPE, Exit); 4575d522f475Smrg#endif /* USE_SYSV_SIGNALS and not SIGTSTP */ 4576d522f475Smrg 4577d522f475Smrg return 0; 4578d522f475Smrg} /* end spawnXTerm */ 4579d522f475Smrg 4580d522f475SmrgSIGNAL_T 4581d522f475SmrgExit(int n) 4582d522f475Smrg{ 458320d2c4d2Smrg XtermWidget xw = term; 458420d2c4d2Smrg TScreen *screen = TScreenOf(xw); 4585d522f475Smrg 4586d522f475Smrg#ifdef USE_UTEMPTER 4587d522f475Smrg if (!resource.utmpInhibit && added_utmp_entry) 4588d522f475Smrg removeFromUtmp(); 4589d522f475Smrg#elif defined(HAVE_UTMP) 4590d522f475Smrg#ifdef USE_SYSV_UTMP 4591d522f475Smrg struct UTMP_STR utmp; 4592d522f475Smrg struct UTMP_STR *utptr; 4593d522f475Smrg 4594d522f475Smrg /* don't do this more than once */ 4595d522f475Smrg if (xterm_exiting) 4596d522f475Smrg SIGNAL_RETURN; 4597d522f475Smrg xterm_exiting = True; 4598d522f475Smrg 4599d522f475Smrg#ifdef PUCC_PTYD 4600d522f475Smrg closepty(ttydev, ptydev, (resource.utmpInhibit ? OPTY_NOP : OPTY_LOGIN), screen->respond); 4601d522f475Smrg#endif /* PUCC_PTYD */ 4602d522f475Smrg 4603d522f475Smrg /* cleanup the utmp entry we forged earlier */ 4604d522f475Smrg if (!resource.utmpInhibit 4605d522f475Smrg#if OPT_PTY_HANDSHAKE /* without handshake, no way to know */ 4606d522f475Smrg && (resource.ptyHandshake && added_utmp_entry) 4607d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4608d522f475Smrg ) { 4609d522f475Smrg#if defined(USE_UTMP_SETGID) 4610d522f475Smrg setEffectiveGroup(save_egid); 4611d522f475Smrg TRACE_IDS; 4612d522f475Smrg#endif 4613d522f475Smrg init_utmp(USER_PROCESS, &utmp); 4614d522f475Smrg (void) call_setutent(); 4615d522f475Smrg 4616d522f475Smrg /* 4617d522f475Smrg * We could use getutline() if we didn't support old systems. 4618d522f475Smrg */ 4619d522f475Smrg while ((utptr = find_utmp(&utmp)) != 0) { 4620d522f475Smrg if (utptr->ut_pid == screen->pid) { 4621d522f475Smrg utptr->ut_type = DEAD_PROCESS; 4622d522f475Smrg#if defined(HAVE_UTMP_UT_XTIME) 4623d522f475Smrg#if defined(HAVE_UTMP_UT_SESSION) 4624d522f475Smrg utptr->ut_session = getsid(0); 4625d522f475Smrg#endif 4626d522f475Smrg utptr->ut_xtime = time((time_t *) 0); 4627d522f475Smrg utptr->ut_tv.tv_usec = 0; 4628d522f475Smrg#else 4629d522f475Smrg *utptr->ut_user = 0; 4630d522f475Smrg utptr->ut_time = time((time_t *) 0); 4631d522f475Smrg#endif 4632d522f475Smrg (void) call_pututline(utptr); 4633d522f475Smrg#ifdef WTMP 4634d522f475Smrg#if defined(WTMPX_FILE) && (defined(SVR4) || defined(__SCO__)) 463520d2c4d2Smrg if (xw->misc.login_shell) 4636d522f475Smrg updwtmpx(WTMPX_FILE, utptr); 4637d522f475Smrg#elif defined(linux) && defined(__GLIBC__) && (__GLIBC__ >= 2) && !(defined(__powerpc__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)) 4638d522f475Smrg strncpy(utmp.ut_line, utptr->ut_line, sizeof(utmp.ut_line)); 463920d2c4d2Smrg if (xw->misc.login_shell) 4640d522f475Smrg call_updwtmp(etc_wtmp, utptr); 4641d522f475Smrg#else 4642d522f475Smrg /* set wtmp entry if wtmp file exists */ 464320d2c4d2Smrg if (xw->misc.login_shell) { 4644d522f475Smrg int fd; 4645d522f475Smrg if ((fd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 4646d522f475Smrg write(fd, utptr, sizeof(*utptr)); 4647d522f475Smrg close(fd); 4648d522f475Smrg } 4649d522f475Smrg } 4650d522f475Smrg#endif 4651d522f475Smrg#endif 4652d522f475Smrg break; 4653d522f475Smrg } 4654d522f475Smrg memset(utptr, 0, sizeof(*utptr)); /* keep searching */ 4655d522f475Smrg } 4656d522f475Smrg (void) call_endutent(); 4657d522f475Smrg#ifdef USE_UTMP_SETGID 4658d522f475Smrg disableSetGid(); 4659d522f475Smrg TRACE_IDS; 4660d522f475Smrg#endif 4661d522f475Smrg } 4662d522f475Smrg#else /* not USE_SYSV_UTMP */ 4663d522f475Smrg int wfd; 4664d522f475Smrg struct utmp utmp; 4665d522f475Smrg 4666d522f475Smrg if (!resource.utmpInhibit && added_utmp_entry && 4667d522f475Smrg (am_slave < 0 && tslot > 0)) { 4668d522f475Smrg#if defined(USE_UTMP_SETGID) 4669d522f475Smrg setEffectiveGroup(save_egid); 4670d522f475Smrg TRACE_IDS; 4671d522f475Smrg#endif 4672d522f475Smrg if ((wfd = open(etc_utmp, O_WRONLY)) >= 0) { 4673956cc18dSsnj memset(&utmp, 0, sizeof(utmp)); 4674d522f475Smrg lseek(wfd, (long) (tslot * sizeof(utmp)), 0); 4675d522f475Smrg write(wfd, (char *) &utmp, sizeof(utmp)); 4676d522f475Smrg close(wfd); 4677d522f475Smrg } 4678d522f475Smrg#ifdef WTMP 467920d2c4d2Smrg if (xw->misc.login_shell && 4680d522f475Smrg (wfd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 4681d522f475Smrg (void) strncpy(utmp.ut_line, 4682d522f475Smrg my_pty_name(ttydev), 4683d522f475Smrg sizeof(utmp.ut_line)); 4684d522f475Smrg utmp.ut_time = time((time_t *) 0); 4685d522f475Smrg write(wfd, (char *) &utmp, sizeof(utmp)); 4686d522f475Smrg close(wfd); 4687d522f475Smrg } 4688d522f475Smrg#endif /* WTMP */ 4689d522f475Smrg#ifdef USE_UTMP_SETGID 4690d522f475Smrg disableSetGid(); 4691d522f475Smrg TRACE_IDS; 4692d522f475Smrg#endif 4693d522f475Smrg } 4694d522f475Smrg#endif /* USE_SYSV_UTMP */ 4695d522f475Smrg#endif /* HAVE_UTMP */ 4696d522f475Smrg 4697d522f475Smrg /* 4698d522f475Smrg * Flush pending data before releasing ownership, so nobody else can write 4699d522f475Smrg * in the middle of the data. 4700d522f475Smrg */ 4701d522f475Smrg ttyFlush(screen->respond); 4702d522f475Smrg 4703d522f475Smrg if (am_slave < 0) { 4704d522f475Smrg TRACE_IDS; 4705d522f475Smrg /* restore ownership of tty and pty */ 4706d522f475Smrg set_owner(ttydev, 0, 0, 0666U); 4707d522f475Smrg#if (defined(USE_PTY_DEVICE) && !defined(__sgi) && !defined(__hpux)) 4708d522f475Smrg set_owner(ptydev, 0, 0, 0666U); 4709d522f475Smrg#endif 4710d522f475Smrg } 4711d522f475Smrg 4712d522f475Smrg /* 4713d522f475Smrg * Close after releasing ownership to avoid race condition: other programs 4714d522f475Smrg * grabbing it, and *then* having us release ownership.... 4715d522f475Smrg */ 4716d522f475Smrg close(screen->respond); /* close explicitly to avoid race with slave side */ 4717d522f475Smrg#ifdef ALLOWLOGGING 4718d522f475Smrg if (screen->logging) 471920d2c4d2Smrg CloseLog(xw); 4720d522f475Smrg#endif 4721d522f475Smrg 4722d522f475Smrg#ifdef NO_LEAKS 4723d522f475Smrg if (n == 0) { 4724d522f475Smrg TRACE(("Freeing memory leaks\n")); 472520d2c4d2Smrg if (xw != 0) { 472620d2c4d2Smrg Display *dpy = TScreenOf(xw)->display; 4727d522f475Smrg 4728d522f475Smrg if (toplevel) { 4729d522f475Smrg XtDestroyWidget(toplevel); 4730d522f475Smrg TRACE(("destroyed top-level widget\n")); 4731d522f475Smrg } 4732d522f475Smrg sortedOpts(0, 0, 0); 4733d522f475Smrg noleaks_charproc(); 4734d522f475Smrg noleaks_ptydata(); 4735d522f475Smrg#if OPT_WIDE_CHARS 4736d522f475Smrg noleaks_CharacterClass(); 4737d522f475Smrg#endif 4738d522f475Smrg /* XrmSetDatabase(dpy, 0); increases leaks ;-) */ 4739d522f475Smrg XtCloseDisplay(dpy); 4740d522f475Smrg XtDestroyApplicationContext(app_con); 4741d522f475Smrg#if OPT_SESSION_MGT 4742d522f475Smrg IceRemoveConnectionWatch(icewatch, NULL); 4743d522f475Smrg#endif 4744d522f475Smrg TRACE(("closed display\n")); 4745d522f475Smrg } 474620d2c4d2Smrg TRACE_CLOSE(); 4747d522f475Smrg } 4748d522f475Smrg#endif 4749d522f475Smrg 4750d522f475Smrg exit(n); 4751d522f475Smrg SIGNAL_RETURN; 4752d522f475Smrg} 4753d522f475Smrg 4754d522f475Smrg/* ARGSUSED */ 4755d522f475Smrgstatic void 475620d2c4d2Smrgresize_termcap(XtermWidget xw) 4757d522f475Smrg{ 475820d2c4d2Smrg char *newtc = get_tcap_buffer(xw); 475920d2c4d2Smrg 4760d522f475Smrg#ifndef USE_SYSV_ENVVARS 4761d522f475Smrg if (!TEK4014_ACTIVE(xw) && *newtc) { 4762d522f475Smrg TScreen *screen = TScreenOf(xw); 4763d522f475Smrg char *ptr1, *ptr2; 4764d522f475Smrg size_t i; 4765d522f475Smrg int li_first = 0; 4766d522f475Smrg char *temp; 4767d522f475Smrg char oldtc[TERMCAP_SIZE]; 4768d522f475Smrg 4769d522f475Smrg strcpy(oldtc, newtc); 4770d522f475Smrg TRACE(("resize %s\n", oldtc)); 4771d522f475Smrg if ((ptr1 = x_strindex(oldtc, "co#")) == NULL) { 4772d522f475Smrg strcat(oldtc, "co#80:"); 4773d522f475Smrg ptr1 = x_strindex(oldtc, "co#"); 4774d522f475Smrg } 4775d522f475Smrg if ((ptr2 = x_strindex(oldtc, "li#")) == NULL) { 4776d522f475Smrg strcat(oldtc, "li#24:"); 4777d522f475Smrg ptr2 = x_strindex(oldtc, "li#"); 4778d522f475Smrg } 4779d522f475Smrg if (ptr1 > ptr2) { 4780d522f475Smrg li_first++; 4781d522f475Smrg temp = ptr1; 4782d522f475Smrg ptr1 = ptr2; 4783d522f475Smrg ptr2 = temp; 4784d522f475Smrg } 4785d522f475Smrg ptr1 += 3; 4786d522f475Smrg ptr2 += 3; 4787956cc18dSsnj strncpy(newtc, oldtc, i = (size_t) (ptr1 - oldtc)); 4788d522f475Smrg temp = newtc + i; 4789d522f475Smrg sprintf(temp, "%d", (li_first 4790d522f475Smrg ? MaxRows(screen) 4791d522f475Smrg : MaxCols(screen))); 4792d522f475Smrg temp += strlen(temp); 4793d522f475Smrg ptr1 = strchr(ptr1, ':'); 4794956cc18dSsnj strncpy(temp, ptr1, i = (size_t) (ptr2 - ptr1)); 4795d522f475Smrg temp += i; 4796d522f475Smrg sprintf(temp, "%d", (li_first 4797d522f475Smrg ? MaxCols(screen) 4798d522f475Smrg : MaxRows(screen))); 4799d522f475Smrg ptr2 = strchr(ptr2, ':'); 4800d522f475Smrg strcat(temp, ptr2); 4801d522f475Smrg TRACE((" ==> %s\n", newtc)); 4802d522f475Smrg TRACE((" new size %dx%d\n", MaxRows(screen), MaxCols(screen))); 4803d522f475Smrg } 4804d522f475Smrg#endif /* USE_SYSV_ENVVARS */ 4805d522f475Smrg} 4806d522f475Smrg 4807d522f475Smrg#endif /* ! VMS */ 4808d522f475Smrg 4809d522f475Smrg/* 4810d522f475Smrg * Does a non-blocking wait for a child process. If the system 4811d522f475Smrg * doesn't support non-blocking wait, do nothing. 4812d522f475Smrg * Returns the pid of the child, or 0 or -1 if none or error. 4813d522f475Smrg */ 4814d522f475Smrgint 4815d522f475Smrgnonblocking_wait(void) 4816d522f475Smrg{ 4817d522f475Smrg#ifdef USE_POSIX_WAIT 4818d522f475Smrg pid_t pid; 4819d522f475Smrg 4820d522f475Smrg pid = waitpid(-1, NULL, WNOHANG); 4821d522f475Smrg#elif defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP)) 4822d522f475Smrg /* cannot do non-blocking wait */ 4823d522f475Smrg int pid = 0; 4824d522f475Smrg#else /* defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP)) */ 4825d522f475Smrg#if defined(Lynx) 4826d522f475Smrg int status; 4827d522f475Smrg#else 4828d522f475Smrg union wait status; 4829d522f475Smrg#endif 4830d522f475Smrg int pid; 4831d522f475Smrg 4832d522f475Smrg pid = wait3(&status, WNOHANG, (struct rusage *) NULL); 4833d522f475Smrg#endif /* USE_POSIX_WAIT else */ 4834d522f475Smrg return pid; 4835d522f475Smrg} 4836d522f475Smrg 4837d522f475Smrg#ifndef VMS 4838d522f475Smrg 4839d522f475Smrg/* ARGSUSED */ 4840d522f475Smrgstatic SIGNAL_T 4841d522f475Smrgreapchild(int n GCC_UNUSED) 4842d522f475Smrg{ 4843d522f475Smrg int olderrno = errno; 4844d522f475Smrg int pid; 4845d522f475Smrg 4846d522f475Smrg pid = wait(NULL); 4847d522f475Smrg 4848d522f475Smrg#ifdef USE_SYSV_SIGNALS 4849d522f475Smrg /* cannot re-enable signal before waiting for child 4850d522f475Smrg * because then SVR4 loops. Sigh. HP-UX 9.01 too. 4851d522f475Smrg */ 4852d522f475Smrg (void) signal(SIGCHLD, reapchild); 4853d522f475Smrg#endif 4854d522f475Smrg 4855d522f475Smrg do { 485620d2c4d2Smrg if (pid == TScreenOf(term)->pid) { 4857d522f475Smrg#ifdef DEBUG 4858d522f475Smrg if (debug) 4859d522f475Smrg fputs("Exiting\n", stderr); 4860d522f475Smrg#endif 4861d522f475Smrg if (!hold_screen) 4862d522f475Smrg need_cleanup = True; 4863d522f475Smrg } 4864d522f475Smrg } while ((pid = nonblocking_wait()) > 0); 4865d522f475Smrg 4866d522f475Smrg errno = olderrno; 4867d522f475Smrg SIGNAL_RETURN; 4868d522f475Smrg} 4869d522f475Smrg#endif /* !VMS */ 4870d522f475Smrg 4871d522f475Smrgstatic void 487220d2c4d2Smrgremove_termcap_entry(char *buf, const char *str) 4873d522f475Smrg{ 4874d522f475Smrg char *base = buf; 4875d522f475Smrg char *first = base; 4876d522f475Smrg int count = 0; 4877d522f475Smrg size_t len = strlen(str); 4878d522f475Smrg 4879d522f475Smrg TRACE(("*** remove_termcap_entry('%s', '%s')\n", str, buf)); 4880d522f475Smrg 4881d522f475Smrg while (*buf != 0) { 4882d522f475Smrg if (!count && !strncmp(buf, str, len)) { 4883d522f475Smrg while (*buf != 0) { 4884d522f475Smrg if (*buf == '\\') 4885d522f475Smrg buf++; 4886d522f475Smrg else if (*buf == ':') 4887d522f475Smrg break; 4888d522f475Smrg if (*buf != 0) 4889d522f475Smrg buf++; 4890d522f475Smrg } 4891d522f475Smrg while ((*first++ = *buf++) != 0) ; 4892d522f475Smrg TRACE(("...removed_termcap_entry('%s', '%s')\n", str, base)); 4893d522f475Smrg return; 4894d522f475Smrg } else if (*buf == '\\') { 4895d522f475Smrg buf++; 4896d522f475Smrg } else if (*buf == ':') { 4897d522f475Smrg first = buf; 4898d522f475Smrg count = 0; 4899d522f475Smrg } else if (!isspace(CharOf(*buf))) { 4900d522f475Smrg count++; 4901d522f475Smrg } 4902d522f475Smrg if (*buf != 0) 4903d522f475Smrg buf++; 4904d522f475Smrg } 4905d522f475Smrg TRACE(("...cannot remove\n")); 4906d522f475Smrg} 4907d522f475Smrg 4908d522f475Smrg/* 4909d522f475Smrg * parse_tty_modes accepts lines of the following form: 4910d522f475Smrg * 4911d522f475Smrg * [SETTING] ... 4912d522f475Smrg * 4913d522f475Smrg * where setting consists of the words in the modelist followed by a character 4914d522f475Smrg * or ^char. 4915d522f475Smrg */ 4916d522f475Smrgstatic int 4917d522f475Smrgparse_tty_modes(char *s, struct _xttymodes *modelist) 4918d522f475Smrg{ 4919d522f475Smrg struct _xttymodes *mp; 4920d522f475Smrg int c; 4921d522f475Smrg int count = 0; 4922d522f475Smrg 4923d522f475Smrg TRACE(("parse_tty_modes\n")); 4924d522f475Smrg while (1) { 4925d522f475Smrg size_t len; 4926d522f475Smrg 4927d522f475Smrg while (*s && isascii(CharOf(*s)) && isspace(CharOf(*s))) 4928d522f475Smrg s++; 4929d522f475Smrg if (!*s) 4930d522f475Smrg return count; 4931d522f475Smrg 4932d522f475Smrg for (len = 0; isalnum(CharOf(s[len])); ++len) ; 4933d522f475Smrg for (mp = modelist; mp->name; mp++) { 4934d522f475Smrg if (len == mp->len 4935d522f475Smrg && strncmp(s, mp->name, mp->len) == 0) 4936d522f475Smrg break; 4937d522f475Smrg } 4938d522f475Smrg if (!mp->name) 4939d522f475Smrg return -1; 4940d522f475Smrg 4941d522f475Smrg s += mp->len; 4942d522f475Smrg while (*s && isascii(CharOf(*s)) && isspace(CharOf(*s))) 4943d522f475Smrg s++; 4944d522f475Smrg if (!*s) 4945d522f475Smrg return -1; 4946d522f475Smrg 4947d522f475Smrg if ((c = decode_keyvalue(&s, False)) != -1) { 4948d522f475Smrg mp->value = c; 4949d522f475Smrg mp->set = 1; 4950d522f475Smrg count++; 4951d522f475Smrg TRACE(("...parsed #%d: %s=%#x\n", count, mp->name, c)); 4952d522f475Smrg } 4953d522f475Smrg } 4954d522f475Smrg} 4955d522f475Smrg 4956d522f475Smrg#ifndef VMS /* don't use pipes on OpenVMS */ 4957d522f475Smrgint 4958d522f475SmrgGetBytesAvailable(int fd) 4959d522f475Smrg{ 4960d522f475Smrg#if defined(FIONREAD) 4961d522f475Smrg int arg; 4962d522f475Smrg ioctl(fd, FIONREAD, (char *) &arg); 4963d522f475Smrg return (int) arg; 4964d522f475Smrg#elif defined(__CYGWIN__) 4965d522f475Smrg fd_set set; 496620d2c4d2Smrg struct timeval select_timeout = 4967d522f475Smrg {0, 0}; 4968d522f475Smrg 4969d522f475Smrg FD_ZERO(&set); 4970d522f475Smrg FD_SET(fd, &set); 497120d2c4d2Smrg if (Select(fd + 1, &set, NULL, NULL, &select_timeout) > 0) 4972d522f475Smrg return 1; 4973d522f475Smrg else 4974d522f475Smrg return 0; 4975d522f475Smrg#elif defined(FIORDCK) 4976d522f475Smrg return (ioctl(fd, FIORDCHK, NULL)); 4977d522f475Smrg#else /* !FIORDCK */ 4978d522f475Smrg struct pollfd pollfds[1]; 4979d522f475Smrg 4980d522f475Smrg pollfds[0].fd = fd; 4981d522f475Smrg pollfds[0].events = POLLIN; 4982d522f475Smrg return poll(pollfds, 1, 0); 4983d522f475Smrg#endif 4984d522f475Smrg} 4985d522f475Smrg#endif /* !VMS */ 4986d522f475Smrg 4987d522f475Smrg/* Utility function to try to hide system differences from 4988d522f475Smrg everybody who used to call killpg() */ 4989d522f475Smrg 4990d522f475Smrgint 4991d522f475Smrgkill_process_group(int pid, int sig) 4992d522f475Smrg{ 4993d522f475Smrg TRACE(("kill_process_group(pid=%d, sig=%d)\n", pid, sig)); 4994d522f475Smrg#if defined(SVR4) || defined(SYSV) || !defined(X_NOT_POSIX) 4995d522f475Smrg return kill(-pid, sig); 4996d522f475Smrg#else 4997d522f475Smrg return killpg(pid, sig); 4998d522f475Smrg#endif 4999d522f475Smrg} 5000d522f475Smrg 5001d522f475Smrg#if OPT_EBCDIC 5002d522f475Smrgint 5003d522f475SmrgA2E(int x) 5004d522f475Smrg{ 5005d522f475Smrg char c; 5006d522f475Smrg c = x; 5007d522f475Smrg __atoe_l(&c, 1); 5008d522f475Smrg return c; 5009d522f475Smrg} 5010d522f475Smrg 5011d522f475Smrgint 5012d522f475SmrgE2A(int x) 5013d522f475Smrg{ 5014d522f475Smrg char c; 5015d522f475Smrg c = x; 5016d522f475Smrg __etoa_l(&c, 1); 5017d522f475Smrg return c; 5018d522f475Smrg} 5019d522f475Smrg#endif 5020d522f475Smrg 5021d522f475Smrg#if defined(__QNX__) && !defined(__QNXNTO__) 5022d522f475Smrg#include <sys/types.h> 5023d522f475Smrg#include <sys/proc_msg.h> 5024d522f475Smrg#include <sys/kernel.h> 5025d522f475Smrg#include <string.h> 5026d522f475Smrg#include <errno.h> 5027d522f475Smrg 5028d522f475Smrgstruct _proc_session ps; 5029d522f475Smrgstruct _proc_session_reply rps; 5030d522f475Smrg 5031d522f475Smrgint 5032d522f475Smrgqsetlogin(char *login, char *ttyname) 5033d522f475Smrg{ 5034d522f475Smrg int v = getsid(getpid()); 5035d522f475Smrg 5036d522f475Smrg memset(&ps, 0, sizeof(ps)); 5037d522f475Smrg memset(&rps, 0, sizeof(rps)); 5038d522f475Smrg 5039d522f475Smrg ps.type = _PROC_SESSION; 5040d522f475Smrg ps.subtype = _PROC_SUB_ACTION1; 5041d522f475Smrg ps.sid = v; 5042d522f475Smrg strcpy(ps.name, login); 5043d522f475Smrg 5044d522f475Smrg Send(1, &ps, &rps, sizeof(ps), sizeof(rps)); 5045d522f475Smrg 5046d522f475Smrg if (rps.status < 0) 5047d522f475Smrg return (rps.status); 5048d522f475Smrg 5049d522f475Smrg ps.type = _PROC_SESSION; 5050d522f475Smrg ps.subtype = _PROC_SUB_ACTION2; 5051d522f475Smrg ps.sid = v; 5052d522f475Smrg sprintf(ps.name, "//%d%s", getnid(), ttyname); 5053d522f475Smrg Send(1, &ps, &rps, sizeof(ps), sizeof(rps)); 5054d522f475Smrg 5055d522f475Smrg return (rps.status); 5056d522f475Smrg} 5057d522f475Smrg#endif 5058