main.c revision 04b94745
104b94745Smrg/* $XTermId: main.c,v 1.921 2024/05/22 20:11:43 tom Exp $ */ 20bd37d32Smrg 30bd37d32Smrg/* 404b94745Smrg * Copyright 2002-2023,2024 by Thomas E. Dickey 50bd37d32Smrg * 60bd37d32Smrg * All Rights Reserved 70bd37d32Smrg * 80bd37d32Smrg * Permission is hereby granted, free of charge, to any person obtaining a 90bd37d32Smrg * copy of this software and associated documentation files (the 100bd37d32Smrg * "Software"), to deal in the Software without restriction, including 110bd37d32Smrg * without limitation the rights to use, copy, modify, merge, publish, 120bd37d32Smrg * distribute, sublicense, and/or sell copies of the Software, and to 130bd37d32Smrg * permit persons to whom the Software is furnished to do so, subject to 140bd37d32Smrg * the following conditions: 150bd37d32Smrg * 160bd37d32Smrg * The above copyright notice and this permission notice shall be included 170bd37d32Smrg * in all copies or substantial portions of the Software. 180bd37d32Smrg * 190bd37d32Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 200bd37d32Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 210bd37d32Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 220bd37d32Smrg * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 230bd37d32Smrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 240bd37d32Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 250bd37d32Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 260bd37d32Smrg * 270bd37d32Smrg * Except as contained in this notice, the name(s) of the above copyright 280bd37d32Smrg * holders shall not be used in advertising or otherwise to promote the 290bd37d32Smrg * sale, use or other dealings in this Software without prior written 300bd37d32Smrg * authorization. 310bd37d32Smrg * 32f2e35a3aSmrg * Copyright 1987, 1988 X Consortium 330bd37d32Smrg * 340bd37d32Smrg * Permission to use, copy, modify, distribute, and sell this software and its 350bd37d32Smrg * documentation for any purpose is hereby granted without fee, provided that 360bd37d32Smrg * the above copyright notice appear in all copies and that both that 370bd37d32Smrg * copyright notice and this permission notice appear in supporting 380bd37d32Smrg * documentation. 390bd37d32Smrg * 400bd37d32Smrg * The above copyright notice and this permission notice shall be included in 410bd37d32Smrg * all copies or substantial portions of the Software. 420bd37d32Smrg * 430bd37d32Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 440bd37d32Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 450bd37d32Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 460bd37d32Smrg * OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 470bd37d32Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 480bd37d32Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 490bd37d32Smrg * 50f2e35a3aSmrg * Except as contained in this notice, the name of the X Consortium shall not be 510bd37d32Smrg * used in advertising or otherwise to promote the sale, use or other dealings 52f2e35a3aSmrg * in this Software without prior written authorization from the X Consortium. 530bd37d32Smrg * 540bd37d32Smrg * Copyright 1987, 1988 by Digital Equipment Corporation, Maynard. 550bd37d32Smrg * 560bd37d32Smrg * All Rights Reserved 570bd37d32Smrg * 580bd37d32Smrg * Permission to use, copy, modify, and distribute this software and its 590bd37d32Smrg * documentation for any purpose and without fee is hereby granted, 600bd37d32Smrg * provided that the above copyright notice appear in all copies and that 610bd37d32Smrg * both that copyright notice and this permission notice appear in 620bd37d32Smrg * supporting documentation, and that the name of Digital not be used in 630bd37d32Smrg * advertising or publicity pertaining to distribution of the software 640bd37d32Smrg * without specific, written prior permission. 650bd37d32Smrg * 660bd37d32Smrg * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 670bd37d32Smrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 680bd37d32Smrg * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 690bd37d32Smrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 700bd37d32Smrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 710bd37d32Smrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 720bd37d32Smrg * SOFTWARE. 730bd37d32Smrg */ 74d522f475Smrg 75d522f475Smrg/* 76d522f475Smrg * W A R N I N G 77d522f475Smrg * 78d522f475Smrg * If you think you know what all of this code is doing, you are 79d522f475Smrg * probably very mistaken. There be serious and nasty dragons here. 80d522f475Smrg * 81d522f475Smrg * This client is *not* to be taken as an example of how to write X 82d522f475Smrg * Toolkit applications. It is in need of a substantial rewrite, 83d522f475Smrg * ideally to create a generic tty widget with several different parsing 84d522f475Smrg * widgets so that you can plug 'em together any way you want. Don't 85d522f475Smrg * hold your breath, though.... 86d522f475Smrg */ 87d522f475Smrg 88d522f475Smrg/* main.c */ 89d522f475Smrg 90d522f475Smrg#define RES_OFFSET(field) XtOffsetOf(XTERM_RESOURCE, field) 91d522f475Smrg 92d522f475Smrg#include <xterm.h> 930bd37d32Smrg#include <version.h> 94894e0ac8Smrg#include <graphics.h> 95d522f475Smrg 9604b94745Smrg/* xterm uses these X Toolkit resource names, which are exported in array */ 9704b94745Smrg#undef XtNborderWidth 9804b94745Smrg#undef XtNiconName 9904b94745Smrg#undef XtNgeometry 10004b94745Smrg#undef XtNreverseVideo 10104b94745Smrg#undef XtNtitle 10204b94745Smrg 10304b94745Smrg#define XtNborderWidth "borderWidth" 10404b94745Smrg#define XtNgeometry "geometry" 10504b94745Smrg#define XtNiconName "iconName" 10604b94745Smrg#define XtNreverseVideo "reverseVideo" 10704b94745Smrg#define XtNtitle "title" 10804b94745Smrg 109d522f475Smrg#if OPT_TOOLBAR 110d522f475Smrg 111d522f475Smrg#if defined(HAVE_LIB_XAW) 112d522f475Smrg#include <X11/Xaw/Form.h> 113d522f475Smrg#elif defined(HAVE_LIB_XAW3D) 114d522f475Smrg#include <X11/Xaw3d/Form.h> 11501037d57Smrg#elif defined(HAVE_LIB_XAW3DXFT) 11601037d57Smrg#include <X11/Xaw3dxft/Form.h> 117f2e35a3aSmrg#include <X11/Xaw3dxft/Xaw3dXft.h> 118d522f475Smrg#elif defined(HAVE_LIB_NEXTAW) 119d522f475Smrg#include <X11/neXtaw/Form.h> 120d522f475Smrg#elif defined(HAVE_LIB_XAWPLUS) 121d522f475Smrg#include <X11/XawPlus/Form.h> 122d522f475Smrg#endif 123d522f475Smrg 124f2e35a3aSmrg#else 125f2e35a3aSmrg 126f2e35a3aSmrg#if defined(HAVE_LIB_XAW3DXFT) 127f2e35a3aSmrg#include <X11/Xaw3dxft/Xaw3dXft.h> 128f2e35a3aSmrg#endif 129f2e35a3aSmrg 130d522f475Smrg#endif /* OPT_TOOLBAR */ 131d522f475Smrg 132d522f475Smrg#include <pwd.h> 133d522f475Smrg#include <ctype.h> 134d522f475Smrg 135d522f475Smrg#include <data.h> 136d522f475Smrg#include <error.h> 137d522f475Smrg#include <menu.h> 138d522f475Smrg#include <main.h> 139d522f475Smrg#include <xstrings.h> 140d522f475Smrg#include <xtermcap.h> 141d522f475Smrg#include <xterm_io.h> 142d522f475Smrg 143d522f475Smrg#if OPT_WIDE_CHARS 144d522f475Smrg#include <charclass.h> 145d522f475Smrg#endif 146d522f475Smrg 147d522f475Smrg#ifdef __osf__ 148d522f475Smrg#define USE_SYSV_SIGNALS 149d522f475Smrg#define WTMP 150d522f475Smrg#include <pty.h> /* openpty() */ 151d522f475Smrg#endif 152d522f475Smrg 153d522f475Smrg#ifdef __sgi 154d522f475Smrg#include <grp.h> /* initgroups() */ 155d522f475Smrg#endif 156d522f475Smrg 157ad37e533Smrgstatic GCC_NORETURN void hungtty(int); 158ad37e533Smrgstatic GCC_NORETURN void Syntax(char *); 159ad37e533Smrgstatic GCC_NORETURN void HsSysError(int); 160d522f475Smrg 16104b94745Smrg#if defined(__SCO__) || defined(SVR4) || defined(_POSIX_VERSION) || ( defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 1) ) 162d522f475Smrg#define USE_POSIX_SIGNALS 163d522f475Smrg#endif 164d522f475Smrg 165d522f475Smrg#if defined(SYSV) && !defined(SVR4) && !defined(ISC22) && !defined(ISC30) 166d522f475Smrg/* older SYSV systems cannot ignore SIGHUP. 167d522f475Smrg Shell hangs, or you get extra shells, or something like that */ 168d522f475Smrg#define USE_SYSV_SIGHUP 169d522f475Smrg#endif 170d522f475Smrg 171d522f475Smrg#if defined(sony) && defined(bsd43) && !defined(KANJI) 172d522f475Smrg#define KANJI 173d522f475Smrg#endif 174d522f475Smrg 17504b94745Smrg#ifdef __linux__ 176d522f475Smrg#define USE_SYSV_PGRP 177d522f475Smrg#define USE_SYSV_SIGNALS 178d522f475Smrg#define WTMP 17904b94745Smrg#ifdef HAVE_PTY_H 180d522f475Smrg#include <pty.h> 181d522f475Smrg#endif 182d522f475Smrg#endif 183d522f475Smrg 184d522f475Smrg#ifdef __MVS__ 185d522f475Smrg#define USE_SYSV_PGRP 186d522f475Smrg#define USE_SYSV_SIGNALS 187d522f475Smrg#endif 188d522f475Smrg 189d522f475Smrg#ifdef __CYGWIN__ 190d522f475Smrg#define WTMP 191d522f475Smrg#endif 192d522f475Smrg 193d522f475Smrg#ifdef __SCO__ 194d522f475Smrg#ifndef _SVID3 195d522f475Smrg#define _SVID3 196d522f475Smrg#endif 197d522f475Smrg#endif 198d522f475Smrg 19904b94745Smrg#if defined(__GLIBC__) && !defined(__linux__) 200d522f475Smrg#define USE_SYSV_PGRP 201d522f475Smrg#define WTMP 202d522f475Smrg#endif 203d522f475Smrg 204f2e35a3aSmrg#if defined(USE_TTY_GROUP) || defined(USE_UTMP_SETGID) || defined(HAVE_INITGROUPS) 205d522f475Smrg#include <grp.h> 206d522f475Smrg#endif 207d522f475Smrg 208d522f475Smrg#ifndef TTY_GROUP_NAME 209d522f475Smrg#define TTY_GROUP_NAME "tty" 210d522f475Smrg#endif 211d522f475Smrg 212d522f475Smrg#include <sys/stat.h> 213d522f475Smrg 214d522f475Smrg#ifdef Lynx 215d522f475Smrg#ifndef BSDLY 216d522f475Smrg#define BSDLY 0 217d522f475Smrg#endif 218d522f475Smrg#ifndef VTDLY 219d522f475Smrg#define VTDLY 0 220d522f475Smrg#endif 221d522f475Smrg#ifndef FFDLY 222d522f475Smrg#define FFDLY 0 223d522f475Smrg#endif 224d522f475Smrg#endif 225d522f475Smrg 226d522f475Smrg#ifdef SYSV /* { */ 227d522f475Smrg 228d522f475Smrg#ifdef USE_USG_PTYS /* AT&T SYSV has no ptyio.h */ 229d522f475Smrg#include <sys/stropts.h> /* for I_PUSH */ 230d522f475Smrg#include <poll.h> /* for POLLIN */ 231d522f475Smrg#endif /* USE_USG_PTYS */ 232d522f475Smrg 233d522f475Smrg#define USE_SYSV_SIGNALS 234d522f475Smrg#define USE_SYSV_PGRP 235d522f475Smrg 236d522f475Smrg#if !defined(TIOCSWINSZ) || defined(__SCO__) || defined(__UNIXWARE__) 237d522f475Smrg#define USE_SYSV_ENVVARS /* COLUMNS/LINES vs. TERMCAP */ 238d522f475Smrg#endif 239d522f475Smrg 240d522f475Smrg/* 241d522f475Smrg * now get system-specific includes 242d522f475Smrg */ 243d522f475Smrg#ifdef macII 244d522f475Smrg#include <sys/ttychars.h> 245d522f475Smrg#undef USE_SYSV_ENVVARS 246d522f475Smrg#undef FIOCLEX 247d522f475Smrg#undef FIONCLEX 248d522f475Smrg#define setpgrp2 setpgrp 249d522f475Smrg#include <sgtty.h> 250d522f475Smrg#include <sys/resource.h> 251d522f475Smrg#endif 252d522f475Smrg 253d522f475Smrg#ifdef __hpux 254d522f475Smrg#include <sys/ptyio.h> 255d522f475Smrg#endif /* __hpux */ 256d522f475Smrg 257d522f475Smrg#ifdef __osf__ 258d522f475Smrg#undef USE_SYSV_PGRP 259d522f475Smrg#define setpgrp setpgid 260d522f475Smrg#endif 261d522f475Smrg 262d522f475Smrg#ifdef __sgi 263d522f475Smrg#include <sys/sysmacros.h> 264d522f475Smrg#endif /* __sgi */ 265d522f475Smrg 266d522f475Smrg#ifdef sun 267d522f475Smrg#include <sys/strredir.h> 268d522f475Smrg#endif 269d522f475Smrg 270e39b573cSmrg#else /* } !SYSV { */ /* BSD systems */ 271d522f475Smrg 272d522f475Smrg#ifdef __QNX__ 273d522f475Smrg 274d522f475Smrg#ifndef __QNXNTO__ 275d522f475Smrg#define ttyslot() 1 276d522f475Smrg#else 277d522f475Smrg#define USE_SYSV_PGRP 278d522f475Smrgextern __inline__ 279d522f475Smrgint 280d522f475Smrgttyslot(void) 281d522f475Smrg{ 282d522f475Smrg return 1; /* yuk */ 283d522f475Smrg} 284d522f475Smrg#endif 285d522f475Smrg 286d522f475Smrg#else 287d522f475Smrg 288d522f475Smrg#if defined(__INTERIX) || defined(__APPLE__) 289d522f475Smrg#define setpgrp setpgid 290d522f475Smrg#endif 291d522f475Smrg 29204b94745Smrg#ifndef __linux__ 293d522f475Smrg#ifndef VMS 294d522f475Smrg#ifndef USE_POSIX_TERMIOS 295d522f475Smrg#ifndef USE_ANY_SYSV_TERMIO 296d522f475Smrg#include <sgtty.h> 297d522f475Smrg#endif 298d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 299d522f475Smrg#ifdef Lynx 300d522f475Smrg#include <resource.h> 301d522f475Smrg#else 302d522f475Smrg#include <sys/resource.h> 303d522f475Smrg#endif 304d522f475Smrg#endif /* !VMS */ 30504b94745Smrg#endif /* !__linux__ */ 306d522f475Smrg 307d522f475Smrg#endif /* __QNX__ */ 308d522f475Smrg 309d522f475Smrg#endif /* } !SYSV */ 310d522f475Smrg 311d522f475Smrg/* Xpoll.h and <sys/param.h> on glibc 2.1 systems have colliding NBBY's */ 312d522f475Smrg#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))) 313d522f475Smrg#ifndef NOFILE 314d522f475Smrg#define NOFILE OPEN_MAX 315d522f475Smrg#endif 316d522f475Smrg#elif !(defined(VMS) || defined(WIN32) || defined(Lynx) || defined(__GNU__) || defined(__MVS__)) 317d522f475Smrg#include <sys/param.h> /* for NOFILE */ 318d522f475Smrg#endif 319d522f475Smrg 320d522f475Smrg#if defined(BSD) && (BSD >= 199103) 321d522f475Smrg#define WTMP 322d522f475Smrg#endif 323d522f475Smrg 324d522f475Smrg#include <stdio.h> 32504b94745Smrg#include <math.h> 326d522f475Smrg 327d522f475Smrg#ifdef __hpux 328d522f475Smrg#include <sys/utsname.h> 329d522f475Smrg#endif /* __hpux */ 330d522f475Smrg 331d522f475Smrg#if defined(apollo) && (OSMAJORVERSION == 10) && (OSMINORVERSION < 4) 332d522f475Smrg#define ttyslot() 1 333d522f475Smrg#endif /* apollo */ 334d522f475Smrg 335d522f475Smrg#if defined(UTMPX_FOR_UTMP) 336d522f475Smrg#define UTMP_STR utmpx 337d522f475Smrg#else 338d522f475Smrg#define UTMP_STR utmp 339d522f475Smrg#endif 340d522f475Smrg 341d522f475Smrg#if defined(USE_UTEMPTER) 342d522f475Smrg#include <utempter.h> 343f2e35a3aSmrg#if 1 344f2e35a3aSmrg#define UTEMPTER_ADD(pty,hostname,master_fd) utempter_add_record(master_fd, hostname) 345f2e35a3aSmrg#define UTEMPTER_DEL() utempter_remove_added_record () 346f2e35a3aSmrg#else 347f2e35a3aSmrg#define UTEMPTER_ADD(pty,hostname,master_fd) addToUtmp(pty, hostname, master_fd) 348f2e35a3aSmrg#define UTEMPTER_DEL() removeFromUtmp() 349f2e35a3aSmrg#endif 350d522f475Smrg#endif 351d522f475Smrg 3522e4f8982Smrg#if defined(I_FIND) && defined(I_PUSH) 3532e4f8982Smrg#define PUSH_FAILS(fd,name) ioctl(fd, I_FIND, name) == 0 \ 3542e4f8982Smrg && ioctl(fd, I_PUSH, name) < 0 3552e4f8982Smrg#else 3562e4f8982Smrg#define PUSH_FAILS(fd,name) ioctl(fd, I_PUSH, name) < 0 3572e4f8982Smrg#endif 3582e4f8982Smrg 359d522f475Smrg#if defined(UTMPX_FOR_UTMP) 360d522f475Smrg 361d522f475Smrg#include <utmpx.h> 362d522f475Smrg 363d522f475Smrg#define call_endutent endutxent 364d522f475Smrg#define call_getutid getutxid 365d522f475Smrg#define call_pututline pututxline 366d522f475Smrg#define call_setutent setutxent 367d522f475Smrg#define call_updwtmp updwtmpx 368d522f475Smrg 369d522f475Smrg#elif defined(HAVE_UTMP) 370d522f475Smrg 371d522f475Smrg#include <utmp.h> 372d522f475Smrg 373d522f475Smrg#if defined(_CRAY) && (OSMAJORVERSION < 8) 374d522f475Smrgextern struct utmp *getutid __((struct utmp * _Id)); 375d522f475Smrg#endif 376d522f475Smrg 377d522f475Smrg#define call_endutent endutent 378d522f475Smrg#define call_getutid getutid 379d522f475Smrg#define call_pututline pututline 380d522f475Smrg#define call_setutent setutent 381d522f475Smrg#define call_updwtmp updwtmp 382d522f475Smrg 383d522f475Smrg#endif 384d522f475Smrg 385d522f475Smrg#if defined(USE_LASTLOG) && defined(HAVE_LASTLOG_H) 386d522f475Smrg#include <lastlog.h> /* caution: glibc includes utmp.h here */ 387d522f475Smrg#endif 388d522f475Smrg 389d522f475Smrg#ifndef USE_LASTLOGX 390d522f475Smrg#if defined(_NETBSD_SOURCE) && defined(_PATH_LASTLOGX) 391d522f475Smrg#define USE_LASTLOGX 1 392d522f475Smrg#endif 393d522f475Smrg#endif 394d522f475Smrg 395d522f475Smrg#ifdef PUCC_PTYD 396d522f475Smrg#include <local/openpty.h> 397d522f475Smrg#endif /* PUCC_PTYD */ 398d522f475Smrg 399d522f475Smrg#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) 400d522f475Smrg#include <util.h> /* openpty() */ 401d522f475Smrg#endif 402d522f475Smrg 403956cc18dSsnj#if defined(__FreeBSD__) || defined(__DragonFly__) 404d522f475Smrg#include <libutil.h> /* openpty() */ 405d522f475Smrg#endif 406d522f475Smrg 407d522f475Smrg#if !defined(UTMP_FILENAME) 408d522f475Smrg#if defined(UTMP_FILE) 409d522f475Smrg#define UTMP_FILENAME UTMP_FILE 410d522f475Smrg#elif defined(_PATH_UTMP) 411d522f475Smrg#define UTMP_FILENAME _PATH_UTMP 412d522f475Smrg#else 413d522f475Smrg#define UTMP_FILENAME "/etc/utmp" 414d522f475Smrg#endif 415d522f475Smrg#endif 416d522f475Smrg 417d522f475Smrg#ifndef LASTLOG_FILENAME 418d522f475Smrg#ifdef _PATH_LASTLOG 419d522f475Smrg#define LASTLOG_FILENAME _PATH_LASTLOG 420d522f475Smrg#else 421d522f475Smrg#define LASTLOG_FILENAME "/usr/adm/lastlog" /* only on BSD systems */ 422d522f475Smrg#endif 423d522f475Smrg#endif 424d522f475Smrg 425d522f475Smrg#if !defined(WTMP_FILENAME) 426d522f475Smrg#if defined(WTMP_FILE) 427d522f475Smrg#define WTMP_FILENAME WTMP_FILE 428d522f475Smrg#elif defined(_PATH_WTMP) 429d522f475Smrg#define WTMP_FILENAME _PATH_WTMP 430d522f475Smrg#elif defined(SYSV) 431d522f475Smrg#define WTMP_FILENAME "/etc/wtmp" 432d522f475Smrg#else 433d522f475Smrg#define WTMP_FILENAME "/usr/adm/wtmp" 434d522f475Smrg#endif 435d522f475Smrg#endif 436d522f475Smrg 437d522f475Smrg#include <signal.h> 438d522f475Smrg 43904b94745Smrg#if defined(__SCO__) || (defined(ISC) && !defined(_POSIX_VERSION)) 440d522f475Smrg#undef SIGTSTP /* defined, but not the BSD way */ 441d522f475Smrg#endif 442d522f475Smrg 443d522f475Smrg#ifdef SIGTSTP 444d522f475Smrg#include <sys/wait.h> 445d522f475Smrg#endif 446d522f475Smrg 447d522f475Smrg#if defined(__SCO__) || defined(__UNIXWARE__) 448d522f475Smrg#undef ECHOKE 449d522f475Smrg#undef ECHOCTL 450d522f475Smrg#endif 451d522f475Smrg 452d522f475Smrg#if defined(HAVE_SYS_TTYDEFAULTS_H) && !defined(CEOF) 453d522f475Smrg#include <sys/ttydefaults.h> 454d522f475Smrg#endif 455d522f475Smrg 456d522f475Smrg#ifdef X_NOT_POSIX 457d522f475Smrgextern long lseek(); 458d522f475Smrg#if defined(USG) || defined(SVR4) 459d522f475Smrgextern unsigned sleep(); 460d522f475Smrg#else 461d522f475Smrgextern void sleep(); 462d522f475Smrg#endif 463d522f475Smrgextern char *ttyname(); 464d522f475Smrg#endif 465d522f475Smrg 466d522f475Smrg#if defined(SYSV) && defined(DECL_PTSNAME) 467d522f475Smrgextern char *ptsname(int); 468d522f475Smrg#endif 469d522f475Smrg 470d522f475Smrg#ifndef VMS 4710bd37d32Smrgstatic void reapchild(int /* n */ ); 4722e4f8982Smrgstatic int spawnXTerm(XtermWidget /* xw */ 4732e4f8982Smrg ,unsigned /* line_speed */ ); 47420d2c4d2Smrgstatic void remove_termcap_entry(char *, const char *); 475d522f475Smrg#ifdef USE_PTY_SEARCH 47620d2c4d2Smrgstatic int pty_search(int * /* pty */ ); 477d522f475Smrg#endif 478d522f475Smrg#endif /* ! VMS */ 479d522f475Smrg 480d522f475Smrgstatic int get_pty(int *pty, char *from); 48120d2c4d2Smrgstatic void resize_termcap(XtermWidget xw); 482e0a2b6dfSmrgstatic void set_owner(char *device, unsigned uid, unsigned gid, unsigned mode); 483d522f475Smrg 484d522f475Smrgstatic Bool added_utmp_entry = False; 485d522f475Smrg 486d522f475Smrg#ifdef HAVE_POSIX_SAVED_IDS 487d522f475Smrgstatic uid_t save_euid; 488d522f475Smrgstatic gid_t save_egid; 489d522f475Smrg#endif 490d522f475Smrg 491d522f475Smrgstatic uid_t save_ruid; 492d522f475Smrgstatic gid_t save_rgid; 493d522f475Smrg 494d522f475Smrg#if defined(USE_UTMP_SETGID) 495d522f475Smrgstatic int really_get_pty(int *pty, char *from); 496d522f475Smrg#endif 497d522f475Smrg 498d522f475Smrg#if defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 499d522f475Smrgstatic Bool xterm_exiting = False; 500d522f475Smrg#endif 501d522f475Smrg 502d522f475Smrgstatic char *explicit_shname = NULL; 503d522f475Smrg 504d522f475Smrg/* 505d522f475Smrg** Ordinarily it should be okay to omit the assignment in the following 506d522f475Smrg** statement. Apparently the c89 compiler on AIX 4.1.3 has a bug, or does 507d522f475Smrg** it? Without the assignment though the compiler will init command_to_exec 508d522f475Smrg** to 0xffffffff instead of NULL; and subsequent usage, e.g. in spawnXTerm() to 509d522f475Smrg** SEGV. 510d522f475Smrg*/ 511d522f475Smrgstatic char **command_to_exec = NULL; 512d522f475Smrg 513d522f475Smrg#if OPT_LUIT_PROG 514d522f475Smrgstatic char **command_to_exec_with_luit = NULL; 5150bd37d32Smrgstatic unsigned command_length_with_luit = 0; 516d522f475Smrg#endif 517d522f475Smrg 518d522f475Smrg/* choose a nice default value for speed - if we make it too low, users who 519d522f475Smrg * mistakenly use $TERM set to vt100 will get padding delays. Setting it to a 520d522f475Smrg * higher value is not useful since legacy applications (termcap) that care 521d522f475Smrg * about padding generally store the code in a short, which does not have 522d522f475Smrg * enough bits for the extended values. 523d522f475Smrg */ 524d522f475Smrg#ifdef B38400 /* everyone should define this */ 525d522f475Smrg#define VAL_LINE_SPEED B38400 526d522f475Smrg#else /* ...but xterm's used this for a long time */ 527d522f475Smrg#define VAL_LINE_SPEED B9600 528d522f475Smrg#endif 529d522f475Smrg 530d522f475Smrg/* 531d522f475Smrg * Allow use of system default characters if defined and reasonable. 532d522f475Smrg * These are based on the BSD ttydefaults.h 533d522f475Smrg */ 534d522f475Smrg#ifndef CBRK 535d522f475Smrg#define CBRK 0xff /* was 0 */ 536d522f475Smrg#endif 537d522f475Smrg#ifndef CDISCARD 538d522f475Smrg#define CDISCARD CONTROL('O') 539d522f475Smrg#endif 540d522f475Smrg#ifndef CDSUSP 541d522f475Smrg#define CDSUSP CONTROL('Y') 542d522f475Smrg#endif 543d522f475Smrg#ifndef CEOF 544d522f475Smrg#define CEOF CONTROL('D') 545d522f475Smrg#endif 546d522f475Smrg#ifndef CEOL 547d522f475Smrg#define CEOL 0xff /* was 0 */ 548d522f475Smrg#endif 549d522f475Smrg#ifndef CERASE 550d522f475Smrg#define CERASE 0177 551d522f475Smrg#endif 552d522f475Smrg#ifndef CERASE2 553d522f475Smrg#define CERASE2 CONTROL('H') 554d522f475Smrg#endif 555d522f475Smrg#ifndef CFLUSH 556d522f475Smrg#define CFLUSH CONTROL('O') 557d522f475Smrg#endif 558d522f475Smrg#ifndef CINTR 559d522f475Smrg#define CINTR CONTROL('C') 560d522f475Smrg#endif 561d522f475Smrg#ifndef CKILL 562d522f475Smrg#define CKILL CONTROL('U') /* was '@' */ 563d522f475Smrg#endif 564d522f475Smrg#ifndef CLNEXT 565d522f475Smrg#define CLNEXT CONTROL('V') 566d522f475Smrg#endif 567d522f475Smrg#ifndef CNUL 568d522f475Smrg#define CNUL 0 569d522f475Smrg#endif 570d522f475Smrg#ifndef CQUIT 571d522f475Smrg#define CQUIT CONTROL('\\') 572d522f475Smrg#endif 573d522f475Smrg#ifndef CRPRNT 574d522f475Smrg#define CRPRNT CONTROL('R') 575d522f475Smrg#endif 576d522f475Smrg#ifndef CREPRINT 577d522f475Smrg#define CREPRINT CRPRNT 578d522f475Smrg#endif 579d522f475Smrg#ifndef CSTART 580d522f475Smrg#define CSTART CONTROL('Q') 581d522f475Smrg#endif 582d522f475Smrg#ifndef CSTATUS 583d522f475Smrg#define CSTATUS CONTROL('T') 584d522f475Smrg#endif 585d522f475Smrg#ifndef CSTOP 586d522f475Smrg#define CSTOP CONTROL('S') 587d522f475Smrg#endif 588d522f475Smrg#ifndef CSUSP 589d522f475Smrg#define CSUSP CONTROL('Z') 590d522f475Smrg#endif 591d522f475Smrg#ifndef CSWTCH 592d522f475Smrg#define CSWTCH 0 593d522f475Smrg#endif 594d522f475Smrg#ifndef CWERASE 595d522f475Smrg#define CWERASE CONTROL('W') 596d522f475Smrg#endif 597d522f475Smrg 598d522f475Smrg#ifndef VMS 599d522f475Smrg#ifdef TERMIO_STRUCT 600d522f475Smrg/* The following structures are initialized in main() in order 601d522f475Smrg** to eliminate any assumptions about the internal order of their 602d522f475Smrg** contents. 603d522f475Smrg*/ 604d522f475Smrgstatic TERMIO_STRUCT d_tio; 605d522f475Smrg 606f2e35a3aSmrg#ifndef ONLCR 607f2e35a3aSmrg#define ONLCR 0 608f2e35a3aSmrg#endif 609f2e35a3aSmrg 610f2e35a3aSmrg#ifndef OPOST 611f2e35a3aSmrg#define OPOST 0 612f2e35a3aSmrg#endif 613f2e35a3aSmrg 614f2e35a3aSmrg#define D_TIO_FLAGS (OPOST | ONLCR) 615f2e35a3aSmrg 616d522f475Smrg#ifdef HAS_LTCHARS 617d522f475Smrgstatic struct ltchars d_ltc; 618d522f475Smrg#endif /* HAS_LTCHARS */ 619d522f475Smrg 620d522f475Smrg#ifdef TIOCLSET 621d522f475Smrgstatic unsigned int d_lmode; 622d522f475Smrg#endif /* TIOCLSET */ 623d522f475Smrg 624d522f475Smrg#else /* !TERMIO_STRUCT */ 625f2e35a3aSmrg 626f2e35a3aSmrg#define D_SG_FLAGS (EVENP | ODDP | ECHO | CRMOD) 627f2e35a3aSmrg 628d522f475Smrgstatic struct sgttyb d_sg = 629d522f475Smrg{ 630f2e35a3aSmrg 0, 0, 0177, CKILL, (D_SG_FLAGS | XTABS) 631d522f475Smrg}; 632d522f475Smrgstatic struct tchars d_tc = 633d522f475Smrg{ 634d522f475Smrg CINTR, CQUIT, CSTART, 635d522f475Smrg CSTOP, CEOF, CBRK 636d522f475Smrg}; 637d522f475Smrgstatic struct ltchars d_ltc = 638d522f475Smrg{ 639d522f475Smrg CSUSP, CDSUSP, CRPRNT, 640d522f475Smrg CFLUSH, CWERASE, CLNEXT 641d522f475Smrg}; 642d522f475Smrgstatic int d_disipline = NTTYDISC; 643d522f475Smrgstatic long int d_lmode = LCRTBS | LCRTERA | LCRTKIL | LCTLECH; 644d522f475Smrg#ifdef sony 645d522f475Smrgstatic long int d_jmode = KM_SYSSJIS | KM_ASCII; 646d522f475Smrgstatic struct jtchars d_jtc = 647d522f475Smrg{ 648d522f475Smrg 'J', 'B' 649d522f475Smrg}; 650d522f475Smrg#endif /* sony */ 651d522f475Smrg#endif /* TERMIO_STRUCT */ 652d522f475Smrg#endif /* ! VMS */ 653d522f475Smrg 654d522f475Smrg/* 655d522f475Smrg * SYSV has the termio.c_cc[V] and ltchars; BSD has tchars and ltchars; 656d522f475Smrg * SVR4 has only termio.c_cc, but it includes everything from ltchars. 657d522f475Smrg * POSIX termios has termios.c_cc, which is similar to SVR4. 658d522f475Smrg */ 659d522f475Smrg#define TTYMODE(name) { name, sizeof(name)-1, 0, 0 } 660d522f475Smrgstatic Boolean override_tty_modes = False; 661d522f475Smrg/* *INDENT-OFF* */ 662f2e35a3aSmrgstatic struct { 66320d2c4d2Smrg const char *name; 664d522f475Smrg size_t len; 665d522f475Smrg int set; 666d522f475Smrg int value; 667f2e35a3aSmrg} ttyModes[] = { 668d522f475Smrg TTYMODE("intr"), /* tchars.t_intrc ; VINTR */ 669d522f475Smrg#define XTTYMODE_intr 0 670d522f475Smrg TTYMODE("quit"), /* tchars.t_quitc ; VQUIT */ 671d522f475Smrg#define XTTYMODE_quit 1 672d522f475Smrg TTYMODE("erase"), /* sgttyb.sg_erase ; VERASE */ 673d522f475Smrg#define XTTYMODE_erase 2 674d522f475Smrg TTYMODE("kill"), /* sgttyb.sg_kill ; VKILL */ 675d522f475Smrg#define XTTYMODE_kill 3 676d522f475Smrg TTYMODE("eof"), /* tchars.t_eofc ; VEOF */ 677d522f475Smrg#define XTTYMODE_eof 4 678d522f475Smrg TTYMODE("eol"), /* VEOL */ 679d522f475Smrg#define XTTYMODE_eol 5 680d522f475Smrg TTYMODE("swtch"), /* VSWTCH */ 681d522f475Smrg#define XTTYMODE_swtch 6 682d522f475Smrg TTYMODE("start"), /* tchars.t_startc ; VSTART */ 683d522f475Smrg#define XTTYMODE_start 7 684d522f475Smrg TTYMODE("stop"), /* tchars.t_stopc ; VSTOP */ 685d522f475Smrg#define XTTYMODE_stop 8 686d522f475Smrg TTYMODE("brk"), /* tchars.t_brkc */ 687d522f475Smrg#define XTTYMODE_brk 9 688d522f475Smrg TTYMODE("susp"), /* ltchars.t_suspc ; VSUSP */ 689d522f475Smrg#define XTTYMODE_susp 10 690d522f475Smrg TTYMODE("dsusp"), /* ltchars.t_dsuspc ; VDSUSP */ 691d522f475Smrg#define XTTYMODE_dsusp 11 692d522f475Smrg TTYMODE("rprnt"), /* ltchars.t_rprntc ; VREPRINT */ 693d522f475Smrg#define XTTYMODE_rprnt 12 694d522f475Smrg TTYMODE("flush"), /* ltchars.t_flushc ; VDISCARD */ 695d522f475Smrg#define XTTYMODE_flush 13 696d522f475Smrg TTYMODE("weras"), /* ltchars.t_werasc ; VWERASE */ 697d522f475Smrg#define XTTYMODE_weras 14 698d522f475Smrg TTYMODE("lnext"), /* ltchars.t_lnextc ; VLNEXT */ 699d522f475Smrg#define XTTYMODE_lnext 15 700d522f475Smrg TTYMODE("status"), /* VSTATUS */ 701d522f475Smrg#define XTTYMODE_status 16 702d522f475Smrg TTYMODE("erase2"), /* VERASE2 */ 703d522f475Smrg#define XTTYMODE_erase2 17 704d522f475Smrg TTYMODE("eol2"), /* VEOL2 */ 705d522f475Smrg#define XTTYMODE_eol2 18 706f2e35a3aSmrg TTYMODE("tabs"), /* TAB0 */ 707f2e35a3aSmrg#define XTTYMODE_tabs 19 708f2e35a3aSmrg TTYMODE("-tabs"), /* TAB3 */ 709f2e35a3aSmrg#define XTTYMODE__tabs 20 710d522f475Smrg}; 711d522f475Smrg 712f2e35a3aSmrg#ifndef TAB0 713f2e35a3aSmrg#define TAB0 0 714f2e35a3aSmrg#endif 715f2e35a3aSmrg 716f2e35a3aSmrg#ifndef TAB3 717f2e35a3aSmrg#if defined(OXTABS) 718f2e35a3aSmrg#define TAB3 OXTABS 719f2e35a3aSmrg#elif defined(XTABS) 720f2e35a3aSmrg#define TAB3 XTABS 721f2e35a3aSmrg#endif 722f2e35a3aSmrg#endif 723f2e35a3aSmrg 724f2e35a3aSmrg#ifndef TABDLY 725f2e35a3aSmrg#define TABDLY (TAB0|TAB3) 726f2e35a3aSmrg#endif 727f2e35a3aSmrg 728f2e35a3aSmrg#define isTtyMode(p,q) (ttyChars[p].myMode == q && ttyModes[q].set) 729f2e35a3aSmrg 730f2e35a3aSmrg#define isTabMode(n) \ 731f2e35a3aSmrg (isTtyMode(n, XTTYMODE_tabs) || \ 732f2e35a3aSmrg isTtyMode(n, XTTYMODE__tabs)) 733f2e35a3aSmrg 734f2e35a3aSmrg#define TMODE(ind,var) \ 735f2e35a3aSmrg if (ttyModes[ind].set) \ 736f2e35a3aSmrg var = (cc_t) ttyModes[ind].value 737f2e35a3aSmrg 738d522f475Smrg#define validTtyChar(data, n) \ 739f2e35a3aSmrg (ttyChars[n].sysMode >= 0 && \ 740f2e35a3aSmrg ttyChars[n].sysMode < (int) XtNumber(data.c_cc)) 741d522f475Smrg 742d522f475Smrgstatic const struct { 743d522f475Smrg int sysMode; 744d522f475Smrg int myMode; 745d522f475Smrg int myDefault; 746f2e35a3aSmrg} ttyChars[] = { 747d522f475Smrg#ifdef VINTR 748d522f475Smrg { VINTR, XTTYMODE_intr, CINTR }, 749d522f475Smrg#endif 750d522f475Smrg#ifdef VQUIT 751d522f475Smrg { VQUIT, XTTYMODE_quit, CQUIT }, 752d522f475Smrg#endif 753d522f475Smrg#ifdef VERASE 754d522f475Smrg { VERASE, XTTYMODE_erase, CERASE }, 755d522f475Smrg#endif 756d522f475Smrg#ifdef VKILL 757d522f475Smrg { VKILL, XTTYMODE_kill, CKILL }, 758d522f475Smrg#endif 759d522f475Smrg#ifdef VEOF 760d522f475Smrg { VEOF, XTTYMODE_eof, CEOF }, 761d522f475Smrg#endif 762d522f475Smrg#ifdef VEOL 763d522f475Smrg { VEOL, XTTYMODE_eol, CEOL }, 764d522f475Smrg#endif 765d522f475Smrg#ifdef VSWTCH 766d522f475Smrg { VSWTCH, XTTYMODE_swtch, CNUL }, 767d522f475Smrg#endif 768d522f475Smrg#ifdef VSTART 769d522f475Smrg { VSTART, XTTYMODE_start, CSTART }, 770d522f475Smrg#endif 771d522f475Smrg#ifdef VSTOP 772d522f475Smrg { VSTOP, XTTYMODE_stop, CSTOP }, 773d522f475Smrg#endif 774d522f475Smrg#ifdef VSUSP 775d522f475Smrg { VSUSP, XTTYMODE_susp, CSUSP }, 776d522f475Smrg#endif 777d522f475Smrg#ifdef VDSUSP 778d522f475Smrg { VDSUSP, XTTYMODE_dsusp, CDSUSP }, 779d522f475Smrg#endif 780d522f475Smrg#ifdef VREPRINT 781d522f475Smrg { VREPRINT, XTTYMODE_rprnt, CREPRINT }, 782d522f475Smrg#endif 783d522f475Smrg#ifdef VDISCARD 784d522f475Smrg { VDISCARD, XTTYMODE_flush, CDISCARD }, 785d522f475Smrg#endif 786d522f475Smrg#ifdef VWERASE 787d522f475Smrg { VWERASE, XTTYMODE_weras, CWERASE }, 788d522f475Smrg#endif 789d522f475Smrg#ifdef VLNEXT 790d522f475Smrg { VLNEXT, XTTYMODE_lnext, CLNEXT }, 791d522f475Smrg#endif 792d522f475Smrg#ifdef VSTATUS 793d522f475Smrg { VSTATUS, XTTYMODE_status, CSTATUS }, 794d522f475Smrg#endif 795d522f475Smrg#ifdef VERASE2 796d522f475Smrg { VERASE2, XTTYMODE_erase2, CERASE2 }, 797d522f475Smrg#endif 798d522f475Smrg#ifdef VEOL2 799d522f475Smrg { VEOL2, XTTYMODE_eol2, CNUL }, 800d522f475Smrg#endif 801f2e35a3aSmrg { -1, XTTYMODE_tabs, TAB0 }, 802f2e35a3aSmrg { -1, XTTYMODE__tabs, TAB3 }, 803d522f475Smrg}; 804d522f475Smrg/* *INDENT-ON* */ 805d522f475Smrg 806f2e35a3aSmrgstatic int parse_tty_modes(char *s); 807d522f475Smrg 808d522f475Smrg#ifndef USE_UTEMPTER 809d522f475Smrg#ifdef USE_SYSV_UTMP 810d522f475Smrg#if (defined(AIXV3) && (OSMAJORVERSION < 4)) && !(defined(getutid)) 811d522f475Smrgextern struct utmp *getutid(); 812d522f475Smrg#endif /* AIXV3 */ 813d522f475Smrg 814d522f475Smrg#else /* not USE_SYSV_UTMP */ 815d522f475Smrgstatic char etc_utmp[] = UTMP_FILENAME; 816d522f475Smrg#endif /* USE_SYSV_UTMP */ 817d522f475Smrg 818d522f475Smrg#if defined(USE_LASTLOG) && defined(USE_STRUCT_LASTLOG) 819d522f475Smrgstatic char etc_lastlog[] = LASTLOG_FILENAME; 820d522f475Smrg#else 821d522f475Smrg#undef USE_LASTLOG 822d522f475Smrg#endif 823d522f475Smrg 824d522f475Smrg#ifdef WTMP 825d522f475Smrgstatic char etc_wtmp[] = WTMP_FILENAME; 826d522f475Smrg#endif 827d522f475Smrg#endif /* !USE_UTEMPTER */ 828d522f475Smrg 829d522f475Smrg/* 830d522f475Smrg * Some people with 4.3bsd /bin/login seem to like to use login -p -f user 831d522f475Smrg * to implement xterm -ls. They can turn on USE_LOGIN_DASH_P and turn off 832d522f475Smrg * WTMP and USE_LASTLOG. 833d522f475Smrg */ 834d522f475Smrg#ifdef USE_LOGIN_DASH_P 835d522f475Smrg#ifndef LOGIN_FILENAME 836d522f475Smrg#define LOGIN_FILENAME "/bin/login" 837d522f475Smrg#endif 838d522f475Smrgstatic char bin_login[] = LOGIN_FILENAME; 839d522f475Smrg#endif 840d522f475Smrg 84101037d57Smrgstatic char noPassedPty[2]; 84201037d57Smrgstatic char *passedPty = noPassedPty; /* name if pty if slave */ 843d522f475Smrg 844d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 845d522f475Smrgstatic int Console; 846d522f475Smrg#include <X11/Xmu/SysUtil.h> /* XmuGetHostname */ 847d522f475Smrg#define MIT_CONSOLE_LEN 12 848d522f475Smrg#define MIT_CONSOLE "MIT_CONSOLE_" 849d522f475Smrgstatic char mit_console_name[255 + MIT_CONSOLE_LEN + 1] = MIT_CONSOLE; 850d522f475Smrgstatic Atom mit_console; 851d522f475Smrg#endif /* TIOCCONS */ 852d522f475Smrg 853d522f475Smrg#ifndef USE_SYSV_UTMP 854d522f475Smrgstatic int tslot; 855d522f475Smrg#endif /* USE_SYSV_UTMP */ 856d522f475Smrgstatic sigjmp_buf env; 857d522f475Smrg 858d522f475Smrg#define SetUtmpHost(dst, screen) \ 859d522f475Smrg { \ 860d522f475Smrg char host[sizeof(dst) + 1]; \ 861f2e35a3aSmrg strncpy(host, DisplayString(screen->display), sizeof(host) - 1); \ 862f2e35a3aSmrg host[sizeof(dst)] = '\0'; \ 863d522f475Smrg TRACE(("DisplayString(%s)\n", host)); \ 864d522f475Smrg if (!resource.utmpDisplayId) { \ 865d522f475Smrg char *endptr = strrchr(host, ':'); \ 866d522f475Smrg if (endptr) { \ 867d522f475Smrg TRACE(("trimming display-id '%s'\n", host)); \ 868d522f475Smrg *endptr = '\0'; \ 869d522f475Smrg } \ 870d522f475Smrg } \ 871894e0ac8Smrg copy_filled(dst, host, sizeof(dst)); \ 872d522f475Smrg } 873d522f475Smrg 874d522f475Smrg#ifdef HAVE_UTMP_UT_SYSLEN 875d522f475Smrg# define SetUtmpSysLen(utmp) \ 876d522f475Smrg { \ 877d522f475Smrg utmp.ut_host[sizeof(utmp.ut_host)-1] = '\0'; \ 878f2e35a3aSmrg utmp.ut_syslen = (short) ((int) strlen(utmp.ut_host) + 1); \ 879d522f475Smrg } 880d522f475Smrg#endif 881d522f475Smrg 882d522f475Smrg/* used by VT (charproc.c) */ 883d522f475Smrg 884d522f475Smrgstatic XtResource application_resources[] = 885d522f475Smrg{ 88604b94745Smrg Sres(XtNiconGeometry, XtCIconGeometry, icon_geometry, NULL), 887d522f475Smrg Sres(XtNtitle, XtCTitle, title, NULL), 8880bd37d32Smrg Sres(XtNiconHint, XtCIconHint, icon_hint, NULL), 889d522f475Smrg Sres(XtNiconName, XtCIconName, icon_name, NULL), 89004b94745Smrg Sres(XtNtermName, XtCTermName, term_name, NULL), 89104b94745Smrg Sres(XtNttyModes, XtCTtyModes, tty_modes, NULL), 89204b94745Smrg Sres(XtNvalidShells, XtCValidShells, valid_shells, NULL), 89304b94745Smrg Bres(XtNhold, XtCHold, hold_screen, False), 89404b94745Smrg Bres(XtNutmpInhibit, XtCUtmpInhibit, utmpInhibit, False), 89504b94745Smrg Bres(XtNutmpDisplayId, XtCUtmpDisplayId, utmpDisplayId, True), 89604b94745Smrg Bres(XtNmessages, XtCMessages, messages, True), 89704b94745Smrg Ires(XtNminBufSize, XtCMinBufSize, minBufSize, 4096), 89804b94745Smrg Ires(XtNmaxBufSize, XtCMaxBufSize, maxBufSize, 32768), 89904b94745Smrg Sres(XtNmenuLocale, XtCMenuLocale, menuLocale, DEF_MENU_LOCALE), 90004b94745Smrg Sres(XtNomitTranslation, XtCOmitTranslation, omitTranslation, NULL), 90104b94745Smrg Sres(XtNkeyboardType, XtCKeyboardType, keyboardType, "unknown"), 902ad37e533Smrg#ifdef HAVE_LIB_XCURSOR 90304b94745Smrg Sres(XtNcursorTheme, XtCCursorTheme, cursorTheme, "none"), 904ad37e533Smrg#endif 905e39b573cSmrg#if OPT_PRINT_ON_EXIT 90604b94745Smrg Ires(XtNprintModeImmediate, XtCPrintModeImmediate, printModeNow, 0), 90704b94745Smrg Ires(XtNprintOptsImmediate, XtCPrintOptsImmediate, printOptsNow, 9), 90804b94745Smrg Sres(XtNprintFileImmediate, XtCPrintFileImmediate, printFileNow, NULL), 90904b94745Smrg Ires(XtNprintModeOnXError, XtCPrintModeOnXError, printModeOnXError, 0), 91004b94745Smrg Ires(XtNprintOptsOnXError, XtCPrintOptsOnXError, printOptsOnXError, 9), 91104b94745Smrg Sres(XtNprintFileOnXError, XtCPrintFileOnXError, printFileOnXError, NULL), 912e39b573cSmrg#endif 913d522f475Smrg#if OPT_SUNPC_KBD 91404b94745Smrg Bres(XtNsunKeyboard, XtCSunKeyboard, sunKeyboard, False), 915d522f475Smrg#endif 916d522f475Smrg#if OPT_HP_FUNC_KEYS 91704b94745Smrg Bres(XtNhpFunctionKeys, XtCHpFunctionKeys, hpFunctionKeys, False), 918d522f475Smrg#endif 919d522f475Smrg#if OPT_SCO_FUNC_KEYS 92004b94745Smrg Bres(XtNscoFunctionKeys, XtCScoFunctionKeys, scoFunctionKeys, False), 921d522f475Smrg#endif 922d522f475Smrg#if OPT_SUN_FUNC_KEYS 92304b94745Smrg Bres(XtNsunFunctionKeys, XtCSunFunctionKeys, sunFunctionKeys, False), 924d522f475Smrg#endif 925d522f475Smrg#if OPT_TCAP_FKEYS 92604b94745Smrg Bres(XtNtcapFunctionKeys, XtCTcapFunctionKeys, termcapKeys, False), 927d522f475Smrg#endif 928d522f475Smrg#if OPT_INITIAL_ERASE 92904b94745Smrg Bres(XtNptyInitialErase, XtCPtyInitialErase, ptyInitialErase, DEF_INITIAL_ERASE), 93004b94745Smrg Bres(XtNbackarrowKeyIsErase, XtCBackarrowKeyIsErase, backarrow_is_erase, DEF_BACKARO_ERASE), 931d522f475Smrg#endif 93204b94745Smrg Bres(XtNuseInsertMode, XtCUseInsertMode, useInsertMode, False), 933d522f475Smrg#if OPT_ZICONBEEP 93404b94745Smrg Ires(XtNzIconBeep, XtCZIconBeep, zIconBeep, 0), 93504b94745Smrg Sres(XtNzIconTitleFormat, XtCZIconTitleFormat, zIconFormat, "*** %s"), 936d522f475Smrg#endif 937d522f475Smrg#if OPT_PTY_HANDSHAKE 93804b94745Smrg Bres(XtNwaitForMap, XtCWaitForMap, wait_for_map, False), 93904b94745Smrg Bres(XtNptyHandshake, XtCPtyHandshake, ptyHandshake, True), 94004b94745Smrg Bres(XtNptySttySize, XtCPtySttySize, ptySttySize, DEF_PTY_STTY_SIZE), 941d522f475Smrg#endif 942913cc679Smrg#if OPT_REPORT_CCLASS 94304b94745Smrg Bres(XtNreportCClass, XtCReportCClass, reportCClass, False), 944913cc679Smrg#endif 945e0a2b6dfSmrg#if OPT_REPORT_COLORS 94604b94745Smrg Bres(XtNreportColors, XtCReportColors, reportColors, False), 947e0a2b6dfSmrg#endif 948e0a2b6dfSmrg#if OPT_REPORT_FONTS 94904b94745Smrg Bres(XtNreportFonts, XtCReportFonts, reportFonts, False), 950e0a2b6dfSmrg#endif 951f2e35a3aSmrg#if OPT_REPORT_ICONS 95204b94745Smrg Bres(XtNreportIcons, XtCReportIcons, reportIcons, False), 953f2e35a3aSmrg#endif 954f2e35a3aSmrg#if OPT_XRES_QUERY 95504b94745Smrg Bres(XtNreportXRes, XtCReportXRes, reportXRes, False), 956f2e35a3aSmrg#endif 957d522f475Smrg#if OPT_SAME_NAME 95804b94745Smrg Bres(XtNsameName, XtCSameName, sameName, True), 959d522f475Smrg#endif 960d522f475Smrg#if OPT_SESSION_MGT 96104b94745Smrg Bres(XtNsessionMgt, XtCSessionMgt, sessionMgt, True), 962d522f475Smrg#endif 963d522f475Smrg#if OPT_TOOLBAR 964d522f475Smrg Bres(XtNtoolBar, XtCToolBar, toolBar, True), 965d522f475Smrg#endif 966956cc18dSsnj#if OPT_MAXIMIZE 967956cc18dSsnj Bres(XtNmaximized, XtCMaximized, maximized, False), 968a1f3da82Smrg Sres(XtNfullscreen, XtCFullscreen, fullscreen_s, "off"), 969956cc18dSsnj#endif 970f2e35a3aSmrg#if USE_DOUBLE_BUFFER 971f2e35a3aSmrg Bres(XtNbuffered, XtCBuffered, buffered, DEF_DOUBLE_BUFFER), 972f2e35a3aSmrg Ires(XtNbufferedFPS, XtCBufferedFPS, buffered_fps, 40), 973f2e35a3aSmrg#endif 974d522f475Smrg}; 975d522f475Smrg 97620d2c4d2Smrgstatic String fallback_resources[] = 977d522f475Smrg{ 978e39b573cSmrg#if OPT_TOOLBAR 979e39b573cSmrg "*toolBar: false", 980e39b573cSmrg#endif 981d522f475Smrg "*SimpleMenu*menuLabel.vertSpace: 100", 982d522f475Smrg "*SimpleMenu*HorizontalMargins: 16", 983d522f475Smrg "*SimpleMenu*Sme.height: 16", 984d522f475Smrg "*SimpleMenu*Cursor: left_ptr", 985d522f475Smrg "*mainMenu.Label: Main Options (no app-defaults)", 986d522f475Smrg "*vtMenu.Label: VT Options (no app-defaults)", 987d522f475Smrg "*fontMenu.Label: VT Fonts (no app-defaults)", 988d522f475Smrg#if OPT_TEK4014 989d522f475Smrg "*tekMenu.Label: Tek Options (no app-defaults)", 990d522f475Smrg#endif 991d522f475Smrg NULL 992d522f475Smrg}; 993d522f475Smrg 994d522f475Smrg/* Command line options table. Only resources are entered here...there is a 995d522f475Smrg pass over the remaining options after XrmParseCommand is let loose. */ 996d522f475Smrg/* *INDENT-OFF* */ 997f2e35a3aSmrg#define DATA(option,pattern,type,value) { (char *) option, (char *) pattern, type, (XPointer) value } 99804b94745Smrg#define OPTS(option,pattern_type,value) { (char *) option, (char *) pattern_type, (XPointer) value } 99904b94745Smrg#define UP_ARG(name) "."name, XrmoptionSepArg 100004b94745Smrg#define MY_ARG(name) "*"name, XrmoptionSepArg 100104b94745Smrg#define VT_ARG(name) "*vt100."name, XrmoptionSepArg 100204b94745Smrg#define NO_ARG(name) "*"name, XrmoptionNoArg 1003d522f475Smrgstatic XrmOptionDescRec optionDescList[] = { 100404b94745SmrgOPTS("-geometry", VT_ARG(XtNgeometry), NULL), 100504b94745SmrgOPTS("-132", NO_ARG(XtNc132), "on"), 100604b94745SmrgOPTS("+132", NO_ARG(XtNc132), "off"), 100704b94745SmrgOPTS("-ah", NO_ARG(XtNalwaysHighlight), "on"), 100804b94745SmrgOPTS("+ah", NO_ARG(XtNalwaysHighlight), "off"), 100904b94745SmrgOPTS("-aw", NO_ARG(XtNautoWrap), "on"), 101004b94745SmrgOPTS("+aw", NO_ARG(XtNautoWrap), "off"), 1011d522f475Smrg#ifndef NO_ACTIVE_ICON 101204b94745SmrgOPTS("-ai", NO_ARG(XtNactiveIcon), "off"), 101304b94745SmrgOPTS("+ai", NO_ARG(XtNactiveIcon), "on"), 1014d522f475Smrg#endif /* NO_ACTIVE_ICON */ 101504b94745SmrgOPTS("-b", MY_ARG(XtNinternalBorder), NULL), 101604b94745SmrgOPTS("-barc", NO_ARG(XtNcursorBar), "on"), 101704b94745SmrgOPTS("+barc", NO_ARG(XtNcursorBar), "off"), 101804b94745SmrgOPTS("-bc", NO_ARG(XtNcursorBlink), "on"), 101904b94745SmrgOPTS("+bc", NO_ARG(XtNcursorBlink), "off"), 102004b94745SmrgOPTS("-bcf", MY_ARG(XtNcursorOffTime), NULL), 102104b94745SmrgOPTS("-bcn", MY_ARG(XtNcursorOnTime), NULL), 102204b94745SmrgOPTS("-bdc", NO_ARG(XtNcolorBDMode), "off"), 102304b94745SmrgOPTS("+bdc", NO_ARG(XtNcolorBDMode), "on"), 102404b94745SmrgOPTS("-cb", NO_ARG(XtNcutToBeginningOfLine), "off"), 102504b94745SmrgOPTS("+cb", NO_ARG(XtNcutToBeginningOfLine), "on"), 102604b94745SmrgOPTS("-cc", MY_ARG(XtNcharClass), NULL), 102704b94745SmrgOPTS("-cm", NO_ARG(XtNcolorMode), "off"), 102804b94745SmrgOPTS("+cm", NO_ARG(XtNcolorMode), "on"), 102904b94745SmrgOPTS("-cn", NO_ARG(XtNcutNewline), "off"), 103004b94745SmrgOPTS("+cn", NO_ARG(XtNcutNewline), "on"), 103104b94745SmrgOPTS("-cr", MY_ARG(XtNcursorColor), NULL), 103204b94745SmrgOPTS("-cu", NO_ARG(XtNcurses), "on"), 103304b94745SmrgOPTS("+cu", NO_ARG(XtNcurses), "off"), 103404b94745SmrgOPTS("-dc", NO_ARG(XtNdynamicColors), "off"), 103504b94745SmrgOPTS("+dc", NO_ARG(XtNdynamicColors), "on"), 103604b94745SmrgOPTS("-fb", MY_ARG(XtNboldFont), NULL), 103704b94745SmrgOPTS("-fbb", NO_ARG(XtNfreeBoldBox), "off"), 103804b94745SmrgOPTS("+fbb", NO_ARG(XtNfreeBoldBox), "on"), 103904b94745SmrgOPTS("-fbx", NO_ARG(XtNforceBoxChars), "off"), 104004b94745SmrgOPTS("+fbx", NO_ARG(XtNforceBoxChars), "on"), 104104b94745SmrgOPTS("-fc", MY_ARG(XtNinitialFont), NULL), 1042d522f475Smrg#ifndef NO_ACTIVE_ICON 104304b94745SmrgOPTS("-fi", MY_ARG(XtNiconFont), NULL), 1044d522f475Smrg#endif /* NO_ACTIVE_ICON */ 1045d522f475Smrg#if OPT_RENDERFONT 104604b94745SmrgOPTS("-fa", MY_ARG(XtNfaceName), NULL), 104704b94745SmrgOPTS("-fd", MY_ARG(XtNfaceNameDoublesize), NULL), 104804b94745SmrgOPTS("-fs", MY_ARG(XtNfaceSize), NULL), 1049d522f475Smrg#endif 105001037d57Smrg#if OPT_WIDE_ATTRS && OPT_ISO_COLORS 105104b94745SmrgOPTS("-itc", NO_ARG(XtNcolorITMode), "off"), 105204b94745SmrgOPTS("+itc", NO_ARG(XtNcolorITMode), "on"), 105301037d57Smrg#endif 1054d522f475Smrg#if OPT_WIDE_CHARS 105504b94745SmrgOPTS("-fw", MY_ARG(XtNwideFont), NULL), 105604b94745SmrgOPTS("-fwb", MY_ARG(XtNwideBoldFont), NULL), 1057d522f475Smrg#endif 1058d522f475Smrg#if OPT_INPUT_METHOD 105904b94745SmrgOPTS("-fx", MY_ARG(XtNximFont), NULL), 1060d522f475Smrg#endif 1061d522f475Smrg#if OPT_HIGHLIGHT_COLOR 106204b94745SmrgOPTS("-hc", MY_ARG(XtNhighlightColor), NULL), 106304b94745SmrgOPTS("-hm", NO_ARG(XtNhighlightColorMode), "on"), 106404b94745SmrgOPTS("+hm", NO_ARG(XtNhighlightColorMode), "off"), 106504b94745SmrgOPTS("-selfg", MY_ARG(XtNhighlightTextColor), NULL), 106604b94745SmrgOPTS("-selbg", MY_ARG(XtNhighlightColor), NULL), 1067d522f475Smrg#endif 1068d522f475Smrg#if OPT_HP_FUNC_KEYS 106904b94745SmrgOPTS("-hf", NO_ARG(XtNhpFunctionKeys), "on"), 107004b94745SmrgOPTS("+hf", NO_ARG(XtNhpFunctionKeys), "off"), 1071d522f475Smrg#endif 107204b94745SmrgOPTS("-hold", NO_ARG(XtNhold), "on"), 107304b94745SmrgOPTS("+hold", NO_ARG(XtNhold), "off"), 1074d522f475Smrg#if OPT_INITIAL_ERASE 107504b94745SmrgOPTS("-ie", NO_ARG(XtNptyInitialErase), "on"), 107604b94745SmrgOPTS("+ie", NO_ARG(XtNptyInitialErase), "off"), 1077d522f475Smrg#endif 107804b94745SmrgOPTS("-j", NO_ARG(XtNjumpScroll), "on"), 107904b94745SmrgOPTS("+j", NO_ARG(XtNjumpScroll), "off"), 108004b94745SmrgOPTS("-jf", NO_ARG(XtNfastScroll), "on"), 108104b94745SmrgOPTS("+jf", NO_ARG(XtNfastScroll), "off"), 1082d522f475Smrg#if OPT_C1_PRINT 108304b94745SmrgOPTS("-k8", NO_ARG(XtNallowC1Printable), "on"), 108404b94745SmrgOPTS("+k8", NO_ARG(XtNallowC1Printable), "off"), 1085d522f475Smrg#endif 108604b94745SmrgOPTS("-kt", MY_ARG(XtNkeyboardType), NULL), 1087d522f475Smrg/* parse logging options anyway for compatibility */ 108804b94745SmrgOPTS("-l", NO_ARG(XtNlogging), "on"), 108904b94745SmrgOPTS("+l", NO_ARG(XtNlogging), "off"), 109004b94745SmrgOPTS("-lf", MY_ARG(XtNlogFile), NULL), 109104b94745SmrgOPTS("-ls", NO_ARG(XtNloginShell), "on"), 109204b94745SmrgOPTS("+ls", NO_ARG(XtNloginShell), "off"), 109304b94745SmrgOPTS("-mb", NO_ARG(XtNmarginBell), "on"), 109404b94745SmrgOPTS("+mb", NO_ARG(XtNmarginBell), "off"), 109504b94745SmrgOPTS("-mc", MY_ARG(XtNmultiClickTime), NULL), 109604b94745SmrgOPTS("-mesg", NO_ARG(XtNmessages), "off"), 109704b94745SmrgOPTS("+mesg", NO_ARG(XtNmessages), "on"), 109804b94745SmrgOPTS("-ms", MY_ARG(XtNpointerColor), NULL), 109904b94745SmrgOPTS("-nb", MY_ARG(XtNnMarginBell), NULL), 110004b94745SmrgOPTS("-nul", NO_ARG(XtNunderLine), "off"), 110104b94745SmrgOPTS("+nul", NO_ARG(XtNunderLine), "on"), 110204b94745SmrgOPTS("-pc", NO_ARG(XtNboldColors), "on"), 110304b94745SmrgOPTS("+pc", NO_ARG(XtNboldColors), "off"), 110404b94745SmrgOPTS("-pf", MY_ARG(XtNpointerFont), NULL), 110504b94745SmrgOPTS("-rw", NO_ARG(XtNreverseWrap), "on"), 110604b94745SmrgOPTS("+rw", NO_ARG(XtNreverseWrap), "off"), 110704b94745SmrgOPTS("-s", NO_ARG(XtNmultiScroll), "on"), 110804b94745SmrgOPTS("+s", NO_ARG(XtNmultiScroll), "off"), 110904b94745SmrgOPTS("-sb", NO_ARG(XtNscrollBar), "on"), 111004b94745SmrgOPTS("+sb", NO_ARG(XtNscrollBar), "off"), 1111913cc679Smrg#if OPT_REPORT_CCLASS 111204b94745SmrgOPTS("-report-charclass", NO_ARG(XtNreportCClass), "on"), 1113913cc679Smrg#endif 1114e0a2b6dfSmrg#if OPT_REPORT_COLORS 111504b94745SmrgOPTS("-report-colors", NO_ARG(XtNreportColors), "on"), 1116f2e35a3aSmrg#endif 1117f2e35a3aSmrg#if OPT_REPORT_ICONS 111804b94745SmrgOPTS("-report-icons", NO_ARG(XtNreportIcons), "on"), 1119e0a2b6dfSmrg#endif 1120e0a2b6dfSmrg#if OPT_REPORT_FONTS 112104b94745SmrgOPTS("-report-fonts", NO_ARG(XtNreportFonts), "on"), 1122f2e35a3aSmrg#endif 1123f2e35a3aSmrg#if OPT_XRES_QUERY 112404b94745SmrgOPTS("-report-xres", NO_ARG(XtNreportXRes), "on"), 1125e0a2b6dfSmrg#endif 1126d522f475Smrg#ifdef SCROLLBAR_RIGHT 112704b94745SmrgOPTS("-leftbar", NO_ARG(XtNrightScrollBar), "off"), 112804b94745SmrgOPTS("-rightbar", NO_ARG(XtNrightScrollBar), "on"), 112904b94745Smrg#endif 113004b94745SmrgOPTS("-rvc", NO_ARG(XtNcolorRVMode), "off"), 113104b94745SmrgOPTS("+rvc", NO_ARG(XtNcolorRVMode), "on"), 113204b94745SmrgOPTS("-sf", NO_ARG(XtNsunFunctionKeys), "on"), 113304b94745SmrgOPTS("+sf", NO_ARG(XtNsunFunctionKeys), "off"), 113404b94745SmrgOPTS("-sh", MY_ARG(XtNscaleHeight), NULL), 113504b94745SmrgOPTS("-si", NO_ARG(XtNscrollTtyOutput), "off"), 113604b94745SmrgOPTS("+si", NO_ARG(XtNscrollTtyOutput), "on"), 113704b94745SmrgOPTS("-sk", NO_ARG(XtNscrollKey), "on"), 113804b94745SmrgOPTS("+sk", NO_ARG(XtNscrollKey), "off"), 113904b94745SmrgOPTS("-sl", MY_ARG(XtNsaveLines), NULL), 1140d522f475Smrg#if OPT_SUNPC_KBD 114104b94745SmrgOPTS("-sp", NO_ARG(XtNsunKeyboard), "on"), 114204b94745SmrgOPTS("+sp", NO_ARG(XtNsunKeyboard), "off"), 1143d522f475Smrg#endif 1144d522f475Smrg#if OPT_TEK4014 114504b94745SmrgOPTS("-t", NO_ARG(XtNtekStartup), "on"), 114604b94745SmrgOPTS("+t", NO_ARG(XtNtekStartup), "off"), 1147d522f475Smrg#endif 114804b94745SmrgOPTS("-ti", MY_ARG(XtNdecTerminalID), NULL), 114904b94745SmrgOPTS("-tm", MY_ARG(XtNttyModes), NULL), 115004b94745SmrgOPTS("-tn", MY_ARG(XtNtermName), NULL), 1151d522f475Smrg#if OPT_WIDE_CHARS 115204b94745SmrgOPTS("-u8", NO_ARG(XtNutf8), "2"), 115304b94745SmrgOPTS("+u8", NO_ARG(XtNutf8), "0"), 1154d522f475Smrg#endif 1155d522f475Smrg#if OPT_LUIT_PROG 115604b94745SmrgOPTS("-lc", NO_ARG(XtNlocale), "on"), 115704b94745SmrgOPTS("+lc", NO_ARG(XtNlocale), "off"), 115804b94745SmrgOPTS("-lcc", MY_ARG(XtNlocaleFilter), NULL), 115904b94745SmrgOPTS("-en", MY_ARG(XtNlocale), NULL), 116004b94745Smrg#endif 116104b94745SmrgOPTS("-uc", NO_ARG(XtNcursorUnderLine), "on"), 116204b94745SmrgOPTS("+uc", NO_ARG(XtNcursorUnderLine), "off"), 116304b94745SmrgOPTS("-ulc", NO_ARG(XtNcolorULMode), "off"), 116404b94745SmrgOPTS("+ulc", NO_ARG(XtNcolorULMode), "on"), 116504b94745SmrgOPTS("-ulit", NO_ARG(XtNitalicULMode), "off"), 116604b94745SmrgOPTS("+ulit", NO_ARG(XtNitalicULMode), "on"), 116704b94745SmrgOPTS("-ut", NO_ARG(XtNutmpInhibit), "on"), 116804b94745SmrgOPTS("+ut", NO_ARG(XtNutmpInhibit), "off"), 116904b94745SmrgOPTS("-im", NO_ARG(XtNuseInsertMode), "on"), 117004b94745SmrgOPTS("+im", NO_ARG(XtNuseInsertMode), "off"), 117104b94745SmrgOPTS("-vb", NO_ARG(XtNvisualBell), "on"), 117204b94745SmrgOPTS("+vb", NO_ARG(XtNvisualBell), "off"), 117304b94745SmrgOPTS("-pob", NO_ARG(XtNpopOnBell), "on"), 117404b94745SmrgOPTS("+pob", NO_ARG(XtNpopOnBell), "off"), 1175d522f475Smrg#if OPT_WIDE_CHARS 117604b94745SmrgOPTS("-wc", NO_ARG(XtNwideChars), "on"), 117704b94745SmrgOPTS("+wc", NO_ARG(XtNwideChars), "off"), 117804b94745SmrgOPTS("-mk_width", NO_ARG(XtNmkWidth), "on"), 117904b94745SmrgOPTS("+mk_width", NO_ARG(XtNmkWidth), "off"), 118004b94745SmrgOPTS("-cjk_width", NO_ARG(XtNcjkWidth), "on"), 118104b94745SmrgOPTS("+cjk_width", NO_ARG(XtNcjkWidth), "off"), 118204b94745Smrg#endif 118304b94745SmrgOPTS("-wf", NO_ARG(XtNwaitForMap), "on"), 118404b94745SmrgOPTS("+wf", NO_ARG(XtNwaitForMap), "off"), 1185d522f475Smrg#if OPT_ZICONBEEP 118604b94745SmrgOPTS("-ziconbeep", MY_ARG(XtNzIconBeep), NULL), 1187d522f475Smrg#endif 1188d522f475Smrg#if OPT_SAME_NAME 118904b94745SmrgOPTS("-samename", NO_ARG(XtNsameName), "on"), 119004b94745SmrgOPTS("+samename", NO_ARG(XtNsameName), "off"), 1191d522f475Smrg#endif 1192d522f475Smrg#if OPT_SESSION_MGT 119304b94745SmrgOPTS("-sm", NO_ARG(XtNsessionMgt), "on"), 119404b94745SmrgOPTS("+sm", NO_ARG(XtNsessionMgt), "off"), 1195d522f475Smrg#endif 1196d522f475Smrg#if OPT_TOOLBAR 119704b94745SmrgOPTS("-tb", NO_ARG(XtNtoolBar), "on"), 119804b94745SmrgOPTS("+tb", NO_ARG(XtNtoolBar), "off"), 1199d522f475Smrg#endif 1200956cc18dSsnj#if OPT_MAXIMIZE 120104b94745SmrgOPTS("-maximized", NO_ARG(XtNmaximized), "on"), 120204b94745SmrgOPTS("+maximized", NO_ARG(XtNmaximized), "off"), 120304b94745SmrgOPTS("-fullscreen", NO_ARG(XtNfullscreen), "on"), 120404b94745SmrgOPTS("+fullscreen", NO_ARG(XtNfullscreen), "off"), 1205956cc18dSsnj#endif 1206d522f475Smrg/* options that we process ourselves */ 1207f2e35a3aSmrgDATA("-help", NULL, XrmoptionSkipNArgs, NULL), 1208f2e35a3aSmrgDATA("-version", NULL, XrmoptionSkipNArgs, NULL), 1209f2e35a3aSmrgDATA("-baudrate", NULL, XrmoptionSkipArg, NULL), 1210f2e35a3aSmrgDATA("-class", NULL, XrmoptionSkipArg, NULL), 1211f2e35a3aSmrgDATA("-e", NULL, XrmoptionSkipLine, NULL), 1212f2e35a3aSmrgDATA("-into", NULL, XrmoptionSkipArg, NULL), 1213d522f475Smrg/* bogus old compatibility stuff for which there are 1214d522f475Smrg standard XtOpenApplication options now */ 1215f2e35a3aSmrgDATA("%", "*tekGeometry", XrmoptionStickyArg, NULL), 121604b94745SmrgDATA("#", ".iconGeometry", XrmoptionStickyArg, NULL), 121704b94745SmrgOPTS("-T", UP_ARG(XtNtitle), NULL), 121804b94745SmrgOPTS("-n", MY_ARG(XtNiconName), NULL), 121904b94745SmrgOPTS("-r", NO_ARG(XtNreverseVideo), "on"), 122004b94745SmrgOPTS("+r", NO_ARG(XtNreverseVideo), "off"), 122104b94745SmrgOPTS("-rv", NO_ARG(XtNreverseVideo), "on"), 122204b94745SmrgOPTS("+rv", NO_ARG(XtNreverseVideo), "off"), 122304b94745SmrgOPTS("-w", UP_ARG(XtNborderWidth), NULL), 1224f2e35a3aSmrg#undef DATA 1225d522f475Smrg}; 1226d522f475Smrg 1227d522f475Smrgstatic OptionHelp xtermOptions[] = { 1228d522f475Smrg{ "-version", "print the version number" }, 1229d522f475Smrg{ "-help", "print out this message" }, 1230d522f475Smrg{ "-display displayname", "X server to contact" }, 1231d522f475Smrg{ "-geometry geom", "size (in characters) and position" }, 1232d522f475Smrg{ "-/+rv", "turn on/off reverse video" }, 1233d522f475Smrg{ "-bg color", "background color" }, 1234d522f475Smrg{ "-fg color", "foreground color" }, 1235d522f475Smrg{ "-bd color", "border color" }, 1236d522f475Smrg{ "-bw number", "border width in pixels" }, 1237d522f475Smrg{ "-fn fontname", "normal text font" }, 1238d522f475Smrg{ "-fb fontname", "bold text font" }, 1239f2e35a3aSmrg{ "-fc fontmenu", "start with named fontmenu choice" }, 1240d522f475Smrg{ "-/+fbb", "turn on/off normal/bold font comparison inhibit"}, 1241d522f475Smrg{ "-/+fbx", "turn off/on linedrawing characters"}, 1242d522f475Smrg#if OPT_RENDERFONT 1243d522f475Smrg{ "-fa pattern", "FreeType font-selection pattern" }, 1244d522f475Smrg{ "-fd pattern", "FreeType Doublesize font-selection pattern" }, 1245d522f475Smrg{ "-fs size", "FreeType font-size" }, 1246d522f475Smrg#endif 1247d522f475Smrg#if OPT_WIDE_CHARS 1248d522f475Smrg{ "-fw fontname", "doublewidth text font" }, 1249d522f475Smrg{ "-fwb fontname", "doublewidth bold text font" }, 1250d522f475Smrg#endif 1251d522f475Smrg#if OPT_INPUT_METHOD 1252d522f475Smrg{ "-fx fontname", "XIM fontset" }, 1253d522f475Smrg#endif 1254d522f475Smrg{ "-iconic", "start iconic" }, 1255d522f475Smrg{ "-name string", "client instance, icon, and title strings" }, 12562e4f8982Smrg{ "-baudrate rate", "set line-speed (default 38400)" }, 1257d522f475Smrg{ "-class string", "class string (XTerm)" }, 1258d522f475Smrg{ "-title string", "title string" }, 1259d522f475Smrg{ "-xrm resourcestring", "additional resource specifications" }, 1260d522f475Smrg{ "-/+132", "turn on/off 80/132 column switching" }, 1261d522f475Smrg{ "-/+ah", "turn on/off always highlight" }, 1262d522f475Smrg#ifndef NO_ACTIVE_ICON 1263d522f475Smrg{ "-/+ai", "turn off/on active icon" }, 1264d522f475Smrg{ "-fi fontname", "icon font for active icon" }, 1265d522f475Smrg#endif /* NO_ACTIVE_ICON */ 1266d522f475Smrg{ "-b number", "internal border in pixels" }, 1267d522f475Smrg{ "-/+bc", "turn on/off text cursor blinking" }, 1268d522f475Smrg{ "-bcf milliseconds", "time text cursor is off when blinking"}, 1269d522f475Smrg{ "-bcn milliseconds", "time text cursor is on when blinking"}, 1270d522f475Smrg{ "-/+bdc", "turn off/on display of bold as color"}, 1271d522f475Smrg{ "-/+cb", "turn on/off cut-to-beginning-of-line inhibit" }, 1272d522f475Smrg{ "-cc classrange", "specify additional character classes" }, 1273d522f475Smrg{ "-/+cm", "turn off/on ANSI color mode" }, 1274d522f475Smrg{ "-/+cn", "turn on/off cut newline inhibit" }, 1275f2e35a3aSmrg{ "-pf fontname", "cursor font for text area pointer" }, 1276d522f475Smrg{ "-cr color", "text cursor color" }, 1277d522f475Smrg{ "-/+cu", "turn on/off curses emulation" }, 1278d522f475Smrg{ "-/+dc", "turn off/on dynamic color selection" }, 1279d522f475Smrg#if OPT_HIGHLIGHT_COLOR 1280d522f475Smrg{ "-/+hm", "turn on/off selection-color override" }, 1281d522f475Smrg{ "-selbg color", "selection background color" }, 1282d522f475Smrg{ "-selfg color", "selection foreground color" }, 12830bd37d32Smrg/* -hc is deprecated, not shown in help message */ 1284d522f475Smrg#endif 1285d522f475Smrg#if OPT_HP_FUNC_KEYS 1286d522f475Smrg{ "-/+hf", "turn on/off HP Function Key escape codes" }, 1287d522f475Smrg#endif 1288d522f475Smrg{ "-/+hold", "turn on/off logic that retains window after exit" }, 1289d522f475Smrg#if OPT_INITIAL_ERASE 1290d522f475Smrg{ "-/+ie", "turn on/off initialization of 'erase' from pty" }, 1291d522f475Smrg#endif 1292d522f475Smrg{ "-/+im", "use insert mode for TERMCAP" }, 1293d522f475Smrg{ "-/+j", "turn on/off jump scroll" }, 1294d522f475Smrg#if OPT_C1_PRINT 1295d522f475Smrg{ "-/+k8", "turn on/off C1-printable classification"}, 1296d522f475Smrg#endif 1297d522f475Smrg{ "-kt keyboardtype", "set keyboard type:" KEYBOARD_TYPES }, 1298d522f475Smrg#ifdef ALLOWLOGGING 1299d522f475Smrg{ "-/+l", "turn on/off logging" }, 1300f2e35a3aSmrg{ "-lf filename", "logging filename (use '-' for standard out)" }, 1301d522f475Smrg#else 1302d522f475Smrg{ "-/+l", "turn on/off logging (not supported)" }, 1303d522f475Smrg{ "-lf filename", "logging filename (not supported)" }, 1304d522f475Smrg#endif 1305d522f475Smrg{ "-/+ls", "turn on/off login shell" }, 1306d522f475Smrg{ "-/+mb", "turn on/off margin bell" }, 1307d522f475Smrg{ "-mc milliseconds", "multiclick time in milliseconds" }, 1308d522f475Smrg{ "-/+mesg", "forbid/allow messages" }, 1309d522f475Smrg{ "-ms color", "pointer color" }, 1310d522f475Smrg{ "-nb number", "margin bell in characters from right end" }, 1311d522f475Smrg{ "-/+nul", "turn off/on display of underlining" }, 1312d522f475Smrg{ "-/+aw", "turn on/off auto wraparound" }, 1313d522f475Smrg{ "-/+pc", "turn on/off PC-style bold colors" }, 1314d522f475Smrg{ "-/+rw", "turn on/off reverse wraparound" }, 1315d522f475Smrg{ "-/+s", "turn on/off multiscroll" }, 1316d522f475Smrg{ "-/+sb", "turn on/off scrollbar" }, 1317913cc679Smrg#if OPT_REPORT_CCLASS 1318913cc679Smrg{"-report-charclass", "report \"charClass\" after initialization"}, 1319913cc679Smrg#endif 1320e0a2b6dfSmrg#if OPT_REPORT_COLORS 1321e0a2b6dfSmrg{ "-report-colors", "report colors as they are allocated" }, 1322e0a2b6dfSmrg#endif 1323e0a2b6dfSmrg#if OPT_REPORT_FONTS 1324e0a2b6dfSmrg{ "-report-fonts", "report fonts as loaded to stdout" }, 1325e0a2b6dfSmrg#endif 1326f2e35a3aSmrg#if OPT_REPORT_ICONS 132704b94745Smrg{ "-report-icons", "report title/icon updates" }, 1328f2e35a3aSmrg#endif 1329f2e35a3aSmrg#if OPT_XRES_QUERY 1330f2e35a3aSmrg{ "-report-xres", "report X resources for VT100 widget" }, 1331f2e35a3aSmrg#endif 1332d522f475Smrg#ifdef SCROLLBAR_RIGHT 1333d522f475Smrg{ "-rightbar", "force scrollbar right (default left)" }, 1334d522f475Smrg{ "-leftbar", "force scrollbar left" }, 1335d522f475Smrg#endif 1336d522f475Smrg{ "-/+rvc", "turn off/on display of reverse as color" }, 1337d522f475Smrg{ "-/+sf", "turn on/off Sun Function Key escape codes" }, 1338894e0ac8Smrg{ "-sh number", "scale line-height values by the given number" }, 1339d522f475Smrg{ "-/+si", "turn on/off scroll-on-tty-output inhibit" }, 1340d522f475Smrg{ "-/+sk", "turn on/off scroll-on-keypress" }, 1341d522f475Smrg{ "-sl number", "number of scrolled lines to save" }, 1342d522f475Smrg#if OPT_SUNPC_KBD 1343d522f475Smrg{ "-/+sp", "turn on/off Sun/PC Function/Keypad mapping" }, 1344d522f475Smrg#endif 1345d522f475Smrg#if OPT_TEK4014 1346d522f475Smrg{ "-/+t", "turn on/off Tek emulation window" }, 1347d522f475Smrg#endif 1348d522f475Smrg#if OPT_TOOLBAR 1349d522f475Smrg{ "-/+tb", "turn on/off toolbar" }, 1350d522f475Smrg#endif 1351d522f475Smrg{ "-ti termid", "terminal identifier" }, 1352d522f475Smrg{ "-tm string", "terminal mode keywords and characters" }, 1353d522f475Smrg{ "-tn name", "TERM environment variable name" }, 1354d522f475Smrg#if OPT_WIDE_CHARS 1355d522f475Smrg{ "-/+u8", "turn on/off UTF-8 mode (implies wide-characters)" }, 1356d522f475Smrg#endif 1357d522f475Smrg#if OPT_LUIT_PROG 1358d522f475Smrg{ "-/+lc", "turn on/off locale mode using luit" }, 1359d522f475Smrg{ "-lcc path", "filename of locale converter (" DEFLOCALEFILTER ")" }, 13600bd37d32Smrg/* -en is deprecated, not shown in help message */ 1361d522f475Smrg#endif 13622eaa94a1Schristos{ "-/+uc", "turn on/off underline cursor" }, 1363d522f475Smrg{ "-/+ulc", "turn off/on display of underline as color" }, 1364d522f475Smrg{ "-/+ulit", "turn off/on display of underline as italics" }, 1365d522f475Smrg#ifdef HAVE_UTMP 1366d522f475Smrg{ "-/+ut", "turn on/off utmp support" }, 1367d522f475Smrg#else 1368d522f475Smrg{ "-/+ut", "turn on/off utmp support (not available)" }, 1369d522f475Smrg#endif 1370d522f475Smrg{ "-/+vb", "turn on/off visual bell" }, 1371d522f475Smrg{ "-/+pob", "turn on/off pop on bell" }, 137201037d57Smrg#if OPT_WIDE_ATTRS && OPT_ISO_COLORS 137301037d57Smrg{ "-/+itc", "turn off/on display of italic as color"}, 137401037d57Smrg#endif 1375d522f475Smrg#if OPT_WIDE_CHARS 1376d522f475Smrg{ "-/+wc", "turn on/off wide-character mode" }, 1377d522f475Smrg{ "-/+mk_width", "turn on/off simple width convention" }, 1378d522f475Smrg{ "-/+cjk_width", "turn on/off legacy CJK width convention" }, 1379d522f475Smrg#endif 1380d522f475Smrg{ "-/+wf", "turn on/off wait for map before command exec" }, 1381d522f475Smrg{ "-e command args ...", "command to execute" }, 1382d522f475Smrg#if OPT_TEK4014 1383d522f475Smrg{ "%geom", "Tek window geometry" }, 1384d522f475Smrg#endif 1385d522f475Smrg{ "#geom", "icon window geometry" }, 1386d522f475Smrg{ "-T string", "title name for window" }, 1387d522f475Smrg{ "-n string", "icon name for window" }, 1388d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 1389d522f475Smrg{ "-C", "intercept console messages" }, 1390d522f475Smrg#else 1391d522f475Smrg{ "-C", "intercept console messages (not supported)" }, 1392d522f475Smrg#endif 1393d522f475Smrg{ "-Sccn", "slave mode on \"ttycc\", file descriptor \"n\"" }, 1394d522f475Smrg{ "-into windowId", "use the window id given to -into as the parent window rather than the default root window" }, 1395d522f475Smrg#if OPT_ZICONBEEP 1396d522f475Smrg{ "-ziconbeep percent", "beep and flag icon of window having hidden output" }, 1397d522f475Smrg#endif 1398d522f475Smrg#if OPT_SAME_NAME 1399d522f475Smrg{ "-/+samename", "turn on/off the no-flicker option for title and icon name" }, 1400d522f475Smrg#endif 1401d522f475Smrg#if OPT_SESSION_MGT 1402d522f475Smrg{ "-/+sm", "turn on/off the session-management support" }, 1403d522f475Smrg#endif 1404956cc18dSsnj#if OPT_MAXIMIZE 1405ad37e533Smrg{"-/+maximized", "turn on/off maximize on startup" }, 1406a1f3da82Smrg{"-/+fullscreen", "turn on/off fullscreen on startup" }, 1407956cc18dSsnj#endif 1408d522f475Smrg{ NULL, NULL }}; 1409d522f475Smrg/* *INDENT-ON* */ 1410d522f475Smrg 141104b94745Smrgstatic const char *const help_message[] = 1412d522f475Smrg{ 1413d522f475Smrg "Fonts should be fixed width and, if both normal and bold are specified, should", 1414d522f475Smrg "have the same size. If only a normal font is specified, it will be used for", 1415d522f475Smrg "both normal and bold text (by doing overstriking). The -e option, if given,", 1416d522f475Smrg "must appear at the end of the command line, otherwise the user's default shell", 1417d522f475Smrg "will be started. Options that start with a plus sign (+) restore the default.", 141804b94745Smrg NULL 141904b94745Smrg}; 142004b94745Smrg 142104b94745Smrgint 142204b94745SmrgxtermDisabledChar(void) 142304b94745Smrg{ 142404b94745Smrg int value = -1; 142504b94745Smrg#if defined(_POSIX_VDISABLE) && defined(HAVE_UNISTD_H) 142604b94745Smrg value = _POSIX_VDISABLE; 142704b94745Smrg#endif 142804b94745Smrg#if defined(_PC_VDISABLE) 142904b94745Smrg if (value == -1) { 143004b94745Smrg value = (int) fpathconf(0, _PC_VDISABLE); 143104b94745Smrg if (value == -1) { 143204b94745Smrg if (errno == 0) 143304b94745Smrg value = 0377; 143404b94745Smrg } 143504b94745Smrg } 143604b94745Smrg#elif defined(VDISABLE) 143704b94745Smrg if (value == -1) 143804b94745Smrg value = VDISABLE; 143904b94745Smrg#endif 144004b94745Smrg return value; 144104b94745Smrg} 144204b94745Smrg 144304b94745Smrg/* 144404b94745Smrg * Retrieve (possibly allocating) an atom from the server. Cache the result. 144504b94745Smrg */ 144604b94745SmrgAtom 144704b94745SmrgCachedInternAtom(Display *display, const char *name) 144804b94745Smrg{ 144904b94745Smrg /* 145004b94745Smrg * Aside from a couple of rarely used atoms, the others are all known. 145104b94745Smrg */ 145204b94745Smrg static const char *const known_atoms[] = 145304b94745Smrg { 145404b94745Smrg "FONT", 145504b94745Smrg "WM_CLASS", 145604b94745Smrg "WM_DELETE_WINDOW", 145704b94745Smrg "_NET_ACTIVE_WINDOW", 145804b94745Smrg "_NET_FRAME_EXTENTS", 145904b94745Smrg "_NET_FRAME_EXTENTS", 146004b94745Smrg "_NET_SUPPORTED", 146104b94745Smrg "_NET_SUPPORTING_WM_CHECK", 146204b94745Smrg "_NET_WM_ALLOWED_ACTIONS", 146304b94745Smrg "_NET_WM_ICON_NAME", 146404b94745Smrg "_NET_WM_NAME", 146504b94745Smrg "_NET_WM_PID", 146604b94745Smrg "_NET_WM_STATE", 146704b94745Smrg "_NET_WM_STATE_ADD", 146804b94745Smrg "_NET_WM_STATE_FULLSCREEN", 146904b94745Smrg "_NET_WM_STATE_HIDDEN", 147004b94745Smrg "_NET_WM_STATE_MAXIMIZED_HORZ", 147104b94745Smrg "_NET_WM_STATE_MAXIMIZED_VERT", 147204b94745Smrg "_NET_WM_STATE_REMOVE", 147304b94745Smrg "_WIN_SUPPORTING_WM_CHECK", 147404b94745Smrg#if defined(HAVE_XKB_BELL_EXT) 147504b94745Smrg XkbBN_Info, 147604b94745Smrg XkbBN_MarginBell, 147704b94745Smrg XkbBN_MinorError, 147804b94745Smrg XkbBN_TerminalBell, 147904b94745Smrg#endif 148004b94745Smrg#if defined(HAVE_XKBQUERYEXTENSION) 148104b94745Smrg "Num Lock", 148204b94745Smrg "Caps Lock", 148304b94745Smrg "Scroll Lock", 148404b94745Smrg#endif 148504b94745Smrg }; 148604b94745Smrg 148704b94745Smrg#define NumKnownAtoms XtNumber(known_atoms) 148804b94745Smrg 148904b94745Smrg /* 149004b94745Smrg * The "+1" entry of the array is used for the occasional atom which is not 149104b94745Smrg * predefined. 149204b94745Smrg */ 149304b94745Smrg static struct { 149404b94745Smrg Atom atom; 149504b94745Smrg const char *name; 149604b94745Smrg } AtomCache[NumKnownAtoms + 1]; 149704b94745Smrg 149804b94745Smrg Boolean found = False; 149904b94745Smrg Atom result = None; 150004b94745Smrg Cardinal i; 150104b94745Smrg 150204b94745Smrg TRACE(("intern_atom \"%s\"\n", name)); 150304b94745Smrg 150404b94745Smrg /* 150504b94745Smrg * This should never happen as it implies xterm is aware of multiple 150604b94745Smrg * displays. 150704b94745Smrg */ 150804b94745Smrg if (display != XtDisplay(toplevel)) { 150904b94745Smrg SysError(ERROR_GET_ATOM); 151004b94745Smrg } 151104b94745Smrg 151204b94745Smrg if (AtomCache[0].name == NULL) { 151304b94745Smrg /* pre-load a number of atoms in one request to reduce latency */ 151404b94745Smrg Atom atom_return[NumKnownAtoms]; 151504b94745Smrg int code; 151604b94745Smrg 151704b94745Smrg TRACE(("initialising atom list\n")); 151804b94745Smrg code = XInternAtoms(display, 151904b94745Smrg (char **) known_atoms, 152004b94745Smrg (int) NumKnownAtoms, 152104b94745Smrg False, 152204b94745Smrg atom_return); 152304b94745Smrg /* 152404b94745Smrg * result should be Success, but actually returns BadRequest. 152504b94745Smrg * manpage says XInternAtoms can generate BadAlloc and BadValue errors. 152604b94745Smrg */ 152704b94745Smrg if (code > BadRequest) 152804b94745Smrg SysError(ERROR_GET_ATOM); 152904b94745Smrg 153004b94745Smrg for (i = 0; i < NumKnownAtoms; ++i) { 153104b94745Smrg AtomCache[i].name = known_atoms[i]; 153204b94745Smrg AtomCache[i].atom = atom_return[i]; 153304b94745Smrg } 153404b94745Smrg } 153504b94745Smrg 153604b94745Smrg /* Linear search is probably OK here, due to the small number of atoms */ 153704b94745Smrg for (i = 0; i < NumKnownAtoms; i++) { 153804b94745Smrg if (strcmp(name, AtomCache[i].name) == 0) { 153904b94745Smrg found = True; 154004b94745Smrg result = AtomCache[i].atom; 154104b94745Smrg break; 154204b94745Smrg } 154304b94745Smrg } 154404b94745Smrg 154504b94745Smrg if (!found) { 154604b94745Smrg if (AtomCache[NumKnownAtoms].name == NULL 154704b94745Smrg || strcmp(AtomCache[NumKnownAtoms].name, name)) { 154804b94745Smrg char *actual = x_strdup(name); 154904b94745Smrg free((void *) AtomCache[NumKnownAtoms].name); 155004b94745Smrg result = XInternAtom(display, actual, False); 155104b94745Smrg AtomCache[NumKnownAtoms].atom = result; 155204b94745Smrg AtomCache[NumKnownAtoms].name = actual; 155304b94745Smrg TRACE(("...allocated new atom\n")); 155404b94745Smrg } else { 155504b94745Smrg result = AtomCache[NumKnownAtoms].atom; 155604b94745Smrg TRACE(("...reused cached atom\n")); 155704b94745Smrg } 155804b94745Smrg } 155904b94745Smrg TRACE(("...intern_atom -> %ld\n", result)); 156004b94745Smrg return result; 156104b94745Smrg} 1562d522f475Smrg 1563d522f475Smrg/* 1564d522f475Smrg * Decode a key-definition. This combines the termcap and ttyModes, for 1565d522f475Smrg * comparison. Note that octal escapes in ttyModes are done by the normal 1566d522f475Smrg * resource translation. Also, ttyModes allows '^-' as a synonym for disabled. 1567d522f475Smrg */ 1568d522f475Smrgstatic int 1569d522f475Smrgdecode_keyvalue(char **ptr, int termcap) 1570d522f475Smrg{ 1571d522f475Smrg char *string = *ptr; 1572d522f475Smrg int value = -1; 1573d522f475Smrg 157420d2c4d2Smrg TRACE(("decode_keyvalue '%s'\n", string)); 1575d522f475Smrg if (*string == '^') { 1576d522f475Smrg switch (*++string) { 1577d522f475Smrg case '?': 1578d522f475Smrg value = A2E(ANSI_DEL); 1579d522f475Smrg break; 1580d522f475Smrg case '-': 1581d522f475Smrg if (!termcap) { 158204b94745Smrg value = xtermDisabledChar(); 1583d522f475Smrg break; 1584d522f475Smrg } 1585d522f475Smrg /* FALLTHRU */ 1586d522f475Smrg default: 1587d522f475Smrg value = CONTROL(*string); 1588d522f475Smrg break; 1589d522f475Smrg } 1590d522f475Smrg ++string; 1591d522f475Smrg } else if (termcap && (*string == '\\')) { 15922e4f8982Smrg char *s = (string + 1); 1593d522f475Smrg char *d; 15942e4f8982Smrg int temp = (int) strtol(s, &d, 8); 15952e4f8982Smrg if (PartS2L(s, d) && temp > 0) { 1596d522f475Smrg value = temp; 1597d522f475Smrg string = d; 1598d522f475Smrg } 1599d522f475Smrg } else { 1600d522f475Smrg value = CharOf(*string); 1601d522f475Smrg ++string; 1602d522f475Smrg } 1603d522f475Smrg *ptr = string; 160420d2c4d2Smrg TRACE(("...decode_keyvalue %#x\n", value)); 1605d522f475Smrg return value; 1606d522f475Smrg} 1607d522f475Smrg 1608d522f475Smrgstatic int 16090bd37d32SmrgmatchArg(XrmOptionDescRec * table, const char *param) 16100bd37d32Smrg{ 16110bd37d32Smrg int result = -1; 16120bd37d32Smrg int n; 16130bd37d32Smrg int ch; 16140bd37d32Smrg 16150bd37d32Smrg for (n = 0; (ch = table->option[n]) != '\0'; ++n) { 16160bd37d32Smrg if (param[n] == ch) { 16170bd37d32Smrg result = n; 16180bd37d32Smrg } else { 16190bd37d32Smrg if (param[n] != '\0') 16200bd37d32Smrg result = -1; 16210bd37d32Smrg break; 16220bd37d32Smrg } 16230bd37d32Smrg } 16240bd37d32Smrg 16250bd37d32Smrg return result; 16260bd37d32Smrg} 16270bd37d32Smrg 16280bd37d32Smrg/* return the number of argv[] entries which constitute arguments of option */ 16290bd37d32Smrgstatic int 16300bd37d32SmrgcountArg(XrmOptionDescRec * item) 1631d522f475Smrg{ 16320bd37d32Smrg int result = 0; 16330bd37d32Smrg 16340bd37d32Smrg switch (item->argKind) { 16350bd37d32Smrg case XrmoptionNoArg: 16360bd37d32Smrg /* FALLTHRU */ 16370bd37d32Smrg case XrmoptionIsArg: 16380bd37d32Smrg /* FALLTHRU */ 16390bd37d32Smrg case XrmoptionStickyArg: 16400bd37d32Smrg break; 16410bd37d32Smrg case XrmoptionSepArg: 16420bd37d32Smrg /* FALLTHRU */ 16430bd37d32Smrg case XrmoptionResArg: 16440bd37d32Smrg /* FALLTHRU */ 16450bd37d32Smrg case XrmoptionSkipArg: 16460bd37d32Smrg result = 1; 16470bd37d32Smrg break; 16480bd37d32Smrg case XrmoptionSkipLine: 16490bd37d32Smrg break; 16500bd37d32Smrg case XrmoptionSkipNArgs: 16510bd37d32Smrg result = (int) (long) (item->value); 16520bd37d32Smrg break; 16530bd37d32Smrg } 16540bd37d32Smrg return result; 16550bd37d32Smrg} 16560bd37d32Smrg 16570bd37d32Smrg#define isOption(string) (Boolean)((string)[0] == '-' || (string)[0] == '+') 16580bd37d32Smrg 16590bd37d32Smrg/* 16600bd37d32Smrg * Parse the argument list, more/less as XtInitialize, etc., would do, so we 16610bd37d32Smrg * can find our own "-help" and "-version" options reliably. Improve on just 16620bd37d32Smrg * doing that, by detecting ambiguous options (things that happen to match the 16630bd37d32Smrg * abbreviated option we are examining), and making it smart enough to handle 16640bd37d32Smrg * "-d" as an abbreviation for "-display". Doing this requires checking the 16650bd37d32Smrg * standard table (something that the X libraries should do). 16660bd37d32Smrg */ 16670bd37d32Smrgstatic XrmOptionDescRec * 16680bd37d32SmrgparseArg(int *num, char **argv, char **valuep) 16690bd37d32Smrg{ 16700bd37d32Smrg /* table adapted from XtInitialize, used here to improve abbreviations */ 16710bd37d32Smrg /* *INDENT-OFF* */ 16725307cd1aSmrg#define DATA(option,kind) { (char *) option, NULL, kind, (XPointer) 0 } 16730bd37d32Smrg static XrmOptionDescRec opTable[] = { 16740bd37d32Smrg DATA("+synchronous", XrmoptionNoArg), 16750bd37d32Smrg DATA("-background", XrmoptionSepArg), 16760bd37d32Smrg DATA("-bd", XrmoptionSepArg), 16770bd37d32Smrg DATA("-bg", XrmoptionSepArg), 16780bd37d32Smrg DATA("-bordercolor", XrmoptionSepArg), 16790bd37d32Smrg DATA("-borderwidth", XrmoptionSepArg), 16800bd37d32Smrg DATA("-bw", XrmoptionSepArg), 16810bd37d32Smrg DATA("-display", XrmoptionSepArg), 16820bd37d32Smrg DATA("-fg", XrmoptionSepArg), 16830bd37d32Smrg DATA("-fn", XrmoptionSepArg), 16840bd37d32Smrg DATA("-font", XrmoptionSepArg), 16850bd37d32Smrg DATA("-foreground", XrmoptionSepArg), 16860bd37d32Smrg DATA("-iconic", XrmoptionNoArg), 16870bd37d32Smrg DATA("-name", XrmoptionSepArg), 16880bd37d32Smrg DATA("-reverse", XrmoptionNoArg), 16890bd37d32Smrg DATA("-selectionTimeout", XrmoptionSepArg), 16900bd37d32Smrg DATA("-synchronous", XrmoptionNoArg), 16910bd37d32Smrg DATA("-title", XrmoptionSepArg), 16920bd37d32Smrg DATA("-xnllanguage", XrmoptionSepArg), 16930bd37d32Smrg DATA("-xrm", XrmoptionResArg), 16940bd37d32Smrg DATA("-xtsessionID", XrmoptionSepArg), 16950bd37d32Smrg /* These xterm options are processed after XtOpenApplication */ 16960bd37d32Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 16970bd37d32Smrg DATA("-C", XrmoptionNoArg), 16980bd37d32Smrg#endif /* TIOCCONS */ 16990bd37d32Smrg DATA("-S", XrmoptionStickyArg), 17000bd37d32Smrg DATA("-D", XrmoptionNoArg), 17010bd37d32Smrg }; 17020bd37d32Smrg#undef DATA 17030bd37d32Smrg /* *INDENT-ON* */ 17040bd37d32Smrg XrmOptionDescRec *result = 0; 17050bd37d32Smrg Cardinal inlist; 17060bd37d32Smrg Cardinal limit = XtNumber(optionDescList) + XtNumber(opTable); 17070bd37d32Smrg int atbest = -1; 17080bd37d32Smrg int best = -1; 17090bd37d32Smrg int test; 17100bd37d32Smrg Boolean exact = False; 17110bd37d32Smrg int ambiguous1 = -1; 17120bd37d32Smrg int ambiguous2 = -1; 17130bd37d32Smrg char *option; 17140bd37d32Smrg char *value; 17150bd37d32Smrg 17160bd37d32Smrg#define ITEM(n) ((Cardinal)(n) < XtNumber(optionDescList) \ 17170bd37d32Smrg ? &optionDescList[n] \ 17180bd37d32Smrg : &opTable[(Cardinal)(n) - XtNumber(optionDescList)]) 17190bd37d32Smrg 17200bd37d32Smrg if ((option = argv[*num]) != 0) { 17210bd37d32Smrg Boolean need_value; 17220bd37d32Smrg Boolean have_value = False; 17230bd37d32Smrg 17240bd37d32Smrg TRACE(("parseArg %s\n", option)); 17250bd37d32Smrg if ((value = argv[(*num) + 1]) != 0) { 1726e0a2b6dfSmrg have_value = (Boolean) !isOption(value); 17270bd37d32Smrg } 17280bd37d32Smrg for (inlist = 0; inlist < limit; ++inlist) { 17290bd37d32Smrg XrmOptionDescRec *check = ITEM(inlist); 17300bd37d32Smrg 17310bd37d32Smrg test = matchArg(check, option); 17320bd37d32Smrg if (test < 0) 17330bd37d32Smrg continue; 17340bd37d32Smrg 17350bd37d32Smrg /* check for exact match */ 17360bd37d32Smrg if ((test + 1) == (int) strlen(check->option)) { 17370bd37d32Smrg if (check->argKind == XrmoptionStickyArg) { 17380bd37d32Smrg if (strlen(option) > strlen(check->option)) { 17390bd37d32Smrg exact = True; 17400bd37d32Smrg atbest = (int) inlist; 17410bd37d32Smrg break; 17420bd37d32Smrg } 17430bd37d32Smrg } else if ((test + 1) == (int) strlen(option)) { 17440bd37d32Smrg exact = True; 17450bd37d32Smrg atbest = (int) inlist; 17460bd37d32Smrg break; 17470bd37d32Smrg } 17480bd37d32Smrg } 17490bd37d32Smrg 17500bd37d32Smrg need_value = (Boolean) (test > 0 && countArg(check) > 0); 17510bd37d32Smrg 17520bd37d32Smrg if (need_value && value != 0) { 17530bd37d32Smrg ; 17540bd37d32Smrg } else if (need_value ^ have_value) { 17550bd37d32Smrg TRACE(("...skipping, need %d vs have %d\n", need_value, have_value)); 17560bd37d32Smrg continue; 17570bd37d32Smrg } 17580bd37d32Smrg 17590bd37d32Smrg /* special-case for our own options - always allow abbreviation */ 17600bd37d32Smrg if (test > 0 17610bd37d32Smrg && ITEM(inlist)->argKind >= XrmoptionSkipArg) { 17620bd37d32Smrg atbest = (int) inlist; 1763e0a2b6dfSmrg if (ITEM(inlist)->argKind == XrmoptionSkipNArgs) { 1764e0a2b6dfSmrg /* in particular, silence a warning about ambiguity */ 1765e0a2b6dfSmrg exact = 1; 1766e0a2b6dfSmrg } 17670bd37d32Smrg break; 17680bd37d32Smrg } 17690bd37d32Smrg if (test > best) { 17700bd37d32Smrg best = test; 17710bd37d32Smrg atbest = (int) inlist; 17720bd37d32Smrg } else if (test == best) { 17730bd37d32Smrg if (atbest >= 0) { 17740bd37d32Smrg if (atbest > 0) { 17750bd37d32Smrg ambiguous1 = (int) inlist; 17760bd37d32Smrg ambiguous2 = (int) atbest; 17770bd37d32Smrg } 17780bd37d32Smrg atbest = -1; 17790bd37d32Smrg } 17800bd37d32Smrg } 17810bd37d32Smrg } 17820bd37d32Smrg } 17830bd37d32Smrg 17840bd37d32Smrg *valuep = 0; 17850bd37d32Smrg if (atbest >= 0) { 17860bd37d32Smrg result = ITEM(atbest); 17870bd37d32Smrg if (!exact) { 17880bd37d32Smrg if (ambiguous1 >= 0 && ambiguous2 >= 0) { 17890bd37d32Smrg xtermWarning("ambiguous option \"%s\" vs \"%s\"\n", 17900bd37d32Smrg ITEM(ambiguous1)->option, 17910bd37d32Smrg ITEM(ambiguous2)->option); 17920bd37d32Smrg } else if (strlen(option) > strlen(result->option)) { 17930bd37d32Smrg result = 0; 17940bd37d32Smrg } 17950bd37d32Smrg } 17960bd37d32Smrg if (result != 0) { 17970bd37d32Smrg TRACE(("...result %s\n", result->option)); 17980bd37d32Smrg /* expand abbreviations */ 17990bd37d32Smrg if (result->argKind != XrmoptionStickyArg) { 18000bd37d32Smrg if (strcmp(argv[*num], result->option)) { 18010bd37d32Smrg argv[*num] = x_strdup(result->option); 18020bd37d32Smrg } 18030bd37d32Smrg } 18040bd37d32Smrg 18050bd37d32Smrg /* adjust (*num) to skip option value */ 18060bd37d32Smrg (*num) += countArg(result); 18070bd37d32Smrg TRACE(("...next %s\n", NonNull(argv[*num]))); 18080bd37d32Smrg if (result->argKind == XrmoptionSkipArg) { 18090bd37d32Smrg *valuep = argv[*num]; 18100bd37d32Smrg TRACE(("...parameter %s\n", NonNull(*valuep))); 18110bd37d32Smrg } 18120bd37d32Smrg } 18130bd37d32Smrg } 18140bd37d32Smrg#undef ITEM 18150bd37d32Smrg return result; 1816d522f475Smrg} 1817d522f475Smrg 1818d522f475Smrgstatic void 1819d522f475SmrgSyntax(char *badOption) 1820d522f475Smrg{ 1821d522f475Smrg OptionHelp *opt; 1822d522f475Smrg OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList)); 1823d522f475Smrg int col; 1824d522f475Smrg 18250bd37d32Smrg TRACE(("Syntax error at %s\n", badOption)); 18260bd37d32Smrg xtermWarning("bad command line option \"%s\"\r\n\n", badOption); 1827d522f475Smrg 1828d522f475Smrg fprintf(stderr, "usage: %s", ProgramName); 1829956cc18dSsnj col = 8 + (int) strlen(ProgramName); 1830d522f475Smrg for (opt = list; opt->opt; opt++) { 1831956cc18dSsnj int len = 3 + (int) strlen(opt->opt); /* space [ string ] */ 1832d522f475Smrg if (col + len > 79) { 1833d522f475Smrg fprintf(stderr, "\r\n "); /* 3 spaces */ 1834d522f475Smrg col = 3; 1835d522f475Smrg } 1836d522f475Smrg fprintf(stderr, " [%s]", opt->opt); 1837d522f475Smrg col += len; 1838d522f475Smrg } 1839d522f475Smrg 1840d522f475Smrg fprintf(stderr, "\r\n\nType %s -help for a full description.\r\n\n", 1841d522f475Smrg ProgramName); 184204b94745Smrg exit(ERROR_MISC); 1843d522f475Smrg} 1844d522f475Smrg 1845d522f475Smrgstatic void 1846d522f475SmrgVersion(void) 1847d522f475Smrg{ 1848d522f475Smrg printf("%s\n", xtermVersion()); 1849d522f475Smrg fflush(stdout); 1850d522f475Smrg} 1851d522f475Smrg 1852d522f475Smrgstatic void 1853d522f475SmrgHelp(void) 1854d522f475Smrg{ 1855d522f475Smrg OptionHelp *opt; 1856d522f475Smrg OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList)); 185701037d57Smrg const char *const *cpp; 1858d522f475Smrg 1859d522f475Smrg printf("%s usage:\n %s [-options ...] [-e command args]\n\n", 1860d522f475Smrg xtermVersion(), ProgramName); 1861d522f475Smrg printf("where options include:\n"); 1862d522f475Smrg for (opt = list; opt->opt; opt++) { 1863d522f475Smrg printf(" %-28s %s\n", opt->opt, opt->desc); 1864d522f475Smrg } 1865d522f475Smrg 1866d522f475Smrg putchar('\n'); 186704b94745Smrg for (cpp = help_message; *cpp; cpp++) 1868d522f475Smrg puts(*cpp); 1869d522f475Smrg putchar('\n'); 1870d522f475Smrg fflush(stdout); 1871d522f475Smrg} 1872d522f475Smrg 1873f2e35a3aSmrgstatic void 1874f2e35a3aSmrgNeedParam(XrmOptionDescRec * option_ptr, const char *option_val) 1875f2e35a3aSmrg{ 1876f2e35a3aSmrg if (IsEmpty(option_val)) { 1877f2e35a3aSmrg xtermWarning("option %s requires a value\n", option_ptr->option); 187804b94745Smrg exit(ERROR_MISC); 1879f2e35a3aSmrg } 1880f2e35a3aSmrg} 1881f2e35a3aSmrg 1882d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 1883d522f475Smrg/* ARGSUSED */ 1884d522f475Smrgstatic Boolean 1885d522f475SmrgConvertConsoleSelection(Widget w GCC_UNUSED, 1886894e0ac8Smrg Atom *selection GCC_UNUSED, 1887894e0ac8Smrg Atom *target GCC_UNUSED, 1888894e0ac8Smrg Atom *type GCC_UNUSED, 1889d522f475Smrg XtPointer *value GCC_UNUSED, 1890d522f475Smrg unsigned long *length GCC_UNUSED, 1891d522f475Smrg int *format GCC_UNUSED) 1892d522f475Smrg{ 1893d522f475Smrg /* we don't save console output, so can't offer it */ 1894d522f475Smrg return False; 1895d522f475Smrg} 1896d522f475Smrg#endif /* TIOCCONS */ 1897d522f475Smrg 1898d522f475Smrg/* 1899d522f475Smrg * DeleteWindow(): Action proc to implement ICCCM delete_window. 1900d522f475Smrg */ 1901d522f475Smrg/* ARGSUSED */ 1902d522f475Smrgstatic void 1903d522f475SmrgDeleteWindow(Widget w, 1904894e0ac8Smrg XEvent *event GCC_UNUSED, 1905e0a2b6dfSmrg String *params GCC_UNUSED, 1906d522f475Smrg Cardinal *num_params GCC_UNUSED) 1907d522f475Smrg{ 1908d522f475Smrg#if OPT_TEK4014 1909d522f475Smrg if (w == toplevel) { 1910d522f475Smrg if (TEK4014_SHOWN(term)) 1911d522f475Smrg hide_vt_window(); 1912d522f475Smrg else 1913d522f475Smrg do_hangup(w, (XtPointer) 0, (XtPointer) 0); 191420d2c4d2Smrg } else if (TScreenOf(term)->Vshow) 1915d522f475Smrg hide_tek_window(); 1916d522f475Smrg else 1917d522f475Smrg#endif 1918d522f475Smrg do_hangup(w, (XtPointer) 0, (XtPointer) 0); 1919d522f475Smrg} 1920d522f475Smrg 1921d522f475Smrg/* ARGSUSED */ 1922d522f475Smrgstatic void 1923d522f475SmrgKeyboardMapping(Widget w GCC_UNUSED, 1924894e0ac8Smrg XEvent *event, 1925e0a2b6dfSmrg String *params GCC_UNUSED, 1926d522f475Smrg Cardinal *num_params GCC_UNUSED) 1927d522f475Smrg{ 1928d522f475Smrg switch (event->type) { 1929d522f475Smrg case MappingNotify: 1930d522f475Smrg XRefreshKeyboardMapping(&event->xmapping); 1931d522f475Smrg break; 1932d522f475Smrg } 1933d522f475Smrg} 1934d522f475Smrg 1935d522f475Smrgstatic XtActionsRec actionProcs[] = 1936d522f475Smrg{ 1937d522f475Smrg {"DeleteWindow", DeleteWindow}, 1938d522f475Smrg {"KeyboardMapping", KeyboardMapping}, 1939d522f475Smrg}; 1940d522f475Smrg 1941d522f475Smrg/* 1942d522f475Smrg * Some platforms use names such as /dev/tty01, others /dev/pts/1. Parse off 1943d522f475Smrg * the "tty01" or "pts/1" portion, and return that for use as an identifier for 1944d522f475Smrg * utmp. 1945d522f475Smrg */ 1946d522f475Smrgstatic char * 1947d522f475Smrgmy_pty_name(char *device) 1948d522f475Smrg{ 1949d522f475Smrg size_t len = strlen(device); 1950d522f475Smrg Bool name = False; 1951d522f475Smrg 1952d522f475Smrg while (len != 0) { 1953d522f475Smrg int ch = device[len - 1]; 1954d522f475Smrg if (isdigit(ch)) { 1955d522f475Smrg len--; 1956d522f475Smrg } else if (ch == '/') { 1957d522f475Smrg if (name) 1958d522f475Smrg break; 1959d522f475Smrg len--; 19605307cd1aSmrg } else if (isalpha(CharOf(ch))) { 1961d522f475Smrg name = True; 1962d522f475Smrg len--; 1963d522f475Smrg } else { 1964d522f475Smrg break; 1965d522f475Smrg } 1966d522f475Smrg } 1967d522f475Smrg TRACE(("my_pty_name(%s) -> '%s'\n", device, device + len)); 1968d522f475Smrg return device + len; 1969d522f475Smrg} 1970d522f475Smrg 1971d522f475Smrg/* 1972d522f475Smrg * If the name contains a '/', it is a "pts/1" case. Otherwise, return the 1973d522f475Smrg * last few characters for a utmp identifier. 1974d522f475Smrg */ 1975d522f475Smrgstatic char * 1976d522f475Smrgmy_pty_id(char *device) 1977d522f475Smrg{ 1978d522f475Smrg char *name = my_pty_name(device); 1979d522f475Smrg char *leaf = x_basename(name); 1980d522f475Smrg 1981d522f475Smrg if (name == leaf) { /* no '/' in the name */ 1982956cc18dSsnj int len = (int) strlen(leaf); 1983d522f475Smrg if (PTYCHARLEN < len) 1984d522f475Smrg leaf = leaf + (len - PTYCHARLEN); 1985d522f475Smrg } 1986d522f475Smrg TRACE(("my_pty_id (%s) -> '%s'\n", device, leaf)); 1987d522f475Smrg return leaf; 1988d522f475Smrg} 1989d522f475Smrg 1990d522f475Smrg/* 1991d522f475Smrg * Set the tty/pty identifier 1992d522f475Smrg */ 1993d522f475Smrgstatic void 1994d522f475Smrgset_pty_id(char *device, char *id) 1995d522f475Smrg{ 1996d522f475Smrg char *name = my_pty_name(device); 1997d522f475Smrg char *leaf = x_basename(name); 1998d522f475Smrg 1999d522f475Smrg if (name == leaf) { 2000d522f475Smrg strcpy(my_pty_id(device), id); 2001d522f475Smrg } else { 2002d522f475Smrg strcpy(leaf, id); 2003d522f475Smrg } 2004d522f475Smrg TRACE(("set_pty_id(%s) -> '%s'\n", id, device)); 2005d522f475Smrg} 2006d522f475Smrg 2007d522f475Smrg/* 2008d522f475Smrg * The original -S option accepts two characters to identify the pty, and a 2009d522f475Smrg * file-descriptor (assumed to be nonzero). That is not general enough, so we 2010d522f475Smrg * check first if the option contains a '/' to delimit the two fields, and if 2011d522f475Smrg * not, fall-thru to the original logic. 2012d522f475Smrg */ 2013d522f475Smrgstatic Bool 2014d522f475SmrgParseSccn(char *option) 2015d522f475Smrg{ 2016d522f475Smrg char *leaf = x_basename(option); 2017d522f475Smrg Bool code = False; 2018d522f475Smrg 201901037d57Smrg passedPty = x_strdup(option); 2020d522f475Smrg if (leaf != option) { 2021d522f475Smrg if (leaf - option > 0 2022d522f475Smrg && isdigit(CharOf(*leaf)) 2023d522f475Smrg && sscanf(leaf, "%d", &am_slave) == 1) { 2024956cc18dSsnj size_t len = (size_t) (leaf - option - 1); 2025d522f475Smrg /* 2026d522f475Smrg * If we have a slash, we only care about the part after the slash, 2027d522f475Smrg * which is a file-descriptor. The part before the slash can be 2028d522f475Smrg * the /dev/pts/XXX value, but since we do not need to reopen it, 2029d522f475Smrg * it is useful mainly for display in a "ps -ef". 2030d522f475Smrg */ 2031d522f475Smrg passedPty[len] = 0; 2032d522f475Smrg code = True; 2033d522f475Smrg } 2034d522f475Smrg } else { 2035d522f475Smrg code = (sscanf(option, "%c%c%d", 2036d522f475Smrg passedPty, passedPty + 1, &am_slave) == 3); 203701037d57Smrg passedPty[2] = '\0'; 2038d522f475Smrg } 2039d522f475Smrg TRACE(("ParseSccn(%s) = '%s' %d (%s)\n", option, 2040d522f475Smrg passedPty, am_slave, code ? "OK" : "ERR")); 2041d522f475Smrg return code; 2042d522f475Smrg} 2043d522f475Smrg 2044d522f475Smrg#if defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 2045d522f475Smrg/* 2046d522f475Smrg * From "man utmp": 2047d522f475Smrg * xterm and other terminal emulators directly create a USER_PROCESS record 2048d522f475Smrg * and generate the ut_id by using the last two letters of /dev/ttyp%c or by 2049d522f475Smrg * using p%d for /dev/pts/%d. If they find a DEAD_PROCESS for this id, they 2050d522f475Smrg * recycle it, otherwise they create a new entry. If they can, they will mark 2051d522f475Smrg * it as DEAD_PROCESS on exiting and it is advised that they null ut_line, 2052d522f475Smrg * ut_time, ut_user and ut_host as well. 2053d522f475Smrg * 2054d522f475Smrg * Generally ut_id allows no more than 3 characters (plus null), even if the 2055d522f475Smrg * pty implementation allows more than 3 digits. 2056d522f475Smrg */ 2057d522f475Smrgstatic char * 2058d522f475Smrgmy_utmp_id(char *device) 2059d522f475Smrg{ 2060d522f475Smrg typedef struct UTMP_STR UTMP_STRUCT; 2061d522f475Smrg#define UTIDSIZE (sizeof(((UTMP_STRUCT *)NULL)->ut_id)) 2062d522f475Smrg static char result[UTIDSIZE + 1]; 2063d522f475Smrg 2064d522f475Smrg#if defined(__SCO__) || defined(__UNIXWARE__) 2065d522f475Smrg /* 2066d522f475Smrg * Legend does not support old-style pty's, has no related compatibility 2067d522f475Smrg * issues, and can use the available space in ut_id differently from the 2068d522f475Smrg * default convention. 2069d522f475Smrg * 2070d522f475Smrg * This scheme is intended to avoid conflicts both with other users of 2071d522f475Smrg * utmpx as well as between multiple xterms. First, Legend uses all of the 2072d522f475Smrg * characters of ut_id, and adds no terminating NUL is required (the 2073d522f475Smrg * default scheme may add a trailing NUL). Second, all xterm entries will 2074d522f475Smrg * start with the letter 'x' followed by three digits, which will be the 2075d522f475Smrg * last three digits of the device name, regardless of the format of the 2076d522f475Smrg * device name, with leading 0's added where necessary. For instance, an 2077d522f475Smrg * xterm on /dev/pts/3 will have a ut_id of x003; an xterm on /dev/pts123 2078d522f475Smrg * will have a ut_id of x123. Under the other convention, /dev/pts/3 would 2079d522f475Smrg * have a ut_id of p3 and /dev/pts123 would have a ut_id of p123. 2080d522f475Smrg */ 2081d522f475Smrg int len, n; 2082d522f475Smrg 2083d522f475Smrg len = strlen(device); 2084d522f475Smrg n = UTIDSIZE; 2085d522f475Smrg result[n] = '\0'; 2086d522f475Smrg while ((n > 0) && (len > 0) && isdigit(device[len - 1])) 2087d522f475Smrg result[--n] = device[--len]; 2088d522f475Smrg while (n > 0) 2089d522f475Smrg result[--n] = '0'; 2090d522f475Smrg result[0] = 'x'; 2091d522f475Smrg#else 2092d522f475Smrg char *name = my_pty_name(device); 2093d522f475Smrg char *leaf = x_basename(name); 2094d522f475Smrg size_t len = strlen(leaf); 2095d522f475Smrg 2096d522f475Smrg if ((UTIDSIZE - 1) < len) 2097d522f475Smrg leaf = leaf + (len - (UTIDSIZE - 1)); 2098d522f475Smrg sprintf(result, "p%s", leaf); 2099d522f475Smrg#endif 2100d522f475Smrg 2101d522f475Smrg TRACE(("my_utmp_id (%s) -> '%s'\n", device, result)); 2102d522f475Smrg return result; 2103d522f475Smrg} 2104d522f475Smrg#endif /* USE_SYSV_UTMP */ 2105d522f475Smrg 2106d522f475Smrg#ifdef USE_POSIX_SIGNALS 2107d522f475Smrg 2108d522f475Smrgtypedef void (*sigfunc) (int); 2109d522f475Smrg 2110d522f475Smrg/* make sure we sure we ignore SIGCHLD for the cases parent 2111d522f475Smrg has just been stopped and not actually killed */ 2112d522f475Smrg 2113d522f475Smrgstatic sigfunc 2114d522f475Smrgposix_signal(int signo, sigfunc func) 2115d522f475Smrg{ 2116d522f475Smrg struct sigaction act, oact; 2117d522f475Smrg 2118d522f475Smrg act.sa_handler = func; 2119d522f475Smrg sigemptyset(&act.sa_mask); 2120d522f475Smrg#ifdef SA_RESTART 2121d522f475Smrg act.sa_flags = SA_NOCLDSTOP | SA_RESTART; 2122d522f475Smrg#else 2123d522f475Smrg act.sa_flags = SA_NOCLDSTOP; 2124d522f475Smrg#endif 2125d522f475Smrg if (sigaction(signo, &act, &oact) < 0) 2126d522f475Smrg return (SIG_ERR); 2127d522f475Smrg return (oact.sa_handler); 2128d522f475Smrg} 2129d522f475Smrg 21300bd37d32Smrg#endif /* USE_POSIX_SIGNALS */ 2131d522f475Smrg 2132d522f475Smrg#if defined(DISABLE_SETUID) || defined(USE_UTMP_SETGID) 2133d522f475Smrgstatic void 2134d522f475SmrgdisableSetUid(void) 2135d522f475Smrg{ 2136d522f475Smrg TRACE(("process %d disableSetUid\n", (int) getpid())); 2137d522f475Smrg if (setuid(save_ruid) == -1) { 21380bd37d32Smrg xtermWarning("unable to reset uid\n"); 213904b94745Smrg exit(ERROR_MISC); 2140d522f475Smrg } 2141d522f475Smrg TRACE_IDS; 2142d522f475Smrg} 2143d522f475Smrg#else 2144d522f475Smrg#define disableSetUid() /* nothing */ 2145d522f475Smrg#endif /* DISABLE_SETUID */ 2146d522f475Smrg 2147d522f475Smrg#if defined(DISABLE_SETGID) || defined(USE_UTMP_SETGID) 2148d522f475Smrgstatic void 2149d522f475SmrgdisableSetGid(void) 2150d522f475Smrg{ 2151d522f475Smrg TRACE(("process %d disableSetGid\n", (int) getpid())); 2152d522f475Smrg if (setegid(save_rgid) == -1) { 21530bd37d32Smrg xtermWarning("unable to reset effective gid\n"); 215404b94745Smrg exit(ERROR_MISC); 2155d522f475Smrg } 2156d522f475Smrg TRACE_IDS; 2157d522f475Smrg} 2158d522f475Smrg#else 2159d522f475Smrg#define disableSetGid() /* nothing */ 2160d522f475Smrg#endif /* DISABLE_SETGID */ 2161d522f475Smrg 2162d522f475Smrg#if defined(HAVE_POSIX_SAVED_IDS) 2163d522f475Smrg#if (!defined(USE_UTEMPTER) || !defined(DISABLE_SETGID)) 2164d522f475Smrgstatic void 2165d522f475SmrgsetEffectiveGroup(gid_t group) 2166d522f475Smrg{ 2167d522f475Smrg TRACE(("process %d setEffectiveGroup(%d)\n", (int) getpid(), (int) group)); 2168d522f475Smrg if (setegid(group) == -1) { 2169d522f475Smrg#ifdef __MVS__ 2170d522f475Smrg if (!(errno == EMVSERR)) /* could happen if _BPX_SHAREAS=REUSE */ 2171d522f475Smrg#endif 2172d522f475Smrg { 21730bd37d32Smrg xtermPerror("setegid(%d)", (int) group); 2174d522f475Smrg } 2175d522f475Smrg } 2176d522f475Smrg TRACE_IDS; 2177d522f475Smrg} 2178d522f475Smrg#endif 2179d522f475Smrg 2180d522f475Smrg#if !defined(USE_UTMP_SETGID) && (!defined(USE_UTEMPTER) || !defined(DISABLE_SETUID)) 2181d522f475Smrgstatic void 2182d522f475SmrgsetEffectiveUser(uid_t user) 2183d522f475Smrg{ 2184d522f475Smrg TRACE(("process %d setEffectiveUser(%d)\n", (int) getpid(), (int) user)); 2185d522f475Smrg if (seteuid(user) == -1) { 2186d522f475Smrg#ifdef __MVS__ 2187d522f475Smrg if (!(errno == EMVSERR)) 2188d522f475Smrg#endif 2189d522f475Smrg { 21900bd37d32Smrg xtermPerror("seteuid(%d)", (int) user); 2191d522f475Smrg } 2192d522f475Smrg } 2193d522f475Smrg TRACE_IDS; 2194d522f475Smrg} 2195d522f475Smrg#endif 2196d522f475Smrg#endif /* HAVE_POSIX_SAVED_IDS */ 2197d522f475Smrg 21982e4f8982Smrg#if OPT_LUIT_PROG 21992e4f8982Smrgstatic Boolean 22002e4f8982Smrgcomplex_command(char **args) 22012e4f8982Smrg{ 22022e4f8982Smrg Boolean result = False; 22032e4f8982Smrg if (x_countargv(args) == 1) { 22042e4f8982Smrg char *check = xtermFindShell(args[0], False); 22052e4f8982Smrg if (check == 0) { 22062e4f8982Smrg result = True; 22072e4f8982Smrg } else { 22082e4f8982Smrg free(check); 22092e4f8982Smrg } 22102e4f8982Smrg } 22112e4f8982Smrg return result; 22122e4f8982Smrg} 22132e4f8982Smrg#endif 22142e4f8982Smrg 22152e4f8982Smrgstatic unsigned 22162e4f8982Smrglookup_baudrate(const char *value) 22172e4f8982Smrg{ 22182e4f8982Smrg struct speed { 22192e4f8982Smrg unsigned given_speed; /* values for 'ospeed' */ 22202e4f8982Smrg unsigned actual_speed; /* the actual speed */ 22212e4f8982Smrg }; 22222e4f8982Smrg 22232e4f8982Smrg#define DATA(number) { B##number, number } 22242e4f8982Smrg 22252e4f8982Smrg static struct speed const speeds[] = 22262e4f8982Smrg { 22272e4f8982Smrg DATA(0), 22282e4f8982Smrg DATA(50), 22292e4f8982Smrg DATA(75), 22302e4f8982Smrg DATA(110), 22312e4f8982Smrg DATA(134), 22322e4f8982Smrg DATA(150), 22332e4f8982Smrg DATA(200), 22342e4f8982Smrg DATA(300), 22352e4f8982Smrg DATA(600), 22362e4f8982Smrg DATA(1200), 22372e4f8982Smrg DATA(1800), 22382e4f8982Smrg DATA(2400), 22392e4f8982Smrg DATA(4800), 22402e4f8982Smrg DATA(9600), 22412e4f8982Smrg#ifdef B19200 22422e4f8982Smrg DATA(19200), 22432e4f8982Smrg#elif defined(EXTA) 22442e4f8982Smrg {EXTA, 19200}, 22452e4f8982Smrg#endif 22462e4f8982Smrg#ifdef B28800 22472e4f8982Smrg DATA(28800), 22482e4f8982Smrg#endif 22492e4f8982Smrg#ifdef B38400 22502e4f8982Smrg DATA(38400), 22512e4f8982Smrg#elif defined(EXTB) 22522e4f8982Smrg {EXTB, 38400}, 22532e4f8982Smrg#endif 22542e4f8982Smrg#ifdef B57600 22552e4f8982Smrg DATA(57600), 22562e4f8982Smrg#endif 22572e4f8982Smrg#ifdef B76800 22582e4f8982Smrg DATA(76800), 22592e4f8982Smrg#endif 22602e4f8982Smrg#ifdef B115200 22612e4f8982Smrg DATA(115200), 22622e4f8982Smrg#endif 22632e4f8982Smrg#ifdef B153600 22642e4f8982Smrg DATA(153600), 22652e4f8982Smrg#endif 22662e4f8982Smrg#ifdef B230400 22672e4f8982Smrg DATA(230400), 22682e4f8982Smrg#endif 22692e4f8982Smrg#ifdef B307200 22702e4f8982Smrg DATA(307200), 22712e4f8982Smrg#endif 22722e4f8982Smrg#ifdef B460800 22732e4f8982Smrg DATA(460800), 22742e4f8982Smrg#endif 22752e4f8982Smrg#ifdef B500000 22762e4f8982Smrg DATA(500000), 22772e4f8982Smrg#endif 22782e4f8982Smrg#ifdef B576000 22792e4f8982Smrg DATA(576000), 22802e4f8982Smrg#endif 22812e4f8982Smrg#ifdef B921600 22822e4f8982Smrg DATA(921600), 22832e4f8982Smrg#endif 22842e4f8982Smrg#ifdef B1000000 22852e4f8982Smrg DATA(1000000), 22862e4f8982Smrg#endif 22872e4f8982Smrg#ifdef B1152000 22882e4f8982Smrg DATA(1152000), 22892e4f8982Smrg#endif 22902e4f8982Smrg#ifdef B1500000 22912e4f8982Smrg DATA(1500000), 22922e4f8982Smrg#endif 22932e4f8982Smrg#ifdef B2000000 22942e4f8982Smrg DATA(2000000), 22952e4f8982Smrg#endif 22962e4f8982Smrg#ifdef B2500000 22972e4f8982Smrg DATA(2500000), 22982e4f8982Smrg#endif 22992e4f8982Smrg#ifdef B3000000 23002e4f8982Smrg DATA(3000000), 23012e4f8982Smrg#endif 23022e4f8982Smrg#ifdef B3500000 23032e4f8982Smrg DATA(3500000), 23042e4f8982Smrg#endif 23052e4f8982Smrg#ifdef B4000000 23062e4f8982Smrg DATA(4000000), 23072e4f8982Smrg#endif 23082e4f8982Smrg }; 23092e4f8982Smrg#undef DATA 23102e4f8982Smrg unsigned result = 0; 23112e4f8982Smrg long check; 23122e4f8982Smrg char *next; 23132e4f8982Smrg if (x_toupper(*value) == 'B') 23142e4f8982Smrg value++; 23152e4f8982Smrg if (isdigit(CharOf(*value))) { 23162e4f8982Smrg check = strtol(value, &next, 10); 23172e4f8982Smrg if (FullS2L(value, next) && (check > 0)) { 23182e4f8982Smrg Cardinal n; 23192e4f8982Smrg for (n = 0; n < XtNumber(speeds); ++n) { 23202e4f8982Smrg if (speeds[n].actual_speed == (unsigned) check) { 23212e4f8982Smrg result = speeds[n].given_speed; 23222e4f8982Smrg break; 23232e4f8982Smrg } 23242e4f8982Smrg } 23252e4f8982Smrg } 23262e4f8982Smrg } 23272e4f8982Smrg if (result == 0) { 23282e4f8982Smrg fprintf(stderr, "unsupported value for baudrate: %s\n", value); 23292e4f8982Smrg } 23302e4f8982Smrg return result; 23312e4f8982Smrg} 23322e4f8982Smrg 23335307cd1aSmrgint 23345307cd1aSmrgget_tty_erase(int fd, int default_erase, const char *tag) 23355307cd1aSmrg{ 23365307cd1aSmrg int result = default_erase; 23375307cd1aSmrg int rc; 23385307cd1aSmrg 23395307cd1aSmrg#ifdef TERMIO_STRUCT 23405307cd1aSmrg TERMIO_STRUCT my_tio; 23415307cd1aSmrg rc = ttyGetAttr(fd, &my_tio); 23425307cd1aSmrg if (rc == 0) 23435307cd1aSmrg result = my_tio.c_cc[VERASE]; 23445307cd1aSmrg#else /* !TERMIO_STRUCT */ 23455307cd1aSmrg struct sgttyb my_sg; 23465307cd1aSmrg rc = ioctl(fd, TIOCGETP, (char *) &my_sg); 23475307cd1aSmrg if (rc == 0) 23485307cd1aSmrg result = my_sg.sg_erase; 23495307cd1aSmrg#endif /* TERMIO_STRUCT */ 23505307cd1aSmrg TRACE(("%s erase:%d (from %s)\n", (rc == 0) ? "OK" : "FAIL", result, tag)); 23515307cd1aSmrg (void) tag; 23525307cd1aSmrg return result; 23535307cd1aSmrg} 23545307cd1aSmrg 23555307cd1aSmrgint 23565307cd1aSmrgget_tty_lnext(int fd, int default_lnext, const char *tag) 23575307cd1aSmrg{ 23585307cd1aSmrg int result = default_lnext; 23595307cd1aSmrg int rc; 23605307cd1aSmrg 23615307cd1aSmrg#ifdef TERMIO_STRUCT 23625307cd1aSmrg TERMIO_STRUCT my_tio; 23635307cd1aSmrg rc = ttyGetAttr(fd, &my_tio); 23645307cd1aSmrg if (rc == 0) 23655307cd1aSmrg result = my_tio.c_cc[VLNEXT]; 23665307cd1aSmrg#elif defined(HAS_LTCHARS) 23675307cd1aSmrg struct ltchars my_ltc; 23685307cd1aSmrg rc = ioctl(fd, TIOCGLTC, (char *) &my_ltc); 23695307cd1aSmrg if (rc == 0) 23705307cd1aSmrg result = my_ltc.t_lnextc; 23715307cd1aSmrg#else 23725307cd1aSmrg result = XTERM_LNEXT; 23735307cd1aSmrg#endif /* TERMIO_STRUCT */ 23745307cd1aSmrg TRACE(("%s lnext:%d (from %s)\n", (rc == 0) ? "OK" : "FAIL", result, tag)); 23755307cd1aSmrg (void) tag; 23765307cd1aSmrg return result; 23775307cd1aSmrg} 23785307cd1aSmrg 2379d522f475Smrgint 2380d522f475Smrgmain(int argc, char *argv[]ENVP_ARG) 2381d522f475Smrg{ 2382a1f3da82Smrg#if OPT_MAXIMIZE 2383a1f3da82Smrg#define DATA(name) { #name, es##name } 238401037d57Smrg static const FlagList tblFullscreen[] = 2385a1f3da82Smrg { 2386a1f3da82Smrg DATA(Always), 2387a1f3da82Smrg DATA(Never) 2388a1f3da82Smrg }; 2389a1f3da82Smrg#undef DATA 2390a1f3da82Smrg#endif 2391a1f3da82Smrg 2392d522f475Smrg Widget form_top, menu_top; 2393d522f475Smrg Dimension menu_high; 2394d522f475Smrg TScreen *screen; 2395d522f475Smrg int mode; 2396e0a2b6dfSmrg char *my_class = x_strdup(DEFCLASS); 23972e4f8982Smrg unsigned line_speed = VAL_LINE_SPEED; 2398d522f475Smrg Window winToEmbedInto = None; 2399f2e35a3aSmrg#if defined(HAVE_LIB_XAW3DXFT) 2400f2e35a3aSmrg Xaw3dXftData *xaw3dxft_data; 2401f2e35a3aSmrg#endif 2402d522f475Smrg 2403ae137402Smrg ProgramName = x_strdup(x_basename(argv[0])); 2404ae137402Smrg ProgramPath = xtermFindShell(argv[0], True); 2405ae137402Smrg if (ProgramPath != NULL) 2406ae137402Smrg argv[0] = ProgramPath; 2407d522f475Smrg 2408d522f475Smrg#ifdef HAVE_POSIX_SAVED_IDS 2409d522f475Smrg save_euid = geteuid(); 2410d522f475Smrg save_egid = getegid(); 2411d522f475Smrg#endif 2412d522f475Smrg 2413d522f475Smrg save_ruid = getuid(); 2414d522f475Smrg save_rgid = getgid(); 2415d522f475Smrg 2416d522f475Smrg#if defined(DISABLE_SETUID) || defined(DISABLE_SETGID) 2417d522f475Smrg#if defined(DISABLE_SETUID) 2418d522f475Smrg disableSetUid(); 2419d522f475Smrg#endif 2420d522f475Smrg#if defined(DISABLE_SETGID) 2421d522f475Smrg disableSetGid(); 2422d522f475Smrg#endif 2423d522f475Smrg TRACE_IDS; 2424d522f475Smrg#endif 2425d522f475Smrg 2426d522f475Smrg /* extra length in case longer tty name like /dev/ttyq255 */ 2427d522f475Smrg ttydev = TypeMallocN(char, sizeof(TTYDEV) + 80); 2428d522f475Smrg#ifdef USE_PTY_DEVICE 2429d522f475Smrg ptydev = TypeMallocN(char, sizeof(PTYDEV) + 80); 2430d522f475Smrg if (!ttydev || !ptydev) 2431d522f475Smrg#else 2432d522f475Smrg if (!ttydev) 2433d522f475Smrg#endif 2434d522f475Smrg { 24350bd37d32Smrg xtermWarning("unable to allocate memory for ttydev or ptydev\n"); 243604b94745Smrg exit(ERROR_MISC); 2437d522f475Smrg } 2438d522f475Smrg strcpy(ttydev, TTYDEV); 2439d522f475Smrg#ifdef USE_PTY_DEVICE 2440d522f475Smrg strcpy(ptydev, PTYDEV); 2441d522f475Smrg#endif 2442d522f475Smrg 2443d522f475Smrg#if defined(USE_UTMP_SETGID) 2444d522f475Smrg get_pty(NULL, NULL); 2445d522f475Smrg disableSetUid(); 2446d522f475Smrg disableSetGid(); 2447d522f475Smrg TRACE_IDS; 2448d522f475Smrg#define get_pty(pty, from) really_get_pty(pty, from) 2449d522f475Smrg#endif 2450d522f475Smrg 2451d522f475Smrg /* Do these first, since we may not be able to open the display */ 2452d522f475Smrg TRACE_OPTS(xtermOptions, optionDescList, XtNumber(optionDescList)); 2453d522f475Smrg TRACE_ARGV("Before XtOpenApplication", argv); 2454ae137402Smrg restart_params = 0; 2455d522f475Smrg if (argc > 1) { 24560bd37d32Smrg XrmOptionDescRec *option_ptr; 24570bd37d32Smrg char *option_value; 2458d522f475Smrg int n; 2459e39b573cSmrg Bool quit = False; 2460d522f475Smrg 2461d522f475Smrg for (n = 1; n < argc; n++) { 24620bd37d32Smrg if ((option_ptr = parseArg(&n, argv, &option_value)) == 0) { 24630bd37d32Smrg if (argv[n] == 0) { 24640bd37d32Smrg break; 24650bd37d32Smrg } else if (isOption(argv[n])) { 24660bd37d32Smrg Syntax(argv[n]); 24670bd37d32Smrg } else if (explicit_shname != 0) { 24680bd37d32Smrg xtermWarning("Explicit shell already was %s\n", explicit_shname); 24690bd37d32Smrg Syntax(argv[n]); 24700bd37d32Smrg } 24710bd37d32Smrg explicit_shname = xtermFindShell(argv[n], True); 24720bd37d32Smrg if (explicit_shname == 0) 24730bd37d32Smrg exit(0); 24740bd37d32Smrg TRACE(("...explicit shell %s\n", explicit_shname)); 2475ae137402Smrg restart_params = (argc - n); 24760bd37d32Smrg } else if (!strcmp(option_ptr->option, "-e")) { 24770bd37d32Smrg command_to_exec = (argv + n + 1); 24780bd37d32Smrg if (!command_to_exec[0]) 24790bd37d32Smrg Syntax(argv[n]); 2480ae137402Smrg restart_params = (argc - n); 24810bd37d32Smrg break; 24820bd37d32Smrg } else if (!strcmp(option_ptr->option, "-version")) { 2483d522f475Smrg Version(); 2484e39b573cSmrg quit = True; 24850bd37d32Smrg } else if (!strcmp(option_ptr->option, "-help")) { 2486d522f475Smrg Help(); 2487e39b573cSmrg quit = True; 24882e4f8982Smrg } else if (!strcmp(option_ptr->option, "-baudrate")) { 2489f2e35a3aSmrg NeedParam(option_ptr, option_value); 24902e4f8982Smrg if ((line_speed = lookup_baudrate(option_value)) == 0) { 24912e4f8982Smrg Help(); 24922e4f8982Smrg quit = True; 24932e4f8982Smrg } 24940bd37d32Smrg } else if (!strcmp(option_ptr->option, "-class")) { 2495f2e35a3aSmrg NeedParam(option_ptr, option_value); 2496e0a2b6dfSmrg free(my_class); 24970bd37d32Smrg if ((my_class = x_strdup(option_value)) == 0) { 2498d522f475Smrg Help(); 2499e39b573cSmrg quit = True; 2500d522f475Smrg } 25010bd37d32Smrg } else if (!strcmp(option_ptr->option, "-into")) { 25020bd37d32Smrg char *endPtr; 2503f2e35a3aSmrg NeedParam(option_ptr, option_value); 25040bd37d32Smrg winToEmbedInto = (Window) strtol(option_value, &endPtr, 0); 25052e4f8982Smrg if (!FullS2L(option_value, endPtr)) { 25062e4f8982Smrg Help(); 25072e4f8982Smrg quit = True; 25082e4f8982Smrg } 2509d522f475Smrg } 2510d522f475Smrg } 2511d522f475Smrg if (quit) 2512d522f475Smrg exit(0); 25130bd37d32Smrg /* 25140bd37d32Smrg * If there is anything left unparsed, and we're not using "-e", 25150bd37d32Smrg * then give up. 25160bd37d32Smrg */ 25170bd37d32Smrg if (n < argc && !command_to_exec) { 25180bd37d32Smrg Syntax(argv[n]); 25190bd37d32Smrg } 2520d522f475Smrg } 2521d522f475Smrg 25220bd37d32Smrg /* This dumped core on HP-UX 9.05 with X11R5 */ 2523d522f475Smrg#if OPT_I18N_SUPPORT 2524d522f475Smrg XtSetLanguageProc(NULL, NULL, NULL); 2525d522f475Smrg#endif 2526d522f475Smrg 2527f2e35a3aSmrg /* enable Xft support in Xaw3DXft */ 2528f2e35a3aSmrg#if defined(HAVE_LIB_XAW3DXFT) 2529f2e35a3aSmrg GET_XAW3DXFT_DATA(xaw3dxft_data); 2530f2e35a3aSmrg xaw3dxft_data->encoding = -1; 2531f2e35a3aSmrg#endif 2532f2e35a3aSmrg 2533d522f475Smrg#ifdef TERMIO_STRUCT /* { */ 2534d522f475Smrg /* Initialization is done here rather than above in order 2535d522f475Smrg * to prevent any assumptions about the order of the contents 2536d522f475Smrg * of the various terminal structures (which may change from 2537d522f475Smrg * implementation to implementation). 2538d522f475Smrg */ 2539d522f475Smrg memset(&d_tio, 0, sizeof(d_tio)); 2540d522f475Smrg d_tio.c_iflag = ICRNL | IXON; 2541f2e35a3aSmrg d_tio.c_oflag = TAB3 | D_TIO_FLAGS; 2542d522f475Smrg { 2543d522f475Smrg Cardinal nn; 2544d522f475Smrg 2545d522f475Smrg /* fill in default-values */ 2546f2e35a3aSmrg for (nn = 0; nn < XtNumber(ttyChars); ++nn) { 2547d522f475Smrg if (validTtyChar(d_tio, nn)) { 2548f2e35a3aSmrg d_tio.c_cc[ttyChars[nn].sysMode] = 2549f2e35a3aSmrg (cc_t) ttyChars[nn].myDefault; 2550d522f475Smrg } 2551d522f475Smrg } 2552d522f475Smrg } 2553d522f475Smrg#if defined(macII) || defined(ATT) || defined(CRAY) /* { */ 25542e4f8982Smrg d_tio.c_cflag = line_speed | CS8 | CREAD | PARENB | HUPCL; 2555d522f475Smrg d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK; 2556d522f475Smrg#ifdef ECHOKE 2557d522f475Smrg d_tio.c_lflag |= ECHOKE | IEXTEN; 2558d522f475Smrg#endif 2559d522f475Smrg#ifdef ECHOCTL 2560d522f475Smrg d_tio.c_lflag |= ECHOCTL | IEXTEN; 2561d522f475Smrg#endif 2562d522f475Smrg#ifndef USE_TERMIOS /* { */ 2563d522f475Smrg d_tio.c_line = 0; 2564d522f475Smrg#endif /* } */ 2565d522f475Smrg#ifdef HAS_LTCHARS /* { */ 2566d522f475Smrg d_ltc.t_suspc = CSUSP; /* t_suspc */ 2567d522f475Smrg d_ltc.t_dsuspc = CDSUSP; /* t_dsuspc */ 2568d522f475Smrg d_ltc.t_rprntc = CRPRNT; 2569d522f475Smrg d_ltc.t_flushc = CFLUSH; 2570d522f475Smrg d_ltc.t_werasc = CWERASE; 2571d522f475Smrg d_ltc.t_lnextc = CLNEXT; 2572d522f475Smrg#endif /* } HAS_LTCHARS */ 2573d522f475Smrg#ifdef TIOCLSET /* { */ 2574d522f475Smrg d_lmode = 0; 2575d522f475Smrg#endif /* } TIOCLSET */ 2576d522f475Smrg#else /* }{ else !macII, ATT, CRAY */ 2577d522f475Smrg#ifndef USE_POSIX_TERMIOS 2578d522f475Smrg#ifdef BAUD_0 /* { */ 2579d522f475Smrg d_tio.c_cflag = CS8 | CREAD | PARENB | HUPCL; 2580d522f475Smrg#else /* }{ !BAUD_0 */ 25812e4f8982Smrg d_tio.c_cflag = line_speed | CS8 | CREAD | PARENB | HUPCL; 2582d522f475Smrg#endif /* } !BAUD_0 */ 2583d522f475Smrg#else /* USE_POSIX_TERMIOS */ 2584d522f475Smrg d_tio.c_cflag = CS8 | CREAD | PARENB | HUPCL; 25852e4f8982Smrg cfsetispeed(&d_tio, line_speed); 25862e4f8982Smrg cfsetospeed(&d_tio, line_speed); 2587d522f475Smrg#endif 2588d522f475Smrg d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK; 2589d522f475Smrg#ifdef ECHOKE 2590d522f475Smrg d_tio.c_lflag |= ECHOKE | IEXTEN; 2591d522f475Smrg#endif 2592d522f475Smrg#ifdef ECHOCTL 2593d522f475Smrg d_tio.c_lflag |= ECHOCTL | IEXTEN; 2594d522f475Smrg#endif 2595d522f475Smrg#ifndef USE_POSIX_TERMIOS 2596d522f475Smrg#ifdef NTTYDISC 2597d522f475Smrg d_tio.c_line = NTTYDISC; 2598d522f475Smrg#else 2599d522f475Smrg d_tio.c_line = 0; 2600d522f475Smrg#endif 2601d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 2602d522f475Smrg#ifdef __sgi 2603d522f475Smrg d_tio.c_cflag &= ~(HUPCL | PARENB); 2604d522f475Smrg d_tio.c_iflag |= BRKINT | ISTRIP | IGNPAR; 2605d522f475Smrg#endif 2606d522f475Smrg#ifdef __MVS__ 2607d522f475Smrg d_tio.c_cflag &= ~(HUPCL | PARENB); 2608d522f475Smrg#endif 2609d522f475Smrg { 2610d522f475Smrg Cardinal nn; 2611d522f475Smrg int i; 2612d522f475Smrg 2613d522f475Smrg /* try to inherit tty settings */ 2614d522f475Smrg for (i = 0; i <= 2; i++) { 2615d522f475Smrg TERMIO_STRUCT deftio; 2616d522f475Smrg if (ttyGetAttr(i, &deftio) == 0) { 2617f2e35a3aSmrg for (nn = 0; nn < XtNumber(ttyChars); ++nn) { 2618d522f475Smrg if (validTtyChar(d_tio, nn)) { 2619f2e35a3aSmrg d_tio.c_cc[ttyChars[nn].sysMode] = 2620f2e35a3aSmrg deftio.c_cc[ttyChars[nn].sysMode]; 2621d522f475Smrg } 2622d522f475Smrg } 2623d522f475Smrg break; 2624d522f475Smrg } 2625d522f475Smrg } 2626d522f475Smrg } 2627d522f475Smrg#if defined(USE_TERMIOS) || defined(USE_POSIX_TERMIOS) /* { */ 2628d522f475Smrg d_tio.c_cc[VMIN] = 1; 2629d522f475Smrg d_tio.c_cc[VTIME] = 0; 2630d522f475Smrg#endif /* } */ 2631d522f475Smrg#ifdef HAS_LTCHARS /* { */ 2632d522f475Smrg d_ltc.t_suspc = CharOf('\000'); /* t_suspc */ 2633d522f475Smrg d_ltc.t_dsuspc = CharOf('\000'); /* t_dsuspc */ 2634d522f475Smrg d_ltc.t_rprntc = CharOf('\377'); /* reserved... */ 2635d522f475Smrg d_ltc.t_flushc = CharOf('\377'); 2636d522f475Smrg d_ltc.t_werasc = CharOf('\377'); 2637d522f475Smrg d_ltc.t_lnextc = CharOf('\377'); 2638d522f475Smrg#endif /* } HAS_LTCHARS */ 2639d522f475Smrg 2640d522f475Smrg#ifdef TIOCLSET /* { */ 2641d522f475Smrg d_lmode = 0; 2642d522f475Smrg#endif /* } TIOCLSET */ 2643d522f475Smrg#endif /* } macII, ATT, CRAY */ 2644d522f475Smrg#endif /* } TERMIO_STRUCT */ 2645d522f475Smrg 2646d522f475Smrg /* Init the Toolkit. */ 2647d522f475Smrg { 2648d522f475Smrg#if defined(HAVE_POSIX_SAVED_IDS) && !defined(USE_UTMP_SETGID) && !defined(USE_UTEMPTER) 2649d522f475Smrg setEffectiveGroup(save_rgid); 2650d522f475Smrg setEffectiveUser(save_ruid); 2651d522f475Smrg TRACE_IDS; 2652d522f475Smrg#endif 26530bd37d32Smrg toplevel = xtermOpenApplication(&app_con, 26540bd37d32Smrg my_class, 26550bd37d32Smrg optionDescList, 26560bd37d32Smrg XtNumber(optionDescList), 2657f2e35a3aSmrg &argc, argv, 26580bd37d32Smrg fallback_resources, 26590bd37d32Smrg sessionShellWidgetClass, 26600bd37d32Smrg NULL, 0); 2661ae137402Smrg TRACE(("created toplevel widget %p, window %#lx\n", 2662ae137402Smrg (void *) toplevel, XtWindow(toplevel))); 2663d522f475Smrg 2664d522f475Smrg XtGetApplicationResources(toplevel, (XtPointer) &resource, 2665d522f475Smrg application_resources, 2666d522f475Smrg XtNumber(application_resources), NULL, 0); 2667d522f475Smrg TRACE_XRES(); 2668ad37e533Smrg#ifdef HAVE_LIB_XCURSOR 2669ad37e533Smrg if (!strcmp(resource.cursorTheme, "none")) { 2670ad37e533Smrg TRACE(("startup with no cursorTheme\n")); 2671ad37e533Smrg init_colored_cursor(XtDisplay(toplevel)); 2672ad37e533Smrg } else { 2673ad37e533Smrg const char *theme = resource.cursorTheme; 2674ad37e533Smrg if (IsEmpty(theme)) 2675ad37e533Smrg theme = "default"; 2676ad37e533Smrg TRACE(("startup with \"%s\" cursorTheme\n", theme)); 2677ad37e533Smrg xtermSetenv("XCURSOR_THEME", theme); 2678ad37e533Smrg } 2679ad37e533Smrg#endif 2680f2e35a3aSmrg#if USE_DOUBLE_BUFFER 2681f2e35a3aSmrg if (resource.buffered_fps <= 0) 2682f2e35a3aSmrg resource.buffered_fps = DEF_BUFFER_RATE; 2683f2e35a3aSmrg if (resource.buffered_fps > 100) 2684f2e35a3aSmrg resource.buffered_fps = 100; 2685f2e35a3aSmrg#endif 2686a1f3da82Smrg#if OPT_MAXIMIZE 2687a1f3da82Smrg resource.fullscreen = extendedBoolean(resource.fullscreen_s, 2688a1f3da82Smrg tblFullscreen, 2689f2e35a3aSmrg esLAST); 2690a1f3da82Smrg#endif 2691e39b573cSmrg VTInitTranslations(); 2692d522f475Smrg#if OPT_PTY_HANDSHAKE 2693d522f475Smrg resource.wait_for_map0 = resource.wait_for_map; 2694d522f475Smrg#endif 2695d522f475Smrg 2696d522f475Smrg#if defined(HAVE_POSIX_SAVED_IDS) && !defined(USE_UTMP_SETGID) 2697d522f475Smrg#if !defined(DISABLE_SETUID) || !defined(DISABLE_SETGID) 2698d522f475Smrg#if !defined(DISABLE_SETUID) 2699d522f475Smrg setEffectiveUser(save_euid); 2700d522f475Smrg#endif 2701d522f475Smrg#if !defined(DISABLE_SETGID) 2702d522f475Smrg setEffectiveGroup(save_egid); 2703d522f475Smrg#endif 2704d522f475Smrg TRACE_IDS; 2705d522f475Smrg#endif 2706d522f475Smrg#endif 2707d522f475Smrg } 2708d522f475Smrg 2709d522f475Smrg /* 2710d522f475Smrg * ICCCM delete_window. 2711d522f475Smrg */ 2712d522f475Smrg XtAppAddActions(app_con, actionProcs, XtNumber(actionProcs)); 2713d522f475Smrg 2714d522f475Smrg /* 2715d522f475Smrg * fill in terminal modes 2716d522f475Smrg */ 2717d522f475Smrg if (resource.tty_modes) { 2718f2e35a3aSmrg int n = parse_tty_modes(resource.tty_modes); 2719d522f475Smrg if (n < 0) { 27200bd37d32Smrg xtermWarning("bad tty modes \"%s\"\n", resource.tty_modes); 2721d522f475Smrg } else if (n > 0) { 2722d522f475Smrg override_tty_modes = True; 2723d522f475Smrg } 2724d522f475Smrg } 27250bd37d32Smrg initZIconBeep(); 2726d522f475Smrg hold_screen = resource.hold_screen ? 1 : 0; 2727d522f475Smrg if (resource.icon_geometry != NULL) { 2728d522f475Smrg int scr, junk; 2729d522f475Smrg int ix, iy; 2730d522f475Smrg Arg args[2]; 2731d522f475Smrg 2732d522f475Smrg for (scr = 0; /* yyuucchh */ 2733d522f475Smrg XtScreen(toplevel) != ScreenOfDisplay(XtDisplay(toplevel), scr); 2734d522f475Smrg scr++) ; 2735d522f475Smrg 2736d522f475Smrg args[0].name = XtNiconX; 2737d522f475Smrg args[1].name = XtNiconY; 2738d522f475Smrg XGeometry(XtDisplay(toplevel), scr, resource.icon_geometry, "", 2739d522f475Smrg 0, 0, 0, 0, 0, &ix, &iy, &junk, &junk); 2740d522f475Smrg args[0].value = (XtArgVal) ix; 2741d522f475Smrg args[1].value = (XtArgVal) iy; 2742d522f475Smrg XtSetValues(toplevel, args, 2); 2743d522f475Smrg } 2744d522f475Smrg 2745d522f475Smrg XtSetValues(toplevel, ourTopLevelShellArgs, 2746d522f475Smrg number_ourTopLevelShellArgs); 2747d522f475Smrg 2748d522f475Smrg#if OPT_WIDE_CHARS 2749d522f475Smrg /* seems as good a place as any */ 2750d522f475Smrg init_classtab(); 2751d522f475Smrg#endif 2752d522f475Smrg 2753d522f475Smrg /* Parse the rest of the command line */ 2754d522f475Smrg TRACE_ARGV("After XtOpenApplication", argv); 2755d522f475Smrg for (argc--, argv++; argc > 0; argc--, argv++) { 27560bd37d32Smrg if (!isOption(*argv)) { 2757d522f475Smrg#ifdef VMS 2758d522f475Smrg Syntax(*argv); 2759d522f475Smrg#else 2760d522f475Smrg if (argc > 1) 2761d522f475Smrg Syntax(*argv); 2762d522f475Smrg continue; 2763d522f475Smrg#endif 27640bd37d32Smrg } 2765d522f475Smrg 2766d522f475Smrg TRACE(("parsing %s\n", argv[0])); 2767d522f475Smrg switch (argv[0][1]) { 2768d522f475Smrg case 'C': 2769d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 2770d522f475Smrg#ifndef __sgi 2771d522f475Smrg { 2772d522f475Smrg struct stat sbuf; 2773d522f475Smrg 2774d522f475Smrg /* Must be owner and have read/write permission. 2775d522f475Smrg xdm cooperates to give the console the right user. */ 2776d522f475Smrg if (!stat("/dev/console", &sbuf) && 2777d522f475Smrg (sbuf.st_uid == save_ruid) && 2778d522f475Smrg !access("/dev/console", R_OK | W_OK)) { 2779d522f475Smrg Console = True; 2780d522f475Smrg } else 2781d522f475Smrg Console = False; 2782d522f475Smrg } 2783d522f475Smrg#else /* __sgi */ 2784d522f475Smrg Console = True; 2785d522f475Smrg#endif /* __sgi */ 2786d522f475Smrg#endif /* TIOCCONS */ 2787d522f475Smrg continue; 2788d522f475Smrg case 'S': 2789d522f475Smrg if (!ParseSccn(*argv + 2)) 2790d522f475Smrg Syntax(*argv); 2791d522f475Smrg continue; 2792d522f475Smrg#ifdef DEBUG 2793d522f475Smrg case 'D': 2794d522f475Smrg debug = True; 2795d522f475Smrg continue; 2796d522f475Smrg#endif /* DEBUG */ 27972e4f8982Smrg case 'b': 27982e4f8982Smrg if (strcmp(argv[0], "-baudrate")) 27992e4f8982Smrg Syntax(*argv); 2800f2e35a3aSmrg argc--; 2801f2e35a3aSmrg argv++; 28022e4f8982Smrg continue; 28030bd37d32Smrg case 'c': 28040bd37d32Smrg if (strcmp(argv[0], "-class")) 2805d522f475Smrg Syntax(*argv); 2806f2e35a3aSmrg argc--; 2807f2e35a3aSmrg argv++; 2808d522f475Smrg continue; 2809d522f475Smrg case 'e': 28100bd37d32Smrg if (strcmp(argv[0], "-e")) 2811d522f475Smrg Syntax(*argv); 28120bd37d32Smrg command_to_exec = (argv + 1); 2813d522f475Smrg break; 2814d522f475Smrg case 'i': 28150bd37d32Smrg if (strcmp(argv[0], "-into")) 2816d522f475Smrg Syntax(*argv); 2817f2e35a3aSmrg argc--; 2818f2e35a3aSmrg argv++; 2819d522f475Smrg continue; 2820d522f475Smrg 2821d522f475Smrg default: 2822d522f475Smrg Syntax(*argv); 2823d522f475Smrg } 2824d522f475Smrg break; 2825d522f475Smrg } 2826d522f475Smrg 2827d522f475Smrg SetupMenus(toplevel, &form_top, &menu_top, &menu_high); 2828d522f475Smrg 2829d522f475Smrg term = (XtermWidget) XtVaCreateManagedWidget("vt100", xtermWidgetClass, 2830d522f475Smrg form_top, 2831d522f475Smrg#if OPT_TOOLBAR 2832d522f475Smrg XtNmenuBar, menu_top, 2833d522f475Smrg XtNresizable, True, 2834d522f475Smrg XtNfromVert, menu_top, 2835d522f475Smrg XtNleft, XawChainLeft, 2836d522f475Smrg XtNright, XawChainRight, 2837d522f475Smrg XtNtop, XawChainTop, 2838d522f475Smrg XtNbottom, XawChainBottom, 2839d522f475Smrg XtNmenuHeight, menu_high, 2840d522f475Smrg#endif 2841d522f475Smrg (XtPointer) 0); 2842ae137402Smrg TRACE(("created vt100 widget %p, window %#lx\n", 2843ae137402Smrg (void *) term, XtWindow(term))); 2844d522f475Smrg decode_keyboard_type(term, &resource); 2845d522f475Smrg 2846d522f475Smrg screen = TScreenOf(term); 2847d522f475Smrg screen->inhibit = 0; 2848d522f475Smrg 2849d522f475Smrg#ifdef ALLOWLOGGING 2850d522f475Smrg if (term->misc.logInhibit) 2851d522f475Smrg screen->inhibit |= I_LOG; 2852d522f475Smrg#endif 2853d522f475Smrg if (term->misc.signalInhibit) 2854d522f475Smrg screen->inhibit |= I_SIGNAL; 2855d522f475Smrg#if OPT_TEK4014 2856d522f475Smrg if (term->misc.tekInhibit) 2857d522f475Smrg screen->inhibit |= I_TEK; 2858d522f475Smrg#endif 2859d522f475Smrg 2860d522f475Smrg /* 2861d522f475Smrg * We might start by showing the tek4014 window. 2862d522f475Smrg */ 2863d522f475Smrg#if OPT_TEK4014 2864d522f475Smrg if (screen->inhibit & I_TEK) 2865d522f475Smrg TEK4014_ACTIVE(term) = False; 2866d522f475Smrg 2867d522f475Smrg if (TEK4014_ACTIVE(term) && !TekInit()) 2868d522f475Smrg SysError(ERROR_INIT); 2869d522f475Smrg#endif 2870d522f475Smrg 2871d522f475Smrg /* 2872d522f475Smrg * Start the toolbar at this point, after the first window has been setup. 2873d522f475Smrg */ 2874d522f475Smrg#if OPT_TOOLBAR 2875d522f475Smrg ShowToolbar(resource.toolBar); 2876d522f475Smrg#endif 2877d522f475Smrg 28780bd37d32Smrg xtermOpenSession(); 2879d522f475Smrg 2880d522f475Smrg /* 2881d522f475Smrg * Set title and icon name if not specified 2882d522f475Smrg */ 2883d522f475Smrg if (command_to_exec) { 2884d522f475Smrg Arg args[2]; 2885d522f475Smrg 28865307cd1aSmrg if (!resource.title) 28875307cd1aSmrg resource.title = x_basename(command_to_exec[0]); 2888d522f475Smrg if (!resource.icon_name) 2889d522f475Smrg resource.icon_name = resource.title; 28905307cd1aSmrg 2891d522f475Smrg XtSetArg(args[0], XtNtitle, resource.title); 2892d522f475Smrg XtSetArg(args[1], XtNiconName, resource.icon_name); 2893d522f475Smrg 28940bd37d32Smrg TRACE(("setting:\n\ttitle \"%s\"\n\ticon \"%s\"\n\thint \"%s\"\n\tbased on command \"%s\"\n", 2895d522f475Smrg resource.title, 2896d522f475Smrg resource.icon_name, 28970bd37d32Smrg NonNull(resource.icon_hint), 2898d522f475Smrg *command_to_exec)); 2899d522f475Smrg 2900d522f475Smrg XtSetValues(toplevel, args, 2); 29015307cd1aSmrg } else if (IsEmpty(resource.title) && strcmp(my_class, DEFCLASS)) { 29025307cd1aSmrg Arg args[2]; 29035307cd1aSmrg int n; 29045307cd1aSmrg 29055307cd1aSmrg resource.title = x_strdup(my_class); 29065307cd1aSmrg for (n = 0; resource.title[n]; ++n) { 29075307cd1aSmrg if (isalpha(CharOf(resource.title[n]))) 29085307cd1aSmrg resource.title[n] = (char) tolower(resource.title[n]); 29095307cd1aSmrg } 29105307cd1aSmrg TRACE(("setting:\n\ttitle \"%s\"\n", resource.title)); 29115307cd1aSmrg XtSetArg(args[0], XtNtitle, resource.title); 29125307cd1aSmrg XtSetValues(toplevel, args, 1); 2913d522f475Smrg } 2914d522f475Smrg#if OPT_LUIT_PROG 2915d522f475Smrg if (term->misc.callfilter) { 29160bd37d32Smrg char **split_filter = x_splitargs(term->misc.localefilter); 29170bd37d32Smrg unsigned count_split = x_countargv(split_filter); 29180bd37d32Smrg unsigned count_exec = x_countargv(command_to_exec); 29190bd37d32Smrg unsigned count_using = (unsigned) (term->misc.use_encoding ? 2 : 0); 29200bd37d32Smrg 29210bd37d32Smrg command_to_exec_with_luit = TypeCallocN(char *, 29220bd37d32Smrg (count_split 29230bd37d32Smrg + count_exec 29240bd37d32Smrg + count_using 29250bd37d32Smrg + 8)); 29260bd37d32Smrg if (command_to_exec_with_luit == NULL) 29270bd37d32Smrg SysError(ERROR_LUMALLOC); 29280bd37d32Smrg 29290bd37d32Smrg x_appendargv(command_to_exec_with_luit, split_filter); 29300bd37d32Smrg if (count_using) { 29310bd37d32Smrg char *encoding_opt[4]; 29320bd37d32Smrg encoding_opt[0] = x_strdup("-encoding"); 29330bd37d32Smrg encoding_opt[1] = term->misc.locale_str; 29340bd37d32Smrg encoding_opt[2] = 0; 29350bd37d32Smrg x_appendargv(command_to_exec_with_luit, encoding_opt); 29360bd37d32Smrg } 29370bd37d32Smrg command_length_with_luit = x_countargv(command_to_exec_with_luit); 29380bd37d32Smrg if (count_exec) { 29392e4f8982Smrg static char *fixup_shell[] = 2940f2e35a3aSmrg {(char *) "sh", (char *) "-c", 0}; 29410bd37d32Smrg char *delimiter[2]; 29420bd37d32Smrg delimiter[0] = x_strdup("--"); 29430bd37d32Smrg delimiter[1] = 0; 29440bd37d32Smrg x_appendargv(command_to_exec_with_luit, delimiter); 29452e4f8982Smrg if (complex_command(command_to_exec)) { 29462e4f8982Smrg x_appendargv(command_to_exec_with_luit, fixup_shell); 29472e4f8982Smrg } 29480bd37d32Smrg x_appendargv(command_to_exec_with_luit, command_to_exec); 2949d522f475Smrg } 29500bd37d32Smrg TRACE_ARGV("luit command", command_to_exec_with_luit); 29510bd37d32Smrg xtermSetenv("XTERM_FILTER", *command_to_exec_with_luit); 2952d522f475Smrg } 2953d522f475Smrg#endif 2954d522f475Smrg 29550bd37d32Smrg if_DEBUG({ 2956d522f475Smrg /* Set up stderr properly. Opening this log file cannot be 2957d522f475Smrg done securely by a privileged xterm process (although we try), 2958d522f475Smrg so the debug feature is disabled by default. */ 2959e39b573cSmrg char dbglogfile[TIMESTAMP_LEN + 20]; 2960d522f475Smrg int i = -1; 29610bd37d32Smrg timestamp_filename(dbglogfile, "xterm.debug.log."); 29620bd37d32Smrg if (creat_as(save_ruid, save_rgid, False, dbglogfile, 0600) > 0) { 29630bd37d32Smrg i = open(dbglogfile, O_WRONLY | O_TRUNC); 2964d522f475Smrg } 2965d522f475Smrg if (i >= 0) { 2966d522f475Smrg dup2(i, 2); 2967d522f475Smrg 2968d522f475Smrg /* mark this file as close on exec */ 2969d522f475Smrg (void) fcntl(i, F_SETFD, 1); 2970d522f475Smrg } 29710bd37d32Smrg }); 2972d522f475Smrg 29732e4f8982Smrg spawnXTerm(term, line_speed); 2974d522f475Smrg 2975d522f475Smrg#ifndef VMS 2976d522f475Smrg /* Child process is out there, let's catch its termination */ 2977d522f475Smrg 2978d522f475Smrg#ifdef USE_POSIX_SIGNALS 2979d522f475Smrg (void) posix_signal(SIGCHLD, reapchild); 2980d522f475Smrg#else 2981d522f475Smrg (void) signal(SIGCHLD, reapchild); 2982d522f475Smrg#endif 2983d522f475Smrg /* Realize procs have now been executed */ 2984d522f475Smrg 2985d522f475Smrg if (am_slave >= 0) { /* Write window id so master end can read and use */ 2986d522f475Smrg char buf[80]; 2987d522f475Smrg 2988d522f475Smrg buf[0] = '\0'; 2989d522f475Smrg sprintf(buf, "%lx\n", XtWindow(SHELL_OF(CURRENT_EMU()))); 299020d2c4d2Smrg IGNORE_RC(write(screen->respond, buf, strlen(buf))); 2991d522f475Smrg } 2992d522f475Smrg#ifdef AIXV3 2993d522f475Smrg#if (OSMAJORVERSION < 4) 2994d522f475Smrg /* In AIXV3, xterms started from /dev/console have CLOCAL set. 2995d522f475Smrg * This means we need to clear CLOCAL so that SIGHUP gets sent 2996d522f475Smrg * to the slave-pty process when xterm exits. 2997d522f475Smrg */ 2998d522f475Smrg 2999d522f475Smrg { 3000d522f475Smrg TERMIO_STRUCT tio; 3001d522f475Smrg 3002d522f475Smrg if (ttyGetAttr(screen->respond, &tio) == -1) 3003d522f475Smrg SysError(ERROR_TIOCGETP); 3004d522f475Smrg 3005d522f475Smrg tio.c_cflag &= ~(CLOCAL); 3006d522f475Smrg 3007d522f475Smrg if (ttySetAttr(screen->respond, &tio) == -1) 3008d522f475Smrg SysError(ERROR_TIOCSETP); 3009d522f475Smrg } 3010d522f475Smrg#endif 3011d522f475Smrg#endif 301201037d57Smrg#if defined(USE_ANY_SYSV_TERMIO) || defined(__MVS__) || defined(__minix) 3013d522f475Smrg if (0 > (mode = fcntl(screen->respond, F_GETFL, 0))) 3014d522f475Smrg SysError(ERROR_F_GETFL); 3015d522f475Smrg#ifdef O_NDELAY 3016d522f475Smrg mode |= O_NDELAY; 3017d522f475Smrg#else 3018d522f475Smrg mode |= O_NONBLOCK; 3019d522f475Smrg#endif /* O_NDELAY */ 3020d522f475Smrg if (fcntl(screen->respond, F_SETFL, mode)) 3021d522f475Smrg SysError(ERROR_F_SETFL); 3022d522f475Smrg#else /* !USE_ANY_SYSV_TERMIO */ 3023d522f475Smrg mode = 1; 3024d522f475Smrg if (ioctl(screen->respond, FIONBIO, (char *) &mode) == -1) 3025d522f475Smrg SysError(ERROR_FIONBIO); 3026d522f475Smrg#endif /* USE_ANY_SYSV_TERMIO, etc */ 3027d522f475Smrg 3028d522f475Smrg /* The erase character is used to delete the current completion */ 3029d522f475Smrg#if OPT_DABBREV 3030d522f475Smrg#ifdef TERMIO_STRUCT 3031d522f475Smrg screen->dabbrev_erase_char = d_tio.c_cc[VERASE]; 3032d522f475Smrg#else 3033d522f475Smrg screen->dabbrev_erase_char = d_sg.sg_erase; 3034d522f475Smrg#endif 3035d522f475Smrg TRACE(("set dabbrev erase_char %#x\n", screen->dabbrev_erase_char)); 3036d522f475Smrg#endif 3037d522f475Smrg 3038d522f475Smrg FD_ZERO(&pty_mask); 3039d522f475Smrg FD_ZERO(&X_mask); 3040d522f475Smrg FD_ZERO(&Select_mask); 3041d522f475Smrg FD_SET(screen->respond, &pty_mask); 3042d522f475Smrg FD_SET(ConnectionNumber(screen->display), &X_mask); 3043d522f475Smrg FD_SET(screen->respond, &Select_mask); 3044d522f475Smrg FD_SET(ConnectionNumber(screen->display), &Select_mask); 3045d522f475Smrg max_plus1 = ((screen->respond < ConnectionNumber(screen->display)) 3046d522f475Smrg ? (1 + ConnectionNumber(screen->display)) 3047d522f475Smrg : (1 + screen->respond)); 3048d522f475Smrg 3049d522f475Smrg#endif /* !VMS */ 30500bd37d32Smrg if_DEBUG({ 30510bd37d32Smrg TRACE(("debugging on pid %d\n", (int) getpid())); 30520bd37d32Smrg }); 3053d522f475Smrg XSetErrorHandler(xerror); 3054d522f475Smrg XSetIOErrorHandler(xioerror); 305501037d57Smrg#if OPT_SESSION_MGT 3056e39b573cSmrg IceSetIOErrorHandler(ice_error); 305701037d57Smrg#endif 3058d522f475Smrg 3059d522f475Smrg initPtyData(&VTbuffer); 3060d522f475Smrg#ifdef ALLOWLOGGING 3061d522f475Smrg if (term->misc.log_on) { 306220d2c4d2Smrg StartLog(term); 3063d522f475Smrg } 3064d522f475Smrg#endif 3065d522f475Smrg 30660bd37d32Smrg xtermEmbedWindow(winToEmbedInto); 3067a5ae21e4Smrg 3068a1f3da82Smrg TRACE(("checking reverseVideo before rv %s fg %s, bg %s\n", 3069a1f3da82Smrg term->misc.re_verse0 ? "reverse" : "normal", 307020d2c4d2Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_FG].resource), 307120d2c4d2Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_BG].resource))); 3072d522f475Smrg 3073a1f3da82Smrg if (term->misc.re_verse0) { 3074a1f3da82Smrg if (isDefaultForeground(TScreenOf(term)->Tcolors[TEXT_FG].resource) 3075a1f3da82Smrg && isDefaultBackground(TScreenOf(term)->Tcolors[TEXT_BG].resource)) { 3076a1f3da82Smrg TScreenOf(term)->Tcolors[TEXT_FG].resource = x_strdup(XtDefaultBackground); 3077a1f3da82Smrg TScreenOf(term)->Tcolors[TEXT_BG].resource = x_strdup(XtDefaultForeground); 3078a1f3da82Smrg } else { 3079a1f3da82Smrg ReverseVideo(term); 3080a1f3da82Smrg } 3081a1f3da82Smrg term->misc.re_verse = True; 3082a1f3da82Smrg update_reversevideo(); 3083a1f3da82Smrg TRACE(("updated reverseVideo after rv %s fg %s, bg %s\n", 3084a1f3da82Smrg term->misc.re_verse ? "reverse" : "normal", 3085a1f3da82Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_FG].resource), 3086a1f3da82Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_BG].resource))); 3087a1f3da82Smrg } 3088956cc18dSsnj#if OPT_MAXIMIZE 3089956cc18dSsnj if (resource.maximized) 3090956cc18dSsnj RequestMaximize(term, True); 3091956cc18dSsnj#endif 3092d522f475Smrg for (;;) { 3093d522f475Smrg#if OPT_TEK4014 3094d522f475Smrg if (TEK4014_ACTIVE(term)) 3095d522f475Smrg TekRun(); 3096d522f475Smrg else 3097d522f475Smrg#endif 3098956cc18dSsnj VTRun(term); 3099d522f475Smrg } 3100d522f475Smrg} 3101d522f475Smrg 310204b94745Smrg#if defined(__osf__) || (defined(__linux__) && !defined(USE_USG_PTYS)) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) 3103d522f475Smrg#define USE_OPENPTY 1 3104d522f475Smrgstatic int opened_tty = -1; 3105d522f475Smrg#endif 3106d522f475Smrg 3107d522f475Smrg/* 3108d522f475Smrg * This function opens up a pty master and stuffs its value into pty. 3109d522f475Smrg * 3110d522f475Smrg * If it finds one, it returns a value of 0. If it does not find one, 3111d522f475Smrg * it returns a value of !0. This routine is designed to be re-entrant, 3112d522f475Smrg * so that if a pty master is found and later, we find that the slave 3113d522f475Smrg * has problems, we can re-enter this function and get another one. 3114d522f475Smrg */ 3115d522f475Smrgstatic int 3116d522f475Smrgget_pty(int *pty, char *from GCC_UNUSED) 3117d522f475Smrg{ 3118d522f475Smrg int result = 1; 3119d522f475Smrg 31200bd37d32Smrg#if defined(USE_OPENPTY) 31210bd37d32Smrg result = openpty(pty, &opened_tty, ttydev, NULL, NULL); 31222e4f8982Smrg if (opened_tty >= 0) { 31232e4f8982Smrg close(opened_tty); 31242e4f8982Smrg opened_tty = -1; 31252e4f8982Smrg } 31260bd37d32Smrg#elif defined(HAVE_POSIX_OPENPT) && defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT_PTY_ISATTY) 31270bd37d32Smrg if ((*pty = posix_openpt(O_RDWR)) >= 0) { 31280bd37d32Smrg char *name = ptsname(*pty); 31290bd37d32Smrg if (name != 0) { 31300bd37d32Smrg strcpy(ttydev, name); 31310bd37d32Smrg result = 0; 31320bd37d32Smrg } 31330bd37d32Smrg } 31340bd37d32Smrg#ifdef USE_PTY_SEARCH 31350bd37d32Smrg if (result) { 31360bd37d32Smrg result = pty_search(pty); 31370bd37d32Smrg } 31380bd37d32Smrg#endif 31390bd37d32Smrg#elif defined(PUCC_PTYD) 3140d522f475Smrg result = ((*pty = openrpty(ttydev, ptydev, 3141d522f475Smrg (resource.utmpInhibit ? OPTY_NOP : OPTY_LOGIN), 3142d522f475Smrg save_ruid, from)) < 0); 3143d522f475Smrg#elif defined(__QNXNTO__) 3144d522f475Smrg result = pty_search(pty); 3145d522f475Smrg#else 3146d522f475Smrg#if defined(USE_USG_PTYS) || defined(__CYGWIN__) 3147f2e35a3aSmrg#if defined(__MVS__) 3148d522f475Smrg result = pty_search(pty); 3149d522f475Smrg#else 31500bd37d32Smrg result = ((*pty = open("/dev/ptmx", O_RDWR)) < 0); 3151d522f475Smrg#endif 31520bd37d32Smrg#if defined(SVR4) || defined(__SCO__) 31530bd37d32Smrg if (!result) 31540bd37d32Smrg strcpy(ttydev, ptsname(*pty)); 3155d522f475Smrg#endif 3156d522f475Smrg 3157d522f475Smrg#elif defined(AIXV3) 3158d522f475Smrg 3159d522f475Smrg if ((*pty = open("/dev/ptc", O_RDWR)) >= 0) { 3160d522f475Smrg strcpy(ttydev, ttyname(*pty)); 3161d522f475Smrg result = 0; 3162d522f475Smrg } 3163d522f475Smrg#elif defined(__convex__) 3164d522f475Smrg 3165d522f475Smrg char *pty_name; 3166d522f475Smrg extern char *getpty(void); 3167d522f475Smrg 3168d522f475Smrg while ((pty_name = getpty()) != NULL) { 3169d522f475Smrg if ((*pty = open(pty_name, O_RDWR)) >= 0) { 3170d522f475Smrg strcpy(ptydev, pty_name); 3171d522f475Smrg strcpy(ttydev, pty_name); 3172d522f475Smrg *x_basename(ttydev) = 't'; 3173d522f475Smrg result = 0; 3174d522f475Smrg break; 3175d522f475Smrg } 3176d522f475Smrg } 3177d522f475Smrg 3178d522f475Smrg#elif defined(sequent) 3179d522f475Smrg 3180d522f475Smrg result = ((*pty = getpseudotty(&ttydev, &ptydev)) < 0); 3181d522f475Smrg 3182d522f475Smrg#elif defined(__sgi) && (OSMAJORVERSION >= 4) 3183d522f475Smrg 3184d522f475Smrg char *tty_name; 3185d522f475Smrg 3186d522f475Smrg tty_name = _getpty(pty, O_RDWR, 0622, 0); 3187d522f475Smrg if (tty_name != 0) { 3188d522f475Smrg strcpy(ttydev, tty_name); 3189d522f475Smrg result = 0; 3190d522f475Smrg } 3191d522f475Smrg#elif (defined(__sgi) && (OSMAJORVERSION < 4)) || (defined(umips) && defined (SYSTYPE_SYSV)) 3192d522f475Smrg 3193d522f475Smrg struct stat fstat_buf; 3194d522f475Smrg 3195d522f475Smrg *pty = open("/dev/ptc", O_RDWR); 3196d522f475Smrg if (*pty >= 0 && (fstat(*pty, &fstat_buf)) >= 0) { 3197d522f475Smrg result = 0; 3198d522f475Smrg sprintf(ttydev, "/dev/ttyq%d", minor(fstat_buf.st_rdev)); 3199d522f475Smrg } 3200d522f475Smrg#elif defined(__hpux) 3201d522f475Smrg 3202d522f475Smrg /* 3203d522f475Smrg * Use the clone device if it works, otherwise use pty_search logic. 3204d522f475Smrg */ 3205d522f475Smrg if ((*pty = open("/dev/ptym/clone", O_RDWR)) >= 0) { 3206d522f475Smrg char *name = ptsname(*pty); 3207d522f475Smrg if (name != 0) { 3208d522f475Smrg strcpy(ttydev, name); 3209d522f475Smrg result = 0; 3210d522f475Smrg } else { /* permissions, or other unexpected problem */ 3211d522f475Smrg close(*pty); 3212d522f475Smrg *pty = -1; 3213d522f475Smrg result = pty_search(pty); 3214d522f475Smrg } 3215d522f475Smrg } else { 3216d522f475Smrg result = pty_search(pty); 3217d522f475Smrg } 3218d522f475Smrg 3219d522f475Smrg#else 3220d522f475Smrg 3221d522f475Smrg result = pty_search(pty); 3222d522f475Smrg 3223d522f475Smrg#endif 3224d522f475Smrg#endif 3225d522f475Smrg 3226d522f475Smrg TRACE(("get_pty(ttydev=%s, ptydev=%s) %s fd=%d\n", 3227d522f475Smrg ttydev != 0 ? ttydev : "?", 3228d522f475Smrg ptydev != 0 ? ptydev : "?", 3229d522f475Smrg result ? "FAIL" : "OK", 3230d522f475Smrg pty != 0 ? *pty : -1)); 3231d522f475Smrg return result; 3232d522f475Smrg} 3233d522f475Smrg 3234d522f475Smrgstatic void 3235e0a2b6dfSmrgset_pty_permissions(uid_t uid, unsigned gid, unsigned mode) 3236d522f475Smrg{ 3237d522f475Smrg#ifdef USE_TTY_GROUP 3238d522f475Smrg struct group *ttygrp; 3239d522f475Smrg 3240d522f475Smrg if ((ttygrp = getgrnam(TTY_GROUP_NAME)) != 0) { 3241913cc679Smrg gid = (unsigned) ttygrp->gr_gid; 3242d522f475Smrg mode &= 0660U; 3243d522f475Smrg } 3244d522f475Smrg endgrent(); 3245d522f475Smrg#endif /* USE_TTY_GROUP */ 3246d522f475Smrg 3247d522f475Smrg TRACE_IDS; 3248913cc679Smrg set_owner(ttydev, (unsigned) uid, gid, mode); 3249d522f475Smrg} 3250d522f475Smrg 3251d522f475Smrg#ifdef get_pty /* USE_UTMP_SETGID */ 3252d522f475Smrg#undef get_pty 3253d522f475Smrg/* 3254d522f475Smrg * Call the real get_pty() before relinquishing root-setuid, caching the 3255d522f475Smrg * result. 3256d522f475Smrg */ 3257d522f475Smrgstatic int 3258d522f475Smrgget_pty(int *pty, char *from) 3259d522f475Smrg{ 3260d522f475Smrg static int m_pty = -1; 3261d522f475Smrg int result = -1; 3262d522f475Smrg 3263d522f475Smrg if (pty == NULL) { 3264d522f475Smrg result = really_get_pty(&m_pty, from); 3265d522f475Smrg 3266d522f475Smrg seteuid(0); 3267d522f475Smrg set_pty_permissions(save_ruid, save_rgid, 0600U); 3268d522f475Smrg seteuid(save_ruid); 3269d522f475Smrg TRACE_IDS; 3270d522f475Smrg 3271d522f475Smrg } else if (m_pty != -1) { 3272d522f475Smrg *pty = m_pty; 3273d522f475Smrg result = 0; 3274d522f475Smrg } else { 3275d522f475Smrg result = -1; 3276d522f475Smrg } 32770bd37d32Smrg TRACE(("get_pty(ttydev=%s, ptydev=%s) %s fd=%d (utmp setgid)\n", 32780bd37d32Smrg ttydev != 0 ? ttydev : "?", 32790bd37d32Smrg ptydev != 0 ? ptydev : "?", 32800bd37d32Smrg result ? "FAIL" : "OK", 32810bd37d32Smrg pty != 0 ? *pty : -1)); 32822e4f8982Smrg#ifdef USE_OPENPTY 32832e4f8982Smrg if (opened_tty >= 0) { 32842e4f8982Smrg close(opened_tty); 32852e4f8982Smrg opened_tty = -1; 32862e4f8982Smrg } 32872e4f8982Smrg#endif 3288d522f475Smrg return result; 3289d522f475Smrg} 3290d522f475Smrg#endif 3291d522f475Smrg 3292d522f475Smrg/* 3293d522f475Smrg * Called from get_pty to iterate over likely pseudo terminals 3294d522f475Smrg * we might allocate. Used on those systems that do not have 3295d522f475Smrg * a functional interface for allocating a pty. 3296d522f475Smrg * Returns 0 if found a pty, 1 if fails. 3297d522f475Smrg */ 3298d522f475Smrg#ifdef USE_PTY_SEARCH 3299d522f475Smrgstatic int 3300d522f475Smrgpty_search(int *pty) 3301d522f475Smrg{ 3302d522f475Smrg static int devindex = 0, letter = 0; 3303d522f475Smrg 3304d522f475Smrg#if defined(CRAY) || defined(__MVS__) 3305d522f475Smrg while (devindex < MAXPTTYS) { 3306d522f475Smrg sprintf(ttydev, TTYFORMAT, devindex); 3307d522f475Smrg sprintf(ptydev, PTYFORMAT, devindex); 3308d522f475Smrg devindex++; 3309d522f475Smrg 3310d522f475Smrg TRACE(("pty_search(ttydev=%s, ptydev=%s)\n", ttydev, ptydev)); 3311d522f475Smrg if ((*pty = open(ptydev, O_RDWR)) >= 0) { 3312d522f475Smrg return 0; 3313d522f475Smrg } 3314d522f475Smrg } 3315d522f475Smrg#else /* CRAY || __MVS__ */ 3316d522f475Smrg while (PTYCHAR1[letter]) { 3317d522f475Smrg ttydev[strlen(ttydev) - 2] = 3318d522f475Smrg ptydev[strlen(ptydev) - 2] = PTYCHAR1[letter]; 3319d522f475Smrg 3320d522f475Smrg while (PTYCHAR2[devindex]) { 3321d522f475Smrg ttydev[strlen(ttydev) - 1] = 3322d522f475Smrg ptydev[strlen(ptydev) - 1] = PTYCHAR2[devindex]; 3323d522f475Smrg devindex++; 3324d522f475Smrg 3325d522f475Smrg TRACE(("pty_search(ttydev=%s, ptydev=%s)\n", ttydev, ptydev)); 3326d522f475Smrg if ((*pty = open(ptydev, O_RDWR)) >= 0) { 3327d522f475Smrg#ifdef sun 3328d522f475Smrg /* Need to check the process group of the pty. 3329d522f475Smrg * If it exists, then the slave pty is in use, 3330d522f475Smrg * and we need to get another one. 3331d522f475Smrg */ 3332d522f475Smrg int pgrp_rtn; 3333d522f475Smrg if (ioctl(*pty, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) { 3334d522f475Smrg close(*pty); 3335d522f475Smrg continue; 3336d522f475Smrg } 3337d522f475Smrg#endif /* sun */ 3338d522f475Smrg return 0; 3339d522f475Smrg } 3340d522f475Smrg } 3341d522f475Smrg devindex = 0; 3342d522f475Smrg letter++; 3343d522f475Smrg } 3344d522f475Smrg#endif /* CRAY else */ 3345d522f475Smrg /* 3346d522f475Smrg * We were unable to allocate a pty master! Return an error 3347d522f475Smrg * condition and let our caller terminate cleanly. 3348d522f475Smrg */ 3349d522f475Smrg return 1; 3350d522f475Smrg} 3351d522f475Smrg#endif /* USE_PTY_SEARCH */ 3352d522f475Smrg 3353d522f475Smrg/* 3354d522f475Smrg * The only difference in /etc/termcap between 4014 and 4015 is that 3355d522f475Smrg * the latter has support for switching character sets. We support the 3356d522f475Smrg * 4015 protocol, but ignore the character switches. Therefore, we 3357d522f475Smrg * choose 4014 over 4015. 3358d522f475Smrg * 3359d522f475Smrg * Features of the 4014 over the 4012: larger (19") screen, 12-bit 3360d522f475Smrg * graphics addressing (compatible with 4012 10-bit addressing), 3361d522f475Smrg * special point plot mode, incremental plot mode (not implemented in 3362d522f475Smrg * later Tektronix terminals), and 4 character sizes. 3363d522f475Smrg * All of these are supported by xterm. 3364d522f475Smrg */ 3365d522f475Smrg 3366d522f475Smrg#if OPT_TEK4014 336701037d57Smrgstatic const char *const tekterm[] = 3368d522f475Smrg{ 3369d522f475Smrg "tek4014", 3370d522f475Smrg "tek4015", /* 4014 with APL character set support */ 3371d522f475Smrg "tek4012", /* 4010 with lower case */ 3372d522f475Smrg "tek4013", /* 4012 with APL character set support */ 3373d522f475Smrg "tek4010", /* small screen, upper-case only */ 3374d522f475Smrg "dumb", 3375d522f475Smrg 0 3376d522f475Smrg}; 3377d522f475Smrg#endif 3378d522f475Smrg 3379d522f475Smrg/* The VT102 is a VT100 with the Advanced Video Option included standard. 3380d522f475Smrg * It also adds Escape sequences for insert/delete character/line. 3381d522f475Smrg * The VT220 adds 8-bit character sets, selective erase. 3382d522f475Smrg * The VT320 adds a 25th status line, terminal state interrogation. 3383d522f475Smrg * The VT420 has up to 48 lines on the screen. 3384d522f475Smrg */ 3385d522f475Smrg 338601037d57Smrgstatic const char *const vtterm[] = 3387d522f475Smrg{ 3388d522f475Smrg#ifdef USE_X11TERM 3389d522f475Smrg "x11term", /* for people who want special term name */ 3390d522f475Smrg#endif 3391d522f475Smrg DFT_TERMTYPE, /* for people who want special term name */ 3392f2e35a3aSmrg "xterm", /* the preferred name, should be fastest */ 3393d522f475Smrg "vt102", 3394d522f475Smrg "vt100", 3395d522f475Smrg "ansi", 3396d522f475Smrg "dumb", 3397d522f475Smrg 0 3398d522f475Smrg}; 3399d522f475Smrg 3400d522f475Smrg/* ARGSUSED */ 34010bd37d32Smrgstatic void 3402d522f475Smrghungtty(int i GCC_UNUSED) 3403d522f475Smrg{ 34040bd37d32Smrg DEBUG_MSG("handle:hungtty\n"); 3405d522f475Smrg siglongjmp(env, 1); 3406d522f475Smrg} 3407d522f475Smrg 3408d522f475Smrg#if OPT_PTY_HANDSHAKE 3409d522f475Smrg#define NO_FDS {-1, -1} 3410d522f475Smrg 3411d522f475Smrgstatic int cp_pipe[2] = NO_FDS; /* this pipe is used for child to parent transfer */ 3412d522f475Smrgstatic int pc_pipe[2] = NO_FDS; /* this pipe is used for parent to child transfer */ 3413d522f475Smrg 3414d522f475Smrgtypedef enum { /* c == child, p == parent */ 3415d522f475Smrg PTY_BAD, /* c->p: can't open pty slave for some reason */ 3416d522f475Smrg PTY_FATALERROR, /* c->p: we had a fatal error with the pty */ 3417d522f475Smrg PTY_GOOD, /* c->p: we have a good pty, let's go on */ 3418d522f475Smrg PTY_NEW, /* p->c: here is a new pty slave, try this */ 3419d522f475Smrg PTY_NOMORE, /* p->c; no more pty's, terminate */ 3420d522f475Smrg UTMP_ADDED, /* c->p: utmp entry has been added */ 3421d522f475Smrg UTMP_TTYSLOT, /* c->p: here is my ttyslot */ 3422d522f475Smrg PTY_EXEC /* p->c: window has been mapped the first time */ 3423d522f475Smrg} status_t; 3424d522f475Smrg 3425f2e35a3aSmrg#define HANDSHAKE_LEN 1024 3426f2e35a3aSmrg 3427d522f475Smrgtypedef struct { 3428d522f475Smrg status_t status; 3429d522f475Smrg int error; 3430d522f475Smrg int fatal_error; 3431d522f475Smrg int tty_slot; 3432d522f475Smrg int rows; 3433d522f475Smrg int cols; 3434f2e35a3aSmrg char buffer[HANDSHAKE_LEN]; 3435d522f475Smrg} handshake_t; 3436d522f475Smrg 3437f2e35a3aSmrg/* the buffer is large enough that we can always have a trailing null */ 3438f2e35a3aSmrg#define copy_handshake(dst, src) \ 3439f2e35a3aSmrg strncpy(dst.buffer, src, (size_t)HANDSHAKE_LEN - 1)[HANDSHAKE_LEN - 1] = '\0' 3440f2e35a3aSmrg 3441d522f475Smrg#if OPT_TRACE 3442d522f475Smrgstatic void 3443d522f475Smrgtrace_handshake(const char *tag, handshake_t * data) 3444d522f475Smrg{ 3445d522f475Smrg const char *status = "?"; 3446d522f475Smrg switch (data->status) { 3447d522f475Smrg case PTY_BAD: 3448d522f475Smrg status = "PTY_BAD"; 3449d522f475Smrg break; 3450d522f475Smrg case PTY_FATALERROR: 3451d522f475Smrg status = "PTY_FATALERROR"; 3452d522f475Smrg break; 3453d522f475Smrg case PTY_GOOD: 3454d522f475Smrg status = "PTY_GOOD"; 3455d522f475Smrg break; 3456d522f475Smrg case PTY_NEW: 3457d522f475Smrg status = "PTY_NEW"; 3458d522f475Smrg break; 3459d522f475Smrg case PTY_NOMORE: 3460d522f475Smrg status = "PTY_NOMORE"; 3461d522f475Smrg break; 3462d522f475Smrg case UTMP_ADDED: 3463d522f475Smrg status = "UTMP_ADDED"; 3464d522f475Smrg break; 3465d522f475Smrg case UTMP_TTYSLOT: 3466d522f475Smrg status = "UTMP_TTYSLOT"; 3467d522f475Smrg break; 3468d522f475Smrg case PTY_EXEC: 3469d522f475Smrg status = "PTY_EXEC"; 3470d522f475Smrg break; 3471d522f475Smrg } 3472d522f475Smrg TRACE(("handshake %s %s errno=%d, error=%d device \"%s\"\n", 3473d522f475Smrg tag, 3474d522f475Smrg status, 3475d522f475Smrg data->error, 3476d522f475Smrg data->fatal_error, 3477d522f475Smrg data->buffer)); 3478d522f475Smrg} 3479d522f475Smrg#define TRACE_HANDSHAKE(tag, data) trace_handshake(tag, data) 3480d522f475Smrg#else 3481d522f475Smrg#define TRACE_HANDSHAKE(tag, data) /* nothing */ 3482d522f475Smrg#endif 3483d522f475Smrg 3484d522f475Smrg/* HsSysError() 3485d522f475Smrg * 3486d522f475Smrg * This routine does the equivalent of a SysError but it handshakes 3487d522f475Smrg * over the errno and error exit to the master process so that it can 3488d522f475Smrg * display our error message and exit with our exit code so that the 3489d522f475Smrg * user can see it. 3490d522f475Smrg */ 3491d522f475Smrg 3492d522f475Smrgstatic void 3493d522f475SmrgHsSysError(int error) 3494d522f475Smrg{ 3495d522f475Smrg handshake_t handshake; 3496d522f475Smrg 3497d522f475Smrg memset(&handshake, 0, sizeof(handshake)); 3498d522f475Smrg handshake.status = PTY_FATALERROR; 3499d522f475Smrg handshake.error = errno; 3500d522f475Smrg handshake.fatal_error = error; 3501f2e35a3aSmrg copy_handshake(handshake, ttydev); 3502d522f475Smrg 3503d522f475Smrg if (resource.ptyHandshake && (cp_pipe[1] >= 0)) { 3504d522f475Smrg TRACE(("HsSysError errno=%d, error=%d device \"%s\"\n", 3505d522f475Smrg handshake.error, 3506d522f475Smrg handshake.fatal_error, 3507d522f475Smrg handshake.buffer)); 3508d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 350920d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], 351020d2c4d2Smrg (const char *) &handshake, 351120d2c4d2Smrg sizeof(handshake))); 3512d522f475Smrg } else { 35130bd37d32Smrg xtermWarning("fatal pty error errno=%d, error=%d device \"%s\"\n", 35140bd37d32Smrg handshake.error, 35150bd37d32Smrg handshake.fatal_error, 35160bd37d32Smrg handshake.buffer); 3517d522f475Smrg fprintf(stderr, "%s\n", SysErrorMsg(handshake.error)); 3518d522f475Smrg fprintf(stderr, "Reason: %s\n", SysReasonMsg(handshake.fatal_error)); 3519d522f475Smrg } 3520d522f475Smrg exit(error); 3521d522f475Smrg} 3522d522f475Smrg 3523d522f475Smrgvoid 3524d522f475Smrgfirst_map_occurred(void) 3525d522f475Smrg{ 3526d522f475Smrg if (resource.wait_for_map) { 3527913cc679Smrg if (pc_pipe[1] >= 0) { 3528913cc679Smrg handshake_t handshake; 3529913cc679Smrg TScreen *screen = TScreenOf(term); 3530d522f475Smrg 3531913cc679Smrg memset(&handshake, 0, sizeof(handshake)); 3532913cc679Smrg handshake.status = PTY_EXEC; 3533913cc679Smrg handshake.rows = screen->max_row; 3534913cc679Smrg handshake.cols = screen->max_col; 3535d522f475Smrg 3536913cc679Smrg TRACE(("first_map_occurred: %dx%d\n", MaxRows(screen), MaxCols(screen))); 3537d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 353820d2c4d2Smrg IGNORE_RC(write(pc_pipe[1], 353920d2c4d2Smrg (const char *) &handshake, 354020d2c4d2Smrg sizeof(handshake))); 3541d522f475Smrg close(cp_pipe[0]); 3542d522f475Smrg close(pc_pipe[1]); 3543d522f475Smrg } 3544d522f475Smrg resource.wait_for_map = False; 3545d522f475Smrg } 3546d522f475Smrg} 3547d522f475Smrg#else 3548d522f475Smrg/* 3549d522f475Smrg * temporary hack to get xterm working on att ptys 3550d522f475Smrg */ 3551d522f475Smrgstatic void 3552d522f475SmrgHsSysError(int error) 3553d522f475Smrg{ 35540bd37d32Smrg xtermWarning("fatal pty error %d (errno=%d) on tty %s\n", 35550bd37d32Smrg error, errno, ttydev); 3556d522f475Smrg exit(error); 3557d522f475Smrg} 3558d522f475Smrg#endif /* OPT_PTY_HANDSHAKE else !OPT_PTY_HANDSHAKE */ 3559d522f475Smrg 3560d522f475Smrg#ifndef VMS 3561d522f475Smrgstatic void 3562e0a2b6dfSmrgset_owner(char *device, unsigned uid, unsigned gid, unsigned mode) 3563d522f475Smrg{ 3564d522f475Smrg int why; 3565d522f475Smrg 3566d522f475Smrg TRACE_IDS; 356720d2c4d2Smrg TRACE(("set_owner(%s, uid=%d, gid=%d, mode=%#o\n", 35680bd37d32Smrg device, (int) uid, (int) gid, (unsigned) mode)); 3569d522f475Smrg 3570913cc679Smrg if (chown(device, (uid_t) uid, (gid_t) gid) < 0) { 3571d522f475Smrg why = errno; 3572d522f475Smrg if (why != ENOENT 3573d522f475Smrg && save_ruid == 0) { 35740bd37d32Smrg xtermPerror("Cannot chown %s to %ld,%ld", 35750bd37d32Smrg device, (long) uid, (long) gid); 3576d522f475Smrg } 3577d522f475Smrg TRACE(("...chown failed: %s\n", strerror(why))); 3578913cc679Smrg } else if (chmod(device, (mode_t) mode) < 0) { 3579d522f475Smrg why = errno; 3580d522f475Smrg if (why != ENOENT) { 3581d522f475Smrg struct stat sb; 3582d522f475Smrg if (stat(device, &sb) < 0) { 35830bd37d32Smrg xtermPerror("Cannot chmod %s to %03o", 35840bd37d32Smrg device, (unsigned) mode); 3585d522f475Smrg } else if (mode != (sb.st_mode & 0777U)) { 35860bd37d32Smrg xtermPerror("Cannot chmod %s to %03lo currently %03lo", 35870bd37d32Smrg device, 35880bd37d32Smrg (unsigned long) mode, 35890bd37d32Smrg (unsigned long) (sb.st_mode & 0777U)); 3590d522f475Smrg TRACE(("...stat uid=%d, gid=%d, mode=%#o\n", 35910bd37d32Smrg (int) sb.st_uid, (int) sb.st_gid, (unsigned) sb.st_mode)); 3592d522f475Smrg } 3593d522f475Smrg } 3594d522f475Smrg TRACE(("...chmod failed: %s\n", strerror(why))); 3595d522f475Smrg } 3596d522f475Smrg} 3597d522f475Smrg 3598894e0ac8Smrg/* 3599894e0ac8Smrg * utmp data may not be null-terminated; even if it is, there may be garbage 3600894e0ac8Smrg * after the null. This fills the unused part of the result with nulls. 3601894e0ac8Smrg */ 3602894e0ac8Smrgstatic void 3603894e0ac8Smrgcopy_filled(char *target, const char *source, size_t len) 3604894e0ac8Smrg{ 3605894e0ac8Smrg size_t used = 0; 3606894e0ac8Smrg while (used < len) { 3607894e0ac8Smrg if ((target[used] = source[used]) == 0) 3608894e0ac8Smrg break; 3609894e0ac8Smrg ++used; 3610894e0ac8Smrg } 3611894e0ac8Smrg while (used < len) { 3612894e0ac8Smrg target[used++] = '\0'; 3613894e0ac8Smrg } 3614894e0ac8Smrg} 3615894e0ac8Smrg 3616d522f475Smrg#if defined(HAVE_UTMP) && defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 3617d522f475Smrg/* 3618d522f475Smrg * getutid() only looks at ut_type and ut_id. 3619d522f475Smrg * But we'll also check ut_line in find_utmp(). 3620d522f475Smrg */ 3621d522f475Smrgstatic void 3622d522f475Smrginit_utmp(int type, struct UTMP_STR *tofind) 3623d522f475Smrg{ 3624d522f475Smrg memset(tofind, 0, sizeof(*tofind)); 3625913cc679Smrg tofind->ut_type = (short) type; 3626894e0ac8Smrg copy_filled(tofind->ut_id, my_utmp_id(ttydev), sizeof(tofind->ut_id)); 3627894e0ac8Smrg copy_filled(tofind->ut_line, my_pty_name(ttydev), sizeof(tofind->ut_line)); 3628d522f475Smrg} 3629d522f475Smrg 3630d522f475Smrg/* 3631d522f475Smrg * We could use getutline() if we didn't support old systems. 3632d522f475Smrg */ 3633d522f475Smrgstatic struct UTMP_STR * 3634d522f475Smrgfind_utmp(struct UTMP_STR *tofind) 3635d522f475Smrg{ 3636d522f475Smrg struct UTMP_STR *result; 36370bd37d32Smrg struct UTMP_STR limited; 3638d522f475Smrg struct UTMP_STR working; 3639d522f475Smrg 3640d522f475Smrg for (;;) { 3641d522f475Smrg memset(&working, 0, sizeof(working)); 3642d522f475Smrg working.ut_type = tofind->ut_type; 3643894e0ac8Smrg copy_filled(working.ut_id, tofind->ut_id, sizeof(tofind->ut_id)); 3644d522f475Smrg#if defined(__digital__) && defined(__unix__) && (defined(OSMAJORVERSION) && OSMAJORVERSION < 5) 3645d522f475Smrg working.ut_type = 0; 3646d522f475Smrg#endif 3647d522f475Smrg if ((result = call_getutid(&working)) == 0) 3648d522f475Smrg break; 3649894e0ac8Smrg copy_filled(limited.ut_line, result->ut_line, sizeof(result->ut_line)); 36500bd37d32Smrg if (!memcmp(limited.ut_line, tofind->ut_line, sizeof(limited.ut_line))) 3651d522f475Smrg break; 3652d522f475Smrg /* 3653d522f475Smrg * Solaris, IRIX64 and HPUX manpages say to fill the static area 3654d522f475Smrg * pointed to by the return-value to zeros if searching for multiple 3655d522f475Smrg * occurrences. Otherwise it will continue to return the same value. 3656d522f475Smrg */ 3657d522f475Smrg memset(result, 0, sizeof(*result)); 3658d522f475Smrg } 3659d522f475Smrg return result; 3660d522f475Smrg} 3661d522f475Smrg#endif /* HAVE_UTMP... */ 3662d522f475Smrg 3663d522f475Smrg#define close_fd(fd) close(fd), fd = -1 3664d522f475Smrg 366520d2c4d2Smrg#if defined(TIOCNOTTY) && (!defined(__GLIBC__) || (__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))) 366620d2c4d2Smrg#define USE_NO_DEV_TTY 1 366720d2c4d2Smrg#else 366820d2c4d2Smrg#define USE_NO_DEV_TTY 0 366920d2c4d2Smrg#endif 367020d2c4d2Smrg 3671e0a2b6dfSmrgstatic int 3672e0a2b6dfSmrgsame_leaf(char *a, char *b) 3673e0a2b6dfSmrg{ 3674e0a2b6dfSmrg char *p = x_basename(a); 3675e0a2b6dfSmrg char *q = x_basename(b); 3676e0a2b6dfSmrg return !strcmp(p, q); 3677e0a2b6dfSmrg} 3678e0a2b6dfSmrg 3679e0a2b6dfSmrg/* 3680e0a2b6dfSmrg * "good enough" (inode wouldn't port to Cygwin) 3681e0a2b6dfSmrg */ 3682e0a2b6dfSmrgstatic int 3683e0a2b6dfSmrgsame_file(const char *a, const char *b) 3684e0a2b6dfSmrg{ 3685e0a2b6dfSmrg struct stat asb; 3686e0a2b6dfSmrg struct stat bsb; 3687e0a2b6dfSmrg int result = 0; 3688e0a2b6dfSmrg 3689e0a2b6dfSmrg if ((stat(a, &asb) == 0) 3690e0a2b6dfSmrg && (stat(b, &bsb) == 0) 3691e0a2b6dfSmrg && ((asb.st_mode & S_IFMT) == S_IFREG) 3692e0a2b6dfSmrg && ((bsb.st_mode & S_IFMT) == S_IFREG) 3693e0a2b6dfSmrg && (asb.st_mtime == bsb.st_mtime) 3694e0a2b6dfSmrg && (asb.st_size == bsb.st_size)) { 3695e0a2b6dfSmrg result = 1; 3696e0a2b6dfSmrg } 3697e0a2b6dfSmrg return result; 3698e0a2b6dfSmrg} 3699e0a2b6dfSmrg 3700f2e35a3aSmrgstatic int 3701f2e35a3aSmrgfindValidShell(const char *haystack, const char *needle) 3702f2e35a3aSmrg{ 3703f2e35a3aSmrg int result = -1; 3704f2e35a3aSmrg int count = -1; 3705f2e35a3aSmrg const char *s, *t; 3706f2e35a3aSmrg size_t have; 3707f2e35a3aSmrg size_t want = strlen(needle); 3708f2e35a3aSmrg 3709f2e35a3aSmrg TRACE(("findValidShell:\n%s\n", NonNull(haystack))); 3710f2e35a3aSmrg 3711f2e35a3aSmrg for (s = haystack; (s != 0) && (*s != '\0'); s = t) { 3712f2e35a3aSmrg ++count; 3713f2e35a3aSmrg if ((t = strchr(s, '\n')) == 0) { 3714f2e35a3aSmrg t = s + strlen(s); 3715f2e35a3aSmrg } 3716f2e35a3aSmrg have = (size_t) (t - s); 3717f2e35a3aSmrg 3718f2e35a3aSmrg if ((have >= want) && (*s != '#')) { 37195307cd1aSmrg char *p = (char *) malloc(have + 1); 3720f2e35a3aSmrg 3721f2e35a3aSmrg if (p != 0) { 3722f2e35a3aSmrg char *q; 3723f2e35a3aSmrg 3724f2e35a3aSmrg memcpy(p, s, have); 3725f2e35a3aSmrg p[have] = '\0'; 3726f2e35a3aSmrg if ((q = x_strtrim(p)) != 0) { 3727f2e35a3aSmrg TRACE(("...test %s\n", q)); 3728f2e35a3aSmrg if (!strcmp(q, needle)) { 3729f2e35a3aSmrg result = count; 3730f2e35a3aSmrg } else if (same_leaf(q, (char *) needle) && 3731f2e35a3aSmrg same_file(q, needle)) { 3732f2e35a3aSmrg result = count; 3733f2e35a3aSmrg } 3734f2e35a3aSmrg free(q); 3735f2e35a3aSmrg } 3736f2e35a3aSmrg free(p); 3737f2e35a3aSmrg } 3738f2e35a3aSmrg if (result >= 0) 3739f2e35a3aSmrg break; 3740f2e35a3aSmrg } 3741f2e35a3aSmrg while (*t == '\n') { 3742f2e35a3aSmrg ++t; 3743f2e35a3aSmrg } 3744f2e35a3aSmrg } 3745f2e35a3aSmrg return result; 3746f2e35a3aSmrg} 3747f2e35a3aSmrg 3748f2e35a3aSmrgstatic int 3749f2e35a3aSmrgourValidShell(const char *pathname) 3750f2e35a3aSmrg{ 375104b94745Smrg char *trimmed = x_strtrim(resource.valid_shells); 375204b94745Smrg int result = findValidShell(trimmed, pathname); 375304b94745Smrg free(trimmed); 375404b94745Smrg return result; 3755f2e35a3aSmrg} 3756f2e35a3aSmrg 3757f2e35a3aSmrg#if defined(HAVE_GETUSERSHELL) && defined(HAVE_ENDUSERSHELL) 3758f2e35a3aSmrgstatic Boolean 3759f2e35a3aSmrgvalidShell(const char *pathname) 3760f2e35a3aSmrg{ 3761f2e35a3aSmrg int result = -1; 3762f2e35a3aSmrg 3763f2e35a3aSmrg if (validProgram(pathname)) { 3764f2e35a3aSmrg char *q; 3765f2e35a3aSmrg int count = -1; 3766f2e35a3aSmrg 3767f2e35a3aSmrg TRACE(("validShell:getusershell\n")); 3768f2e35a3aSmrg while ((q = getusershell()) != 0) { 3769f2e35a3aSmrg ++count; 3770f2e35a3aSmrg TRACE(("...test \"%s\"\n", q)); 3771f2e35a3aSmrg if (!strcmp(q, pathname)) { 3772f2e35a3aSmrg result = count; 3773f2e35a3aSmrg break; 3774f2e35a3aSmrg } 3775f2e35a3aSmrg } 3776f2e35a3aSmrg endusershell(); 3777f2e35a3aSmrg 3778f2e35a3aSmrg if (result < 0) 3779f2e35a3aSmrg result = ourValidShell(pathname); 3780f2e35a3aSmrg } 3781f2e35a3aSmrg 3782f2e35a3aSmrg TRACE(("validShell %s ->%d\n", NonNull(pathname), result)); 3783f2e35a3aSmrg return (result >= 0); 3784f2e35a3aSmrg} 3785f2e35a3aSmrg#else 3786e0a2b6dfSmrg/* 3787e0a2b6dfSmrg * Only set $SHELL for paths found in the standard location. 3788e0a2b6dfSmrg */ 3789e0a2b6dfSmrgstatic Boolean 3790e0a2b6dfSmrgvalidShell(const char *pathname) 3791e0a2b6dfSmrg{ 3792f2e35a3aSmrg int result = -1; 3793e0a2b6dfSmrg const char *ok_shells = "/etc/shells"; 3794e0a2b6dfSmrg char *blob; 3795e0a2b6dfSmrg struct stat sb; 3796e0a2b6dfSmrg size_t rc; 3797e0a2b6dfSmrg FILE *fp; 3798e0a2b6dfSmrg 3799f2e35a3aSmrg if (validProgram(pathname)) { 3800f2e35a3aSmrg 3801f2e35a3aSmrg TRACE(("validShell:%s\n", ok_shells)); 3802f2e35a3aSmrg 3803f2e35a3aSmrg if (stat(ok_shells, &sb) == 0 3804f2e35a3aSmrg && (sb.st_mode & S_IFMT) == S_IFREG 3805f2e35a3aSmrg && ((size_t) sb.st_size > 0) 3806f2e35a3aSmrg && ((size_t) sb.st_size < (((size_t) ~0) - 2)) 3807f2e35a3aSmrg && (blob = calloc((size_t) sb.st_size + 2, sizeof(char))) != 0) { 3808f2e35a3aSmrg 3809f2e35a3aSmrg if ((fp = fopen(ok_shells, "r")) != 0) { 3810f2e35a3aSmrg rc = fread(blob, sizeof(char), (size_t) sb.st_size, fp); 3811f2e35a3aSmrg fclose(fp); 3812f2e35a3aSmrg 3813f2e35a3aSmrg if (rc == (size_t) sb.st_size) { 3814f2e35a3aSmrg blob[rc] = '\0'; 3815f2e35a3aSmrg result = findValidShell(blob, pathname); 3816e0a2b6dfSmrg } 3817e0a2b6dfSmrg } 3818f2e35a3aSmrg free(blob); 3819e0a2b6dfSmrg } 3820f2e35a3aSmrg if (result < 0) 3821f2e35a3aSmrg result = ourValidShell(pathname); 3822e0a2b6dfSmrg } 3823e0a2b6dfSmrg TRACE(("validShell %s ->%d\n", NonNull(pathname), result)); 3824f2e35a3aSmrg return (result > 0); 3825e0a2b6dfSmrg} 3826f2e35a3aSmrg#endif 3827e0a2b6dfSmrg 3828e0a2b6dfSmrgstatic char * 3829e0a2b6dfSmrgresetShell(char *oldPath) 3830e0a2b6dfSmrg{ 3831e0a2b6dfSmrg char *newPath = x_strdup("/bin/sh"); 3832e0a2b6dfSmrg char *envPath = getenv("SHELL"); 3833f2e35a3aSmrg free(oldPath); 3834e0a2b6dfSmrg if (!IsEmpty(envPath)) 3835e0a2b6dfSmrg xtermSetenv("SHELL", newPath); 3836e0a2b6dfSmrg return newPath; 3837e0a2b6dfSmrg} 3838e0a2b6dfSmrg 38394419d26bSmrg/* 38404419d26bSmrg * Trim unwanted environment variables: 38414419d26bSmrg * 38424419d26bSmrg * DESKTOP_STARTUP_ID 38434419d26bSmrg * standards.freedesktop.org/startup-notification-spec/ 38444419d26bSmrg * notes that this variable is used when a "reliable" mechanism is 38454419d26bSmrg * not available; in practice it must be unset to avoid confusing 38464419d26bSmrg * GTK applications. 38474419d26bSmrg * 38484419d26bSmrg * XCURSOR_PATH 38494419d26bSmrg * We set this temporarily to work around poor design of Xcursor. Unset it 38504419d26bSmrg * here to avoid confusion. 38514419d26bSmrg * 38524419d26bSmrg * Other... 38534419d26bSmrg * These are set by other terminal emulators or non-standard libraries, and are 38544419d26bSmrg * a nuisance if one starts xterm from a shell inside one of those. 38554419d26bSmrg */ 38564419d26bSmrgstatic void 38574419d26bSmrgxtermTrimEnv(void) 38584419d26bSmrg{ 38595307cd1aSmrg#define KEEP(wild,name) { 0, wild, #name } 38605307cd1aSmrg#define TRIM(wild,name) { 1, wild, #name } 38615307cd1aSmrg /* *INDENT-OFF* */ 38625307cd1aSmrg static const struct { 38635307cd1aSmrg int trim; 38644419d26bSmrg int wild; 38654419d26bSmrg const char *name; 38664419d26bSmrg } table[] = { 38675307cd1aSmrg TRIM(0, COLUMNS), 38685307cd1aSmrg TRIM(0, DEFAULT_COLORS), 38695307cd1aSmrg TRIM(0, DESKTOP_STARTUP_ID), 38705307cd1aSmrg TRIM(0, LINES), 38715307cd1aSmrg TRIM(0, SHLVL), /* ksh, bash */ 38725307cd1aSmrg TRIM(0, STY), /* screen */ 38735307cd1aSmrg TRIM(0, TERMCAP), 38745307cd1aSmrg TRIM(0, TMUX), 38755307cd1aSmrg TRIM(0, TMUX_PANE), 38765307cd1aSmrg TRIM(0, WCWIDTH_CJK_LEGACY), 38775307cd1aSmrg TRIM(0, WINDOW), /* screen */ 38785307cd1aSmrg TRIM(0, XCURSOR_PATH), 38795307cd1aSmrg KEEP(0, MC_XDG_OPEN), 38805307cd1aSmrg TRIM(1, COLORFGBG), 38815307cd1aSmrg TRIM(1, COLORTERM), 38825307cd1aSmrg TRIM(1, GIO_LAUNCHED_), 38835307cd1aSmrg TRIM(1, ITERM2_), 38845307cd1aSmrg TRIM(1, MC_), 38855307cd1aSmrg TRIM(1, MINTTY_), 38865307cd1aSmrg TRIM(1, PUTTY), 38875307cd1aSmrg TRIM(1, RXVT_), 38885307cd1aSmrg TRIM(1, TERM_), 38895307cd1aSmrg TRIM(1, URXVT_), 38905307cd1aSmrg TRIM(1, VTE_), 38915307cd1aSmrg TRIM(1, XTERM_), 38924419d26bSmrg }; 38935307cd1aSmrg#undef TRIM 38945307cd1aSmrg /* *INDENT-ON* */ 38955307cd1aSmrg Cardinal j, k; 38965307cd1aSmrg 38975307cd1aSmrg for (j = 0; environ[j] != NULL; ++j) { 38985307cd1aSmrg char *equals = strchr(environ[j], '='); 38995307cd1aSmrg size_t dstlen = strlen(environ[j]); 39005307cd1aSmrg 39015307cd1aSmrg if (equals != NULL) 39025307cd1aSmrg dstlen = (size_t) (equals - environ[j]); 39035307cd1aSmrg 39045307cd1aSmrg for (k = 0; k < XtNumber(table); ++k) { 39055307cd1aSmrg size_t srclen = strlen(table[k].name); 39065307cd1aSmrg if (table[k].wild) { 39075307cd1aSmrg if (dstlen >= srclen && 39085307cd1aSmrg !strncmp(environ[j], table[k].name, srclen)) { 39094419d26bSmrg char *my_var; 39105307cd1aSmrg if (table[k].trim && 39115307cd1aSmrg (my_var = x_strdup(environ[j])) != NULL) { 39124419d26bSmrg my_var[dstlen] = '\0'; 39134419d26bSmrg xtermUnsetenv(my_var); 39144419d26bSmrg free(my_var); 391504b94745Smrg /* When removing an entry, check the same slot again. */ 391604b94745Smrg j--; 39174419d26bSmrg } 39185307cd1aSmrg break; 39194419d26bSmrg } 39205307cd1aSmrg } else if (dstlen == srclen && 39215307cd1aSmrg !strncmp(environ[j], table[k].name, srclen)) { 392204b94745Smrg if (table[k].trim) { 39235307cd1aSmrg xtermUnsetenv(table[k].name); 392404b94745Smrg /* When removing an entry, check the same slot again. */ 392504b94745Smrg j--; 392604b94745Smrg } 39275307cd1aSmrg break; 39284419d26bSmrg } 39294419d26bSmrg } 39304419d26bSmrg } 39314419d26bSmrg} 39324419d26bSmrg 3933d522f475Smrg/* 3934d522f475Smrg * Inits pty and tty and forks a login process. 3935d522f475Smrg * Does not close fd Xsocket. 3936d522f475Smrg * If slave, the pty named in passedPty is already open for use 3937d522f475Smrg */ 3938d522f475Smrgstatic int 39392e4f8982SmrgspawnXTerm(XtermWidget xw, unsigned line_speed) 3940d522f475Smrg{ 3941d522f475Smrg TScreen *screen = TScreenOf(xw); 3942d522f475Smrg Cardinal nn; 3943d522f475Smrg#if OPT_PTY_HANDSHAKE 3944d522f475Smrg Bool got_handshake_size = False; 3945d522f475Smrg handshake_t handshake; 3946d522f475Smrg int done; 3947d522f475Smrg#endif 3948d522f475Smrg#if OPT_INITIAL_ERASE 39495307cd1aSmrg int initial_erase = XTERM_ERASE; 3950d522f475Smrg Bool setInitialErase; 3951d522f475Smrg#endif 3952d522f475Smrg int rc = 0; 3953d522f475Smrg int ttyfd = -1; 3954d522f475Smrg Bool ok_termcap; 3955d522f475Smrg char *newtc; 3956d522f475Smrg 3957d522f475Smrg#ifdef TERMIO_STRUCT 3958d522f475Smrg TERMIO_STRUCT tio; 3959d522f475Smrg#ifdef __MVS__ 3960d522f475Smrg TERMIO_STRUCT gio; 3961d522f475Smrg#endif /* __MVS__ */ 3962d522f475Smrg#ifdef TIOCLSET 3963d522f475Smrg unsigned lmode; 3964d522f475Smrg#endif /* TIOCLSET */ 3965d522f475Smrg#ifdef HAS_LTCHARS 3966d522f475Smrg struct ltchars ltc; 3967d522f475Smrg#endif /* HAS_LTCHARS */ 3968d522f475Smrg#else /* !TERMIO_STRUCT */ 3969d522f475Smrg int ldisc = 0; 3970d522f475Smrg int discipline; 3971d522f475Smrg unsigned lmode; 3972d522f475Smrg struct tchars tc; 3973d522f475Smrg struct ltchars ltc; 3974d522f475Smrg struct sgttyb sg; 3975d522f475Smrg#ifdef sony 3976d522f475Smrg int jmode; 3977d522f475Smrg struct jtchars jtc; 3978d522f475Smrg#endif /* sony */ 3979d522f475Smrg#endif /* TERMIO_STRUCT */ 3980d522f475Smrg 39810bd37d32Smrg char *shell_path = 0; 39820bd37d32Smrg char *shname, *shname_minus; 398320d2c4d2Smrg int i; 398420d2c4d2Smrg#if USE_NO_DEV_TTY 398520d2c4d2Smrg int no_dev_tty = False; 398620d2c4d2Smrg#endif 398701037d57Smrg const char *const *envnew; /* new environment */ 3988d522f475Smrg char buf[64]; 3989d522f475Smrg char *TermName = NULL; 3990d522f475Smrg#ifdef TTYSIZE_STRUCT 3991d522f475Smrg TTYSIZE_STRUCT ts; 3992d522f475Smrg#endif 39930bd37d32Smrg struct passwd pw; 3994d522f475Smrg char *login_name = NULL; 3995d522f475Smrg#ifndef USE_UTEMPTER 3996d522f475Smrg#ifdef HAVE_UTMP 3997d522f475Smrg struct UTMP_STR utmp; 3998d522f475Smrg#ifdef USE_SYSV_UTMP 3999d522f475Smrg struct UTMP_STR *utret = NULL; 4000d522f475Smrg#endif 4001d522f475Smrg#ifdef USE_LASTLOG 4002d522f475Smrg struct lastlog lastlog; 4003d522f475Smrg#endif 4004d522f475Smrg#ifdef USE_LASTLOGX 4005d522f475Smrg struct lastlogx lastlogx; 4006d522f475Smrg#endif /* USE_LASTLOG */ 4007d522f475Smrg#endif /* HAVE_UTMP */ 4008d522f475Smrg#endif /* !USE_UTEMPTER */ 4009d522f475Smrg 4010e39b573cSmrg#if OPT_TRACE 4011e39b573cSmrg unsigned long xterm_parent = (unsigned long) getpid(); 4012e39b573cSmrg#endif 4013e39b573cSmrg 4014d522f475Smrg /* Noisy compilers (suppress some unused-variable warnings) */ 4015d522f475Smrg (void) rc; 4016d522f475Smrg#if defined(HAVE_UTMP) && defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 4017d522f475Smrg (void) utret; 4018d522f475Smrg#endif 4019d522f475Smrg 4020d522f475Smrg screen->uid = save_ruid; 4021d522f475Smrg screen->gid = save_rgid; 4022d522f475Smrg 4023d522f475Smrg#ifdef SIGTTOU 4024d522f475Smrg /* so that TIOCSWINSZ || TIOCSIZE doesn't block */ 4025d522f475Smrg signal(SIGTTOU, SIG_IGN); 4026d522f475Smrg#endif 4027d522f475Smrg 4028d522f475Smrg#if OPT_PTY_HANDSHAKE 4029d522f475Smrg memset(&handshake, 0, sizeof(handshake)); 4030d522f475Smrg#endif 4031d522f475Smrg 4032d522f475Smrg if (am_slave >= 0) { 4033d522f475Smrg screen->respond = am_slave; 4034d522f475Smrg set_pty_id(ttydev, passedPty); 4035d522f475Smrg#ifdef USE_PTY_DEVICE 4036d522f475Smrg set_pty_id(ptydev, passedPty); 4037d522f475Smrg#endif 4038d522f475Smrg if (xtermResetIds(screen) < 0) 403904b94745Smrg exit(ERROR_MISC); 4040d522f475Smrg } else { 4041d522f475Smrg Bool tty_got_hung; 4042d522f475Smrg 4043d522f475Smrg /* 4044d522f475Smrg * Sometimes /dev/tty hangs on open (as in the case of a pty 4045d522f475Smrg * that has gone away). Simply make up some reasonable 4046d522f475Smrg * defaults. 4047d522f475Smrg */ 4048d522f475Smrg 4049d522f475Smrg if (!sigsetjmp(env, 1)) { 4050913cc679Smrg signal(SIGALRM, hungtty); 4051913cc679Smrg alarm(2); /* alarm(1) might return too soon */ 4052d522f475Smrg ttyfd = open("/dev/tty", O_RDWR); 4053d522f475Smrg alarm(0); 4054d522f475Smrg tty_got_hung = False; 4055d522f475Smrg } else { 4056d522f475Smrg tty_got_hung = True; 4057d522f475Smrg ttyfd = -1; 4058d522f475Smrg errno = ENXIO; 4059d522f475Smrg } 40602e4f8982Smrg shell_path = 0; 40610bd37d32Smrg memset(&pw, 0, sizeof(pw)); 4062d522f475Smrg#if OPT_PTY_HANDSHAKE 4063d522f475Smrg got_handshake_size = False; 4064d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4065d522f475Smrg#if OPT_INITIAL_ERASE 40665307cd1aSmrg initial_erase = XTERM_ERASE; 4067d522f475Smrg#endif 4068d522f475Smrg signal(SIGALRM, SIG_DFL); 4069d522f475Smrg 4070d522f475Smrg /* 4071d522f475Smrg * Check results and ignore current control terminal if 4072d522f475Smrg * necessary. ENXIO is what is normally returned if there is 4073d522f475Smrg * no controlling terminal, but some systems (e.g. SunOS 4.0) 4074d522f475Smrg * seem to return EIO. Solaris 2.3 is said to return EINVAL. 40750bd37d32Smrg * Cygwin returns ENOENT. FreeBSD can return ENOENT, especially 40760bd37d32Smrg * if xterm is run within a jail. 4077d522f475Smrg */ 407820d2c4d2Smrg#if USE_NO_DEV_TTY 4079d522f475Smrg no_dev_tty = False; 408020d2c4d2Smrg#endif 4081d522f475Smrg if (ttyfd < 0) { 4082d522f475Smrg if (tty_got_hung || errno == ENXIO || errno == EIO || 40830bd37d32Smrg errno == ENOENT || 4084d522f475Smrg#ifdef ENODEV 4085d522f475Smrg errno == ENODEV || 4086d522f475Smrg#endif 4087d522f475Smrg errno == EINVAL || errno == ENOTTY || errno == EACCES) { 408820d2c4d2Smrg#if USE_NO_DEV_TTY 4089d522f475Smrg no_dev_tty = True; 409020d2c4d2Smrg#endif 4091d522f475Smrg#ifdef HAS_LTCHARS 4092d522f475Smrg ltc = d_ltc; 4093d522f475Smrg#endif /* HAS_LTCHARS */ 4094d522f475Smrg#ifdef TIOCLSET 4095d522f475Smrg lmode = d_lmode; 4096d522f475Smrg#endif /* TIOCLSET */ 4097d522f475Smrg#ifdef TERMIO_STRUCT 4098d522f475Smrg tio = d_tio; 4099d522f475Smrg#else /* !TERMIO_STRUCT */ 4100d522f475Smrg sg = d_sg; 4101d522f475Smrg tc = d_tc; 4102d522f475Smrg discipline = d_disipline; 4103d522f475Smrg#ifdef sony 4104d522f475Smrg jmode = d_jmode; 4105d522f475Smrg jtc = d_jtc; 4106d522f475Smrg#endif /* sony */ 4107d522f475Smrg#endif /* TERMIO_STRUCT */ 4108d522f475Smrg } else { 4109d522f475Smrg SysError(ERROR_OPDEVTTY); 4110d522f475Smrg } 4111d522f475Smrg } else { 4112d522f475Smrg 4113d522f475Smrg /* Get a copy of the current terminal's state, 4114d522f475Smrg * if we can. Some systems (e.g., SVR4 and MacII) 4115d522f475Smrg * may not have a controlling terminal at this point 4116d522f475Smrg * if started directly from xdm or xinit, 4117d522f475Smrg * in which case we just use the defaults as above. 4118d522f475Smrg */ 4119d522f475Smrg#ifdef HAS_LTCHARS 4120d522f475Smrg if (ioctl(ttyfd, TIOCGLTC, <c) == -1) 4121d522f475Smrg ltc = d_ltc; 4122d522f475Smrg#endif /* HAS_LTCHARS */ 4123d522f475Smrg#ifdef TIOCLSET 4124d522f475Smrg if (ioctl(ttyfd, TIOCLGET, &lmode) == -1) 4125d522f475Smrg lmode = d_lmode; 4126d522f475Smrg#endif /* TIOCLSET */ 4127d522f475Smrg#ifdef TERMIO_STRUCT 412820d2c4d2Smrg rc = ttyGetAttr(ttyfd, &tio); 412920d2c4d2Smrg if (rc == -1) 4130d522f475Smrg tio = d_tio; 4131d522f475Smrg#else /* !TERMIO_STRUCT */ 413220d2c4d2Smrg rc = ioctl(ttyfd, TIOCGETP, (char *) &sg); 413320d2c4d2Smrg if (rc == -1) 4134d522f475Smrg sg = d_sg; 4135d522f475Smrg if (ioctl(ttyfd, TIOCGETC, (char *) &tc) == -1) 4136d522f475Smrg tc = d_tc; 4137d522f475Smrg if (ioctl(ttyfd, TIOCGETD, (char *) &discipline) == -1) 4138d522f475Smrg discipline = d_disipline; 4139d522f475Smrg#ifdef sony 4140d522f475Smrg if (ioctl(ttyfd, TIOCKGET, (char *) &jmode) == -1) 4141d522f475Smrg jmode = d_jmode; 4142d522f475Smrg if (ioctl(ttyfd, TIOCKGETC, (char *) &jtc) == -1) 4143d522f475Smrg jtc = d_jtc; 4144d522f475Smrg#endif /* sony */ 4145d522f475Smrg#endif /* TERMIO_STRUCT */ 4146d522f475Smrg 4147d522f475Smrg /* 4148d522f475Smrg * If ptyInitialErase is set, we want to get the pty's 4149d522f475Smrg * erase value. Just in case that will fail, first get 4150d522f475Smrg * the value from /dev/tty, so we will have something 4151d522f475Smrg * at least. 4152d522f475Smrg */ 4153d522f475Smrg#if OPT_INITIAL_ERASE 4154d522f475Smrg if (resource.ptyInitialErase) { 4155d522f475Smrg#ifdef TERMIO_STRUCT 4156d522f475Smrg initial_erase = tio.c_cc[VERASE]; 4157d522f475Smrg#else /* !TERMIO_STRUCT */ 4158d522f475Smrg initial_erase = sg.sg_erase; 4159d522f475Smrg#endif /* TERMIO_STRUCT */ 4160d522f475Smrg TRACE(("%s initial_erase:%d (from /dev/tty)\n", 4161d522f475Smrg rc == 0 ? "OK" : "FAIL", 4162d522f475Smrg initial_erase)); 4163d522f475Smrg } 4164d522f475Smrg#endif 4165d522f475Smrg#ifdef __MVS__ 4166d522f475Smrg if (ttyGetAttr(ttyfd, &gio) == 0) { 4167d522f475Smrg gio.c_cflag &= ~(HUPCL | PARENB); 4168d522f475Smrg ttySetAttr(ttyfd, &gio); 4169d522f475Smrg } 4170d522f475Smrg#endif /* __MVS__ */ 4171d522f475Smrg 4172d522f475Smrg close_fd(ttyfd); 4173d522f475Smrg } 4174d522f475Smrg 4175d522f475Smrg if (get_pty(&screen->respond, XDisplayString(screen->display))) { 4176d522f475Smrg SysError(ERROR_PTYS); 4177d522f475Smrg } 4178913cc679Smrg TRACE_GET_TTYSIZE(screen->respond, "after get_pty"); 4179d522f475Smrg#if OPT_INITIAL_ERASE 4180d522f475Smrg if (resource.ptyInitialErase) { 41815307cd1aSmrg initial_erase = get_tty_erase(screen->respond, 41825307cd1aSmrg initial_erase, 41835307cd1aSmrg "pty"); 4184d522f475Smrg } 4185d522f475Smrg#endif /* OPT_INITIAL_ERASE */ 4186d522f475Smrg } 4187d522f475Smrg 4188d522f475Smrg /* avoid double MapWindow requests */ 4189d522f475Smrg XtSetMappedWhenManaged(SHELL_OF(CURRENT_EMU()), False); 4190d522f475Smrg 419104b94745Smrg wm_delete_window = CachedInternAtom(XtDisplay(toplevel), 419204b94745Smrg "WM_DELETE_WINDOW"); 4193d522f475Smrg 4194d522f475Smrg if (!TEK4014_ACTIVE(xw)) 4195956cc18dSsnj VTInit(xw); /* realize now so know window size for tty driver */ 4196d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 4197d522f475Smrg if (Console) { 4198d522f475Smrg /* 4199d522f475Smrg * Inform any running xconsole program 4200d522f475Smrg * that we are going to steal the console. 4201d522f475Smrg */ 4202d522f475Smrg XmuGetHostname(mit_console_name + MIT_CONSOLE_LEN, 255); 420304b94745Smrg TRACE(("getting for console name property \"%s\"\n", mit_console_name)); 420404b94745Smrg mit_console = CachedInternAtom(screen->display, mit_console_name); 4205d522f475Smrg /* the user told us to be the console, so we can use CurrentTime */ 4206d522f475Smrg XtOwnSelection(SHELL_OF(CURRENT_EMU()), 4207d522f475Smrg mit_console, CurrentTime, 4208d522f475Smrg ConvertConsoleSelection, NULL, NULL); 4209d522f475Smrg } 4210d522f475Smrg#endif 4211d522f475Smrg#if OPT_TEK4014 4212d522f475Smrg if (TEK4014_ACTIVE(xw)) { 4213d522f475Smrg envnew = tekterm; 4214d522f475Smrg } else 4215d522f475Smrg#endif 4216d522f475Smrg { 4217d522f475Smrg envnew = vtterm; 4218d522f475Smrg } 4219d522f475Smrg 4220d522f475Smrg /* 4221d522f475Smrg * This used to exit if no termcap entry was found for the specified 4222d522f475Smrg * terminal name. That's a little unfriendly, so instead we'll allow 4223d522f475Smrg * the program to proceed (but not to set $TERMCAP) if the termcap 4224d522f475Smrg * entry is not found. 4225d522f475Smrg */ 4226d522f475Smrg ok_termcap = True; 422720d2c4d2Smrg if (!get_termcap(xw, TermName = resource.term_name)) { 422820d2c4d2Smrg const char *last = NULL; 422920d2c4d2Smrg char *next; 423020d2c4d2Smrg 423120d2c4d2Smrg TermName = x_strdup(*envnew); 4232d522f475Smrg ok_termcap = False; 4233d522f475Smrg while (*envnew != NULL) { 423420d2c4d2Smrg if (last == NULL || strcmp(last, *envnew)) { 423520d2c4d2Smrg next = x_strdup(*envnew); 423620d2c4d2Smrg if (get_termcap(xw, next)) { 423720d2c4d2Smrg free(TermName); 423820d2c4d2Smrg TermName = next; 42390bd37d32Smrg ok_termcap = True + 1; 424020d2c4d2Smrg break; 424120d2c4d2Smrg } else { 424220d2c4d2Smrg free(next); 424320d2c4d2Smrg } 4244d522f475Smrg } 4245d522f475Smrg last = *envnew; 4246d522f475Smrg envnew++; 4247d522f475Smrg } 4248d522f475Smrg } 4249d522f475Smrg if (ok_termcap) { 4250f2e35a3aSmrg resource.term_name = x_strdup(TermName); 425120d2c4d2Smrg resize_termcap(xw); 4252d522f475Smrg } 4253d522f475Smrg 4254d522f475Smrg /* 4255d522f475Smrg * Check if ptyInitialErase is not set. If so, we rely on the termcap 4256d522f475Smrg * (or terminfo) to tell us what the erase mode should be set to. 4257d522f475Smrg */ 4258d522f475Smrg#if OPT_INITIAL_ERASE 4259d522f475Smrg TRACE(("resource ptyInitialErase is %sset\n", 4260d522f475Smrg resource.ptyInitialErase ? "" : "not ")); 4261d522f475Smrg setInitialErase = False; 4262f2e35a3aSmrg if (override_tty_modes && ttyModes[XTTYMODE_erase].set) { 4263f2e35a3aSmrg initial_erase = ttyModes[XTTYMODE_erase].value; 4264d522f475Smrg setInitialErase = True; 4265d522f475Smrg } else if (resource.ptyInitialErase) { 4266a1f3da82Smrg /* EMPTY */ ; 4267d522f475Smrg } else if (ok_termcap) { 426820d2c4d2Smrg char *s = get_tcap_erase(xw); 4269d522f475Smrg TRACE(("...extracting initial_erase value from termcap\n")); 4270d522f475Smrg if (s != 0) { 427120d2c4d2Smrg char *save = s; 4272d522f475Smrg initial_erase = decode_keyvalue(&s, True); 4273d522f475Smrg setInitialErase = True; 427420d2c4d2Smrg free(save); 4275d522f475Smrg } 4276d522f475Smrg } 4277d522f475Smrg TRACE(("...initial_erase:%d\n", initial_erase)); 4278d522f475Smrg 4279d522f475Smrg TRACE(("resource backarrowKeyIsErase is %sset\n", 4280d522f475Smrg resource.backarrow_is_erase ? "" : "not ")); 4281d522f475Smrg if (resource.backarrow_is_erase) { /* see input.c */ 4282d522f475Smrg if (initial_erase == ANSI_DEL) { 428320d2c4d2Smrg UIntClr(xw->keyboard.flags, MODE_DECBKM); 4284d522f475Smrg } else { 4285d522f475Smrg xw->keyboard.flags |= MODE_DECBKM; 4286d522f475Smrg xw->keyboard.reset_DECBKM = 1; 4287d522f475Smrg } 4288d522f475Smrg TRACE(("...sets DECBKM %s\n", 4289d522f475Smrg (xw->keyboard.flags & MODE_DECBKM) ? "on" : "off")); 4290d522f475Smrg } else { 4291d522f475Smrg xw->keyboard.reset_DECBKM = 2; 4292d522f475Smrg } 4293d522f475Smrg#endif /* OPT_INITIAL_ERASE */ 4294d522f475Smrg 4295d522f475Smrg#ifdef TTYSIZE_STRUCT 4296d522f475Smrg /* tell tty how big window is */ 4297d522f475Smrg#if OPT_TEK4014 4298d522f475Smrg if (TEK4014_ACTIVE(xw)) { 4299913cc679Smrg setup_winsize(ts, TDefaultRows, TDefaultCols, 4300913cc679Smrg TFullHeight(TekScreenOf(tekWidget)), 4301913cc679Smrg TFullWidth(TekScreenOf(tekWidget))); 4302d522f475Smrg } else 4303d522f475Smrg#endif 4304d522f475Smrg { 4305913cc679Smrg setup_winsize(ts, MaxRows(screen), MaxCols(screen), 4306913cc679Smrg FullHeight(screen), FullWidth(screen)); 4307d522f475Smrg } 430820d2c4d2Smrg TRACE_RC(i, SET_TTYSIZE(screen->respond, ts)); 4309d522f475Smrg TRACE(("spawn SET_TTYSIZE %dx%d return %d\n", 4310d522f475Smrg TTYSIZE_ROWS(ts), 4311d522f475Smrg TTYSIZE_COLS(ts), i)); 4312d522f475Smrg#endif /* TTYSIZE_STRUCT */ 4313d522f475Smrg 43140bd37d32Smrg#if !defined(USE_OPENPTY) 43150bd37d32Smrg#if defined(USE_USG_PTYS) || defined(HAVE_POSIX_OPENPT) 43160bd37d32Smrg /* 43170bd37d32Smrg * utempter checks the ownership of the device; some implementations 43180bd37d32Smrg * set ownership in grantpt - do this first. 43190bd37d32Smrg */ 43200bd37d32Smrg grantpt(screen->respond); 43210bd37d32Smrg#endif 43220bd37d32Smrg#if !defined(USE_USG_PTYS) && defined(HAVE_POSIX_OPENPT) 43230bd37d32Smrg unlockpt(screen->respond); 4324913cc679Smrg TRACE_GET_TTYSIZE(screen->respond, "after unlockpt"); 43250bd37d32Smrg#endif 43260bd37d32Smrg#endif /* !USE_OPENPTY */ 43270bd37d32Smrg 4328d522f475Smrg added_utmp_entry = False; 4329d522f475Smrg#if defined(USE_UTEMPTER) 4330d522f475Smrg#undef UTMP 43312e4f8982Smrg if ((xw->misc.login_shell || !command_to_exec) && !resource.utmpInhibit) { 4332d522f475Smrg struct UTMP_STR dummy; 4333d522f475Smrg 4334d522f475Smrg /* Note: utempter may trim it anyway */ 4335d522f475Smrg SetUtmpHost(dummy.ut_host, screen); 43360bd37d32Smrg TRACE(("...calling addToUtmp(pty=%s, hostname=%s, master_fd=%d)\n", 43370bd37d32Smrg ttydev, dummy.ut_host, screen->respond)); 4338f2e35a3aSmrg UTEMPTER_ADD(ttydev, dummy.ut_host, screen->respond); 4339d522f475Smrg added_utmp_entry = True; 4340d522f475Smrg } 4341d522f475Smrg#endif 4342d522f475Smrg 4343d522f475Smrg if (am_slave < 0) { 4344d522f475Smrg#if OPT_PTY_HANDSHAKE 4345d522f475Smrg if (resource.ptyHandshake && (pipe(pc_pipe) || pipe(cp_pipe))) 4346d522f475Smrg SysError(ERROR_FORK); 4347d522f475Smrg#endif 4348d522f475Smrg TRACE(("Forking...\n")); 4349d522f475Smrg if ((screen->pid = fork()) == -1) 4350d522f475Smrg SysError(ERROR_FORK); 4351d522f475Smrg 4352d522f475Smrg if (screen->pid == 0) { 4353d522f475Smrg#ifdef USE_USG_PTYS 435420d2c4d2Smrg int ptyfd = -1; 4355d522f475Smrg char *pty_name; 4356d522f475Smrg#endif 4357d522f475Smrg /* 4358d522f475Smrg * now in child process 4359d522f475Smrg */ 436004b94745Smrg#ifdef HAVE_SETSID 4361d522f475Smrg int pgrp = setsid(); /* variable may not be used... */ 4362d522f475Smrg#else 4363d522f475Smrg int pgrp = getpid(); 4364d522f475Smrg#endif 436504b94745Smrg TRACE_CHILD; 4366d522f475Smrg 4367d522f475Smrg#ifdef USE_USG_PTYS 43680bd37d32Smrg#ifdef HAVE_SETPGID 436904b94745Smrg setpgid(0, 0); 43700bd37d32Smrg#else 437104b94745Smrg setpgrp(); 43720bd37d32Smrg#endif 43730bd37d32Smrg unlockpt(screen->respond); 4374913cc679Smrg TRACE_GET_TTYSIZE(screen->respond, "after unlockpt"); 43750bd37d32Smrg if ((pty_name = ptsname(screen->respond)) == 0) { 43760bd37d32Smrg SysError(ERROR_PTSNAME); 43770bd37d32Smrg } else if ((ptyfd = open(pty_name, O_RDWR)) < 0) { 43780bd37d32Smrg SysError(ERROR_OPPTSNAME); 43790bd37d32Smrg } 4380d522f475Smrg#ifdef I_PUSH 43812e4f8982Smrg else if (PUSH_FAILS(ptyfd, "ptem")) { 43820bd37d32Smrg SysError(ERROR_PTEM); 43830bd37d32Smrg } 4384d522f475Smrg#if !defined(SVR4) && !(defined(SYSV) && defined(i386)) 43850bd37d32Smrg else if (!x_getenv("CONSEM") 43862e4f8982Smrg && PUSH_FAILS(ptyfd, "consem")) { 43870bd37d32Smrg SysError(ERROR_CONSEM); 43880bd37d32Smrg } 4389d522f475Smrg#endif /* !SVR4 */ 43902e4f8982Smrg else if (PUSH_FAILS(ptyfd, "ldterm")) { 43910bd37d32Smrg SysError(ERROR_LDTERM); 43920bd37d32Smrg } 4393d522f475Smrg#ifdef SVR4 /* from Sony */ 43942e4f8982Smrg else if (PUSH_FAILS(ptyfd, "ttcompat")) { 43950bd37d32Smrg SysError(ERROR_TTCOMPAT); 43960bd37d32Smrg } 4397d522f475Smrg#endif /* SVR4 */ 4398d522f475Smrg#endif /* I_PUSH */ 43990bd37d32Smrg ttyfd = ptyfd; 4400d522f475Smrg#ifndef __MVS__ 44010bd37d32Smrg close_fd(screen->respond); 4402d522f475Smrg#endif /* __MVS__ */ 4403d522f475Smrg 4404d522f475Smrg#ifdef TTYSIZE_STRUCT 44050bd37d32Smrg /* tell tty how big window is */ 4406d522f475Smrg#if OPT_TEK4014 44070bd37d32Smrg if (TEK4014_ACTIVE(xw)) { 4408913cc679Smrg setup_winsize(ts, TDefaultRows, TDefaultCols, 4409913cc679Smrg TFullHeight(TekScreenOf(tekWidget)), 4410913cc679Smrg TFullWidth(TekScreenOf(tekWidget))); 44110bd37d32Smrg } else 4412d522f475Smrg#endif /* OPT_TEK4014 */ 44130bd37d32Smrg { 4414913cc679Smrg setup_winsize(ts, MaxRows(screen), MaxCols(screen), 4415913cc679Smrg FullHeight(screen), FullWidth(screen)); 44160bd37d32Smrg } 4417913cc679Smrg trace_winsize(ts, "initial tty size"); 4418d522f475Smrg#endif /* TTYSIZE_STRUCT */ 4419d522f475Smrg 4420d522f475Smrg#endif /* USE_USG_PTYS */ 4421d522f475Smrg 44220bd37d32Smrg (void) pgrp; /* not all branches use this variable */ 4423d522f475Smrg 4424d522f475Smrg#if OPT_PTY_HANDSHAKE /* warning, goes for a long ways */ 44250bd37d32Smrg if (resource.ptyHandshake) { 44260bd37d32Smrg char *ptr; 4427d522f475Smrg 44280bd37d32Smrg /* close parent's sides of the pipes */ 44290bd37d32Smrg close(cp_pipe[0]); 44300bd37d32Smrg close(pc_pipe[1]); 44310bd37d32Smrg 44320bd37d32Smrg /* Make sure that our sides of the pipes are not in the 44330bd37d32Smrg * 0, 1, 2 range so that we don't fight with stdin, out 44340bd37d32Smrg * or err. 44350bd37d32Smrg */ 44360bd37d32Smrg if (cp_pipe[1] <= 2) { 44370bd37d32Smrg if ((i = fcntl(cp_pipe[1], F_DUPFD, 3)) >= 0) { 44380bd37d32Smrg IGNORE_RC(close(cp_pipe[1])); 44390bd37d32Smrg cp_pipe[1] = i; 4440d522f475Smrg } 44410bd37d32Smrg } 44420bd37d32Smrg if (pc_pipe[0] <= 2) { 44430bd37d32Smrg if ((i = fcntl(pc_pipe[0], F_DUPFD, 3)) >= 0) { 44440bd37d32Smrg IGNORE_RC(close(pc_pipe[0])); 44450bd37d32Smrg pc_pipe[0] = i; 4446d522f475Smrg } 44470bd37d32Smrg } 4448d522f475Smrg 44490bd37d32Smrg /* we don't need the socket, or the pty master anymore */ 44500bd37d32Smrg close(ConnectionNumber(screen->display)); 4451d522f475Smrg#ifndef __MVS__ 4452894e0ac8Smrg if (screen->respond >= 0) 4453894e0ac8Smrg close(screen->respond); 4454d522f475Smrg#endif /* __MVS__ */ 4455d522f475Smrg 44560bd37d32Smrg /* Now is the time to set up our process group and 44570bd37d32Smrg * open up the pty slave. 44580bd37d32Smrg */ 4459d522f475Smrg#ifdef USE_SYSV_PGRP 4460d522f475Smrg#if defined(CRAY) && (OSMAJORVERSION > 5) 44610bd37d32Smrg IGNORE_RC(setsid()); 4462d522f475Smrg#else 44630bd37d32Smrg IGNORE_RC(setpgrp()); 4464d522f475Smrg#endif 4465d522f475Smrg#endif /* USE_SYSV_PGRP */ 4466d522f475Smrg 4467d522f475Smrg#if defined(__QNX__) && !defined(__QNXNTO__) 44680bd37d32Smrg qsetlogin(getlogin(), ttydev); 4469d522f475Smrg#endif 44700bd37d32Smrg if (ttyfd >= 0) { 4471d522f475Smrg#ifdef __MVS__ 44720bd37d32Smrg if (ttyGetAttr(ttyfd, &gio) == 0) { 44730bd37d32Smrg gio.c_cflag &= ~(HUPCL | PARENB); 44740bd37d32Smrg ttySetAttr(ttyfd, &gio); 44750bd37d32Smrg } 4476d522f475Smrg#else /* !__MVS__ */ 44770bd37d32Smrg close_fd(ttyfd); 4478d522f475Smrg#endif /* __MVS__ */ 44790bd37d32Smrg } 4480d522f475Smrg 44810bd37d32Smrg for (;;) { 448220d2c4d2Smrg#if USE_NO_DEV_TTY 44830bd37d32Smrg if (!no_dev_tty 44840bd37d32Smrg && (ttyfd = open("/dev/tty", O_RDWR)) >= 0) { 44850bd37d32Smrg ioctl(ttyfd, TIOCNOTTY, (char *) NULL); 44860bd37d32Smrg close_fd(ttyfd); 44870bd37d32Smrg } 448820d2c4d2Smrg#endif /* USE_NO_DEV_TTY */ 4489d522f475Smrg#ifdef CSRG_BASED 44900bd37d32Smrg IGNORE_RC(revoke(ttydev)); 4491d522f475Smrg#endif 44920bd37d32Smrg if ((ttyfd = open(ttydev, O_RDWR)) >= 0) { 4493913cc679Smrg TRACE_GET_TTYSIZE(ttyfd, "after open"); 44940bd37d32Smrg TRACE_RC(i, SET_TTYSIZE(ttyfd, ts)); 4495913cc679Smrg TRACE_GET_TTYSIZE(ttyfd, "after SET_TTYSIZE fixup"); 4496d522f475Smrg#if defined(CRAY) && defined(TCSETCTTY) 44970bd37d32Smrg /* make /dev/tty work */ 44980bd37d32Smrg ioctl(ttyfd, TCSETCTTY, 0); 4499d522f475Smrg#endif 4500d522f475Smrg#if ((defined(__GLIBC__) && defined(__FreeBSD_kernel__)) || defined(__GNU__)) && defined(TIOCSCTTY) 45010bd37d32Smrg /* make /dev/tty work */ 45020bd37d32Smrg ioctl(ttyfd, TIOCSCTTY, 0); 4503d522f475Smrg#endif 4504d522f475Smrg#ifdef USE_SYSV_PGRP 45050bd37d32Smrg /* We need to make sure that we are actually 45060bd37d32Smrg * the process group leader for the pty. If 45070bd37d32Smrg * we are, then we should now be able to open 45080bd37d32Smrg * /dev/tty. 45090bd37d32Smrg */ 45100bd37d32Smrg if ((i = open("/dev/tty", O_RDWR)) >= 0) { 45110bd37d32Smrg /* success! */ 45120bd37d32Smrg close(i); 4513d522f475Smrg break; 4514d522f475Smrg } 45150bd37d32Smrg#else /* USE_SYSV_PGRP */ 45160bd37d32Smrg break; 45170bd37d32Smrg#endif /* USE_SYSV_PGRP */ 45180bd37d32Smrg } 45190bd37d32Smrg perror("open ttydev"); 4520d522f475Smrg#ifdef TIOCSCTTY 45210bd37d32Smrg ioctl(ttyfd, TIOCSCTTY, 0); 4522d522f475Smrg#endif 45230bd37d32Smrg /* let our master know that the open failed */ 45240bd37d32Smrg handshake.status = PTY_BAD; 45250bd37d32Smrg handshake.error = errno; 4526f2e35a3aSmrg copy_handshake(handshake, ttydev); 45270bd37d32Smrg TRACE_HANDSHAKE("writing", &handshake); 45280bd37d32Smrg IGNORE_RC(write(cp_pipe[1], 45290bd37d32Smrg (const char *) &handshake, 45300bd37d32Smrg sizeof(handshake))); 4531d522f475Smrg 45320bd37d32Smrg /* get reply from parent */ 45330bd37d32Smrg i = (int) read(pc_pipe[0], (char *) &handshake, 45340bd37d32Smrg sizeof(handshake)); 45350bd37d32Smrg if (i <= 0) { 45360bd37d32Smrg /* parent terminated */ 453704b94745Smrg exit(ERROR_MISC); 4538d522f475Smrg } 4539d522f475Smrg 45400bd37d32Smrg if (handshake.status == PTY_NOMORE) { 45410bd37d32Smrg /* No more ptys, let's shutdown. */ 454204b94745Smrg exit(ERROR_MISC); 4543d522f475Smrg } 45440bd37d32Smrg 45450bd37d32Smrg /* We have a new pty to try */ 45460bd37d32Smrg if (ttyfd >= 0) 45470bd37d32Smrg close(ttyfd); 45480bd37d32Smrg free(ttydev); 4549f2e35a3aSmrg handshake.buffer[HANDSHAKE_LEN - 1] = '\0'; 45500bd37d32Smrg ttydev = x_strdup(handshake.buffer); 4551d522f475Smrg } 4552d522f475Smrg 45530bd37d32Smrg /* use the same tty name that everyone else will use 45540bd37d32Smrg * (from ttyname) 45550bd37d32Smrg */ 45560bd37d32Smrg if ((ptr = ttyname(ttyfd)) != 0) { 45570bd37d32Smrg free(ttydev); 45580bd37d32Smrg ttydev = x_strdup(ptr); 45590bd37d32Smrg } 45600bd37d32Smrg } 45610bd37d32Smrg#endif /* OPT_PTY_HANDSHAKE -- from near fork */ 4562d522f475Smrg 4563d522f475Smrg set_pty_permissions(screen->uid, 4564913cc679Smrg (unsigned) screen->gid, 4565d522f475Smrg (resource.messages 4566d522f475Smrg ? 0622U 4567d522f475Smrg : 0600U)); 4568d522f475Smrg 4569d522f475Smrg /* 4570d522f475Smrg * set up the tty modes 4571d522f475Smrg */ 4572d522f475Smrg { 4573d522f475Smrg#ifdef TERMIO_STRUCT 457404b94745Smrg#if defined(umips) || defined(CRAY) || defined(__linux__) 4575d522f475Smrg /* If the control tty had its modes screwed around with, 4576d522f475Smrg eg. by lineedit in the shell, or emacs, etc. then tio 4577d522f475Smrg will have bad values. Let's just get termio from the 4578d522f475Smrg new tty and tailor it. */ 4579d522f475Smrg if (ttyGetAttr(ttyfd, &tio) == -1) 4580d522f475Smrg SysError(ERROR_TIOCGETP); 4581d522f475Smrg tio.c_lflag |= ECHOE; 4582d522f475Smrg#endif /* umips */ 4583d522f475Smrg /* Now is also the time to change the modes of the 4584d522f475Smrg * child pty. 4585d522f475Smrg */ 4586d522f475Smrg /* input: nl->nl, don't ignore cr, cr->nl */ 458720d2c4d2Smrg UIntClr(tio.c_iflag, (INLCR | IGNCR)); 4588d522f475Smrg tio.c_iflag |= ICRNL; 45890bd37d32Smrg#if OPT_WIDE_CHARS && defined(IUTF8) 4590d522f475Smrg#if OPT_LUIT_PROG 4591d522f475Smrg if (command_to_exec_with_luit == 0) 4592d522f475Smrg#endif 4593d522f475Smrg if (screen->utf8_mode) 4594d522f475Smrg tio.c_iflag |= IUTF8; 4595d522f475Smrg#endif 4596f2e35a3aSmrg /* output: cr->cr, nl is not return, no delays, ln->cr/nl */ 4597d522f475Smrg#ifndef USE_POSIX_TERMIOS 459820d2c4d2Smrg UIntClr(tio.c_oflag, 459920d2c4d2Smrg (OCRNL 460020d2c4d2Smrg | ONLRET 460120d2c4d2Smrg | NLDLY 460220d2c4d2Smrg | CRDLY 460320d2c4d2Smrg | TABDLY 460420d2c4d2Smrg | BSDLY 460520d2c4d2Smrg | VTDLY 460620d2c4d2Smrg | FFDLY)); 4607d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 4608f2e35a3aSmrg tio.c_oflag |= D_TIO_FLAGS; 4609d522f475Smrg#ifndef USE_POSIX_TERMIOS 4610d522f475Smrg# if defined(Lynx) && !defined(CBAUD) 4611d522f475Smrg# define CBAUD V_CBAUD 4612d522f475Smrg# endif 461320d2c4d2Smrg UIntClr(tio.c_cflag, CBAUD); 4614d522f475Smrg#ifdef BAUD_0 4615d522f475Smrg /* baud rate is 0 (don't care) */ 4616d522f475Smrg#elif defined(HAVE_TERMIO_C_ISPEED) 46172e4f8982Smrg tio.c_ispeed = tio.c_ospeed = line_speed; 4618d522f475Smrg#else /* !BAUD_0 */ 46192e4f8982Smrg tio.c_cflag |= line_speed; 4620d522f475Smrg#endif /* !BAUD_0 */ 4621d522f475Smrg#else /* USE_POSIX_TERMIOS */ 46222e4f8982Smrg cfsetispeed(&tio, line_speed); 46232e4f8982Smrg cfsetospeed(&tio, line_speed); 4624d522f475Smrg#ifdef __MVS__ 4625d522f475Smrg /* turn off bits that can't be set from the slave side */ 4626d522f475Smrg tio.c_cflag &= ~(PACKET | PKT3270 | PTU3270 | PKTXTND); 4627d522f475Smrg#endif /* __MVS__ */ 4628d522f475Smrg /* Clear CLOCAL so that SIGHUP is sent to us 4629d522f475Smrg when the xterm ends */ 46302e4f8982Smrg tio.c_cflag &= (unsigned) ~CLOCAL; 4631d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 4632d522f475Smrg /* enable signals, canonical processing (erase, kill, etc), 4633d522f475Smrg * echo 4634d522f475Smrg */ 4635d522f475Smrg tio.c_lflag |= ISIG | ICANON | ECHO | ECHOE | ECHOK; 4636d522f475Smrg#ifdef ECHOKE 4637d522f475Smrg tio.c_lflag |= ECHOKE | IEXTEN; 4638d522f475Smrg#endif 4639d522f475Smrg#ifdef ECHOCTL 4640d522f475Smrg tio.c_lflag |= ECHOCTL | IEXTEN; 4641d522f475Smrg#endif 4642f2e35a3aSmrg for (nn = 0; nn < XtNumber(ttyChars); ++nn) { 4643d522f475Smrg if (validTtyChar(tio, nn)) { 4644f2e35a3aSmrg int sysMode = ttyChars[nn].sysMode; 4645d522f475Smrg#ifdef __MVS__ 4646d522f475Smrg if (tio.c_cc[sysMode] != 0) { 4647d522f475Smrg switch (sysMode) { 4648d522f475Smrg case VEOL: 4649d522f475Smrg case VEOF: 4650d522f475Smrg continue; 4651d522f475Smrg } 4652d522f475Smrg } 4653d522f475Smrg#endif 4654f2e35a3aSmrg tio.c_cc[sysMode] = (cc_t) ttyChars[nn].myDefault; 4655d522f475Smrg } 4656d522f475Smrg } 4657d522f475Smrg 4658d522f475Smrg if (override_tty_modes) { 4659f2e35a3aSmrg TRACE(("applying termios ttyModes\n")); 4660f2e35a3aSmrg for (nn = 0; nn < XtNumber(ttyChars); ++nn) { 4661d522f475Smrg if (validTtyChar(tio, nn)) { 4662f2e35a3aSmrg TMODE(ttyChars[nn].myMode, 4663f2e35a3aSmrg tio.c_cc[ttyChars[nn].sysMode]); 4664f2e35a3aSmrg } else if (isTabMode(nn)) { 4665f2e35a3aSmrg unsigned tmp = (unsigned) tio.c_oflag; 4666f2e35a3aSmrg tmp = tmp & (unsigned) ~TABDLY; 4667f2e35a3aSmrg tmp |= (unsigned) ttyModes[ttyChars[nn].myMode].value; 4668f2e35a3aSmrg tio.c_oflag = tmp; 4669d522f475Smrg } 4670d522f475Smrg } 4671d522f475Smrg#ifdef HAS_LTCHARS 4672d522f475Smrg /* both SYSV and BSD have ltchars */ 4673d522f475Smrg TMODE(XTTYMODE_susp, ltc.t_suspc); 4674d522f475Smrg TMODE(XTTYMODE_dsusp, ltc.t_dsuspc); 4675d522f475Smrg TMODE(XTTYMODE_rprnt, ltc.t_rprntc); 4676d522f475Smrg TMODE(XTTYMODE_flush, ltc.t_flushc); 4677d522f475Smrg TMODE(XTTYMODE_weras, ltc.t_werasc); 4678d522f475Smrg TMODE(XTTYMODE_lnext, ltc.t_lnextc); 4679d522f475Smrg#endif 4680d522f475Smrg } 4681d522f475Smrg#ifdef HAS_LTCHARS 4682d522f475Smrg#ifdef __hpux 4683d522f475Smrg /* ioctl chokes when the "reserved" process group controls 4684d522f475Smrg * are not set to _POSIX_VDISABLE */ 4685913cc679Smrg ltc.t_rprntc = _POSIX_VDISABLE; 4686913cc679Smrg ltc.t_rprntc = _POSIX_VDISABLE; 4687913cc679Smrg ltc.t_flushc = _POSIX_VDISABLE; 4688913cc679Smrg ltc.t_werasc = _POSIX_VDISABLE; 4689913cc679Smrg ltc.t_lnextc = _POSIX_VDISABLE; 4690d522f475Smrg#endif /* __hpux */ 4691d522f475Smrg if (ioctl(ttyfd, TIOCSLTC, <c) == -1) 4692d522f475Smrg HsSysError(ERROR_TIOCSETC); 4693d522f475Smrg#endif /* HAS_LTCHARS */ 4694d522f475Smrg#ifdef TIOCLSET 4695d522f475Smrg if (ioctl(ttyfd, TIOCLSET, (char *) &lmode) == -1) 4696d522f475Smrg HsSysError(ERROR_TIOCLSET); 4697d522f475Smrg#endif /* TIOCLSET */ 4698d522f475Smrg if (ttySetAttr(ttyfd, &tio) == -1) 4699d522f475Smrg HsSysError(ERROR_TIOCSETP); 4700d522f475Smrg 4701d522f475Smrg /* ignore errors here - some platforms don't work */ 470220d2c4d2Smrg UIntClr(tio.c_cflag, CSIZE); 4703d522f475Smrg if (screen->input_eight_bits) 4704d522f475Smrg tio.c_cflag |= CS8; 4705d522f475Smrg else 4706d522f475Smrg tio.c_cflag |= CS7; 4707d522f475Smrg (void) ttySetAttr(ttyfd, &tio); 4708d522f475Smrg 4709d522f475Smrg#else /* !TERMIO_STRUCT */ 4710d522f475Smrg sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW); 4711d522f475Smrg sg.sg_flags |= ECHO | CRMOD; 4712d522f475Smrg /* make sure speed is set on pty so that editors work right */ 47132e4f8982Smrg sg.sg_ispeed = line_speed; 47142e4f8982Smrg sg.sg_ospeed = line_speed; 4715d522f475Smrg /* reset t_brkc to default value */ 4716d522f475Smrg tc.t_brkc = -1; 4717d522f475Smrg#ifdef LPASS8 4718d522f475Smrg if (screen->input_eight_bits) 4719d522f475Smrg lmode |= LPASS8; 4720d522f475Smrg else 4721d522f475Smrg lmode &= ~(LPASS8); 4722d522f475Smrg#endif 4723d522f475Smrg#ifdef sony 4724d522f475Smrg jmode &= ~KM_KANJI; 4725d522f475Smrg#endif /* sony */ 4726d522f475Smrg 4727d522f475Smrg ltc = d_ltc; 4728d522f475Smrg 4729d522f475Smrg if (override_tty_modes) { 4730f2e35a3aSmrg TRACE(("applying sgtty ttyModes\n")); 4731d522f475Smrg TMODE(XTTYMODE_intr, tc.t_intrc); 4732d522f475Smrg TMODE(XTTYMODE_quit, tc.t_quitc); 4733d522f475Smrg TMODE(XTTYMODE_erase, sg.sg_erase); 4734d522f475Smrg TMODE(XTTYMODE_kill, sg.sg_kill); 4735d522f475Smrg TMODE(XTTYMODE_eof, tc.t_eofc); 4736d522f475Smrg TMODE(XTTYMODE_start, tc.t_startc); 4737d522f475Smrg TMODE(XTTYMODE_stop, tc.t_stopc); 4738d522f475Smrg TMODE(XTTYMODE_brk, tc.t_brkc); 4739d522f475Smrg /* both SYSV and BSD have ltchars */ 4740d522f475Smrg TMODE(XTTYMODE_susp, ltc.t_suspc); 4741d522f475Smrg TMODE(XTTYMODE_dsusp, ltc.t_dsuspc); 4742d522f475Smrg TMODE(XTTYMODE_rprnt, ltc.t_rprntc); 4743d522f475Smrg TMODE(XTTYMODE_flush, ltc.t_flushc); 4744d522f475Smrg TMODE(XTTYMODE_weras, ltc.t_werasc); 4745d522f475Smrg TMODE(XTTYMODE_lnext, ltc.t_lnextc); 4746f2e35a3aSmrg if (ttyModes[XTTYMODE_tabs].set 4747f2e35a3aSmrg || ttyModes[XTTYMODE__tabs].set) { 4748f2e35a3aSmrg sg.sg_flags &= ~XTABS; 4749f2e35a3aSmrg if (ttyModes[XTTYMODE__tabs].set.set) 4750f2e35a3aSmrg sg.sg_flags |= XTABS; 4751f2e35a3aSmrg } 4752d522f475Smrg } 4753d522f475Smrg 4754d522f475Smrg if (ioctl(ttyfd, TIOCSETP, (char *) &sg) == -1) 4755d522f475Smrg HsSysError(ERROR_TIOCSETP); 4756d522f475Smrg if (ioctl(ttyfd, TIOCSETC, (char *) &tc) == -1) 4757d522f475Smrg HsSysError(ERROR_TIOCSETC); 4758d522f475Smrg if (ioctl(ttyfd, TIOCSETD, (char *) &discipline) == -1) 4759d522f475Smrg HsSysError(ERROR_TIOCSETD); 4760d522f475Smrg if (ioctl(ttyfd, TIOCSLTC, (char *) <c) == -1) 4761d522f475Smrg HsSysError(ERROR_TIOCSLTC); 4762d522f475Smrg if (ioctl(ttyfd, TIOCLSET, (char *) &lmode) == -1) 4763d522f475Smrg HsSysError(ERROR_TIOCLSET); 4764d522f475Smrg#ifdef sony 4765d522f475Smrg if (ioctl(ttyfd, TIOCKSET, (char *) &jmode) == -1) 4766d522f475Smrg HsSysError(ERROR_TIOCKSET); 4767d522f475Smrg if (ioctl(ttyfd, TIOCKSETC, (char *) &jtc) == -1) 4768d522f475Smrg HsSysError(ERROR_TIOCKSETC); 4769d522f475Smrg#endif /* sony */ 4770d522f475Smrg#endif /* TERMIO_STRUCT */ 4771d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 4772d522f475Smrg if (Console) { 4773d522f475Smrg#ifdef TIOCCONS 4774d522f475Smrg int on = 1; 4775d522f475Smrg if (ioctl(ttyfd, TIOCCONS, (char *) &on) == -1) 47760bd37d32Smrg xtermPerror("cannot open console"); 4777d522f475Smrg#endif 4778d522f475Smrg#ifdef SRIOCSREDIR 4779d522f475Smrg int fd = open("/dev/console", O_RDWR); 4780d522f475Smrg if (fd == -1 || ioctl(fd, SRIOCSREDIR, ttyfd) == -1) 47810bd37d32Smrg xtermPerror("cannot open console"); 478220d2c4d2Smrg IGNORE_RC(close(fd)); 4783d522f475Smrg#endif 4784d522f475Smrg } 4785d522f475Smrg#endif /* TIOCCONS */ 4786d522f475Smrg } 4787d522f475Smrg 4788d522f475Smrg signal(SIGCHLD, SIG_DFL); 4789d522f475Smrg#ifdef USE_SYSV_SIGHUP 4790d522f475Smrg /* watch out for extra shells (I don't understand either) */ 4791d522f475Smrg signal(SIGHUP, SIG_DFL); 4792d522f475Smrg#else 4793d522f475Smrg signal(SIGHUP, SIG_IGN); 4794d522f475Smrg#endif 4795d522f475Smrg /* restore various signals to their defaults */ 4796d522f475Smrg signal(SIGINT, SIG_DFL); 4797d522f475Smrg signal(SIGQUIT, SIG_DFL); 4798d522f475Smrg signal(SIGTERM, SIG_DFL); 4799d522f475Smrg 4800d522f475Smrg /* 4801d522f475Smrg * If we're not asked to let the parent process set the terminal's 4802d522f475Smrg * erase mode, or if we had the ttyModes erase resource, then set 4803d522f475Smrg * the terminal's erase mode from our best guess. 4804d522f475Smrg */ 4805d522f475Smrg#if OPT_INITIAL_ERASE 4806d522f475Smrg TRACE(("check if we should set erase to %d:%s\n\tptyInitialErase:%d,\n\toveride_tty_modes:%d,\n\tXTTYMODE_erase:%d\n", 4807d522f475Smrg initial_erase, 4808d522f475Smrg setInitialErase ? "YES" : "NO", 4809d522f475Smrg resource.ptyInitialErase, 4810d522f475Smrg override_tty_modes, 4811f2e35a3aSmrg ttyModes[XTTYMODE_erase].set)); 4812d522f475Smrg if (setInitialErase) { 4813d522f475Smrg#if OPT_TRACE 4814d522f475Smrg int old_erase; 4815d522f475Smrg#endif 4816d522f475Smrg#ifdef TERMIO_STRUCT 4817d522f475Smrg if (ttyGetAttr(ttyfd, &tio) == -1) 4818d522f475Smrg tio = d_tio; 4819d522f475Smrg#if OPT_TRACE 4820d522f475Smrg old_erase = tio.c_cc[VERASE]; 4821d522f475Smrg#endif 48220bd37d32Smrg tio.c_cc[VERASE] = (cc_t) initial_erase; 482320d2c4d2Smrg TRACE_RC(rc, ttySetAttr(ttyfd, &tio)); 4824d522f475Smrg#else /* !TERMIO_STRUCT */ 4825d522f475Smrg if (ioctl(ttyfd, TIOCGETP, (char *) &sg) == -1) 4826d522f475Smrg sg = d_sg; 4827d522f475Smrg#if OPT_TRACE 4828d522f475Smrg old_erase = sg.sg_erase; 4829d522f475Smrg#endif 4830d522f475Smrg sg.sg_erase = initial_erase; 4831d522f475Smrg rc = ioctl(ttyfd, TIOCSETP, (char *) &sg); 4832d522f475Smrg#endif /* TERMIO_STRUCT */ 4833d522f475Smrg TRACE(("%s setting erase to %d (was %d)\n", 4834d522f475Smrg rc ? "FAIL" : "OK", initial_erase, old_erase)); 4835d522f475Smrg } 4836d522f475Smrg#endif 4837d522f475Smrg 4838d522f475Smrg xtermCopyEnv(environ); 48394419d26bSmrg xtermTrimEnv(); 48400bd37d32Smrg 4841a1f3da82Smrg xtermSetenv("TERM", resource.term_name); 4842a1f3da82Smrg if (!resource.term_name) 484320d2c4d2Smrg *get_tcap_buffer(xw) = 0; 4844d522f475Smrg 4845d522f475Smrg sprintf(buf, "%lu", 4846d522f475Smrg ((unsigned long) XtWindow(SHELL_OF(CURRENT_EMU())))); 4847d522f475Smrg xtermSetenv("WINDOWID", buf); 4848d522f475Smrg 4849d522f475Smrg /* put the display into the environment of the shell */ 4850d522f475Smrg xtermSetenv("DISPLAY", XDisplayString(screen->display)); 4851d522f475Smrg 4852d522f475Smrg xtermSetenv("XTERM_VERSION", xtermVersion()); 4853d522f475Smrg xtermSetenv("XTERM_LOCALE", xtermEnvLocale()); 4854d522f475Smrg 4855e39b573cSmrg /* 4856e39b573cSmrg * For debugging only, add environment variables that can be used 4857e39b573cSmrg * in scripts to selectively kill xterm's parent or child 4858e39b573cSmrg * processes. 4859e39b573cSmrg */ 4860e39b573cSmrg#if OPT_TRACE 4861e39b573cSmrg sprintf(buf, "%lu", (unsigned long) xterm_parent); 4862e39b573cSmrg xtermSetenv("XTERM_PARENT", buf); 4863e39b573cSmrg sprintf(buf, "%lu", (unsigned long) getpid()); 4864e39b573cSmrg xtermSetenv("XTERM_CHILD", buf); 4865e39b573cSmrg#endif 4866e39b573cSmrg 4867d522f475Smrg signal(SIGTERM, SIG_DFL); 4868d522f475Smrg 4869d522f475Smrg /* this is the time to go and set up stdin, out, and err 4870d522f475Smrg */ 4871d522f475Smrg { 4872d522f475Smrg#if defined(CRAY) && (OSMAJORVERSION >= 6) 4873d522f475Smrg close_fd(ttyfd); 4874d522f475Smrg 487520d2c4d2Smrg IGNORE_RC(close(0)); 4876d522f475Smrg 4877d522f475Smrg if (open("/dev/tty", O_RDWR)) { 4878d522f475Smrg SysError(ERROR_OPDEVTTY); 4879d522f475Smrg } 488020d2c4d2Smrg IGNORE_RC(close(1)); 488120d2c4d2Smrg IGNORE_RC(close(2)); 4882d522f475Smrg dup(0); 4883d522f475Smrg dup(0); 4884d522f475Smrg#else 4885d522f475Smrg /* dup the tty */ 4886d522f475Smrg for (i = 0; i <= 2; i++) 4887d522f475Smrg if (i != ttyfd) { 488820d2c4d2Smrg IGNORE_RC(close(i)); 488920d2c4d2Smrg IGNORE_RC(dup(ttyfd)); 4890d522f475Smrg } 4891d522f475Smrg#ifndef ATT 4892d522f475Smrg /* and close the tty */ 4893d522f475Smrg if (ttyfd > 2) 4894d522f475Smrg close_fd(ttyfd); 4895d522f475Smrg#endif 4896d522f475Smrg#endif /* CRAY */ 4897d522f475Smrg } 4898d522f475Smrg 4899d522f475Smrg#if !defined(USE_SYSV_PGRP) 4900d522f475Smrg#ifdef TIOCSCTTY 4901d522f475Smrg setsid(); 4902d522f475Smrg ioctl(0, TIOCSCTTY, 0); 4903d522f475Smrg#endif 4904d522f475Smrg ioctl(0, TIOCSPGRP, (char *) &pgrp); 4905d522f475Smrg setpgrp(0, 0); 4906d522f475Smrg close(open(ttydev, O_WRONLY)); 4907d522f475Smrg setpgrp(0, pgrp); 4908d522f475Smrg#if defined(__QNX__) 4909d522f475Smrg tcsetpgrp(0, pgrp /*setsid() */ ); 4910d522f475Smrg#endif 4911d522f475Smrg#endif /* !USE_SYSV_PGRP */ 4912d522f475Smrg 4913d522f475Smrg#ifdef Lynx 4914d522f475Smrg { 4915d522f475Smrg TERMIO_STRUCT t; 4916d522f475Smrg if (ttyGetAttr(0, &t) >= 0) { 4917d522f475Smrg /* this gets lost somewhere on our way... */ 4918d522f475Smrg t.c_oflag |= OPOST; 4919d522f475Smrg ttySetAttr(0, &t); 4920d522f475Smrg } 4921d522f475Smrg } 4922d522f475Smrg#endif 4923d522f475Smrg 4924d522f475Smrg#ifdef HAVE_UTMP 4925d522f475Smrg login_name = NULL; 49260bd37d32Smrg if (x_getpwuid(screen->uid, &pw)) { 49270bd37d32Smrg login_name = x_getlogin(screen->uid, &pw); 4928d522f475Smrg } 4929d522f475Smrg if (login_name != NULL) { 4930d522f475Smrg xtermSetenv("LOGNAME", login_name); /* for POSIX */ 4931d522f475Smrg } 4932d522f475Smrg#ifndef USE_UTEMPTER 4933d522f475Smrg#ifdef USE_UTMP_SETGID 4934d522f475Smrg setEffectiveGroup(save_egid); 4935d522f475Smrg TRACE_IDS; 4936d522f475Smrg#endif 4937d522f475Smrg#ifdef USE_SYSV_UTMP 4938d522f475Smrg /* Set up our utmp entry now. We need to do it here 4939d522f475Smrg * for the following reasons: 4940d522f475Smrg * - It needs to have our correct process id (for 4941d522f475Smrg * login). 4942d522f475Smrg * - If our parent was to set it after the fork(), 4943d522f475Smrg * it might make it out before we need it. 4944d522f475Smrg * - We need to do it before we go and change our 4945d522f475Smrg * user and group id's. 4946d522f475Smrg */ 4947d522f475Smrg (void) call_setutent(); 4948d522f475Smrg init_utmp(DEAD_PROCESS, &utmp); 4949d522f475Smrg 4950d522f475Smrg /* position to entry in utmp file */ 4951d522f475Smrg /* Test return value: beware of entries left behind: PSz 9 Mar 00 */ 495220d2c4d2Smrg utret = find_utmp(&utmp); 495320d2c4d2Smrg if (utret == 0) { 4954d522f475Smrg (void) call_setutent(); 4955d522f475Smrg init_utmp(USER_PROCESS, &utmp); 495620d2c4d2Smrg utret = find_utmp(&utmp); 495720d2c4d2Smrg if (utret == 0) { 4958d522f475Smrg (void) call_setutent(); 4959d522f475Smrg } 4960d522f475Smrg } 4961d522f475Smrg#if OPT_TRACE 4962d522f475Smrg if (!utret) 4963d522f475Smrg TRACE(("getutid: NULL\n")); 4964d522f475Smrg else 49650bd37d32Smrg TRACE(("getutid: pid=%d type=%d user=%s line=%.*s id=%.*s\n", 496620d2c4d2Smrg (int) utret->ut_pid, utret->ut_type, utret->ut_user, 49670bd37d32Smrg (int) sizeof(utret->ut_line), utret->ut_line, 49680bd37d32Smrg (int) sizeof(utret->ut_id), utret->ut_id)); 4969d522f475Smrg#endif 4970d522f475Smrg 4971d522f475Smrg /* set up the new entry */ 4972d522f475Smrg utmp.ut_type = USER_PROCESS; 4973d522f475Smrg#ifdef HAVE_UTMP_UT_XSTATUS 4974d522f475Smrg utmp.ut_xstatus = 2; 4975d522f475Smrg#endif 4976894e0ac8Smrg copy_filled(utmp.ut_user, 4977894e0ac8Smrg (login_name != NULL) ? login_name : "????", 4978894e0ac8Smrg sizeof(utmp.ut_user)); 4979d522f475Smrg /* why are we copying this string again? (see above) */ 4980894e0ac8Smrg copy_filled(utmp.ut_id, my_utmp_id(ttydev), sizeof(utmp.ut_id)); 4981894e0ac8Smrg copy_filled(utmp.ut_line, 4982894e0ac8Smrg my_pty_name(ttydev), sizeof(utmp.ut_line)); 4983d522f475Smrg 4984d522f475Smrg#ifdef HAVE_UTMP_UT_HOST 4985d522f475Smrg SetUtmpHost(utmp.ut_host, screen); 4986d522f475Smrg#endif 4987d522f475Smrg#ifdef HAVE_UTMP_UT_SYSLEN 4988d522f475Smrg SetUtmpSysLen(utmp); 4989d522f475Smrg#endif 4990d522f475Smrg 4991894e0ac8Smrg copy_filled(utmp.ut_name, 4992894e0ac8Smrg (login_name) ? login_name : "????", 4993894e0ac8Smrg sizeof(utmp.ut_name)); 4994d522f475Smrg 4995d522f475Smrg utmp.ut_pid = getpid(); 4996d522f475Smrg#if defined(HAVE_UTMP_UT_XTIME) 4997d522f475Smrg#if defined(HAVE_UTMP_UT_SESSION) 4998d522f475Smrg utmp.ut_session = getsid(0); 4999d522f475Smrg#endif 5000d522f475Smrg utmp.ut_xtime = time((time_t *) 0); 5001d522f475Smrg utmp.ut_tv.tv_usec = 0; 5002d522f475Smrg#else 5003d522f475Smrg utmp.ut_time = time((time_t *) 0); 5004d522f475Smrg#endif 5005d522f475Smrg 5006d522f475Smrg /* write out the entry */ 5007d522f475Smrg if (!resource.utmpInhibit) { 5008d522f475Smrg errno = 0; 5009d522f475Smrg call_pututline(&utmp); 50100bd37d32Smrg TRACE(("pututline: id %.*s, line %.*s, pid %ld, errno %d %s\n", 50110bd37d32Smrg (int) sizeof(utmp.ut_id), utmp.ut_id, 50120bd37d32Smrg (int) sizeof(utmp.ut_line), utmp.ut_line, 5013d522f475Smrg (long) utmp.ut_pid, 5014d522f475Smrg errno, (errno != 0) ? strerror(errno) : "")); 5015d522f475Smrg } 5016d522f475Smrg#ifdef WTMP 5017d522f475Smrg#if defined(WTMPX_FILE) && (defined(SVR4) || defined(__SCO__)) 5018d522f475Smrg if (xw->misc.login_shell) 5019d522f475Smrg updwtmpx(WTMPX_FILE, &utmp); 502004b94745Smrg#elif defined(__linux__) && defined(__GLIBC__) && (__GLIBC__ >= 2) && !(defined(__powerpc__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)) 5021d522f475Smrg if (xw->misc.login_shell) 5022d522f475Smrg call_updwtmp(etc_wtmp, &utmp); 5023d522f475Smrg#else 5024d522f475Smrg if (xw->misc.login_shell && 5025d522f475Smrg (i = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 50260bd37d32Smrg IGNORE_RC(write(i, (char *) &utmp, sizeof(utmp))); 5027d522f475Smrg close(i); 5028d522f475Smrg } 5029d522f475Smrg#endif 5030d522f475Smrg#endif 5031d522f475Smrg /* close the file */ 5032d522f475Smrg (void) call_endutent(); 5033d522f475Smrg 5034d522f475Smrg#else /* USE_SYSV_UTMP */ 5035d522f475Smrg /* We can now get our ttyslot! We can also set the initial 5036d522f475Smrg * utmp entry. 5037d522f475Smrg */ 5038d522f475Smrg tslot = ttyslot(); 5039d522f475Smrg added_utmp_entry = False; 5040d522f475Smrg { 50410bd37d32Smrg if (tslot > 0 && OkPasswd(&pw) && !resource.utmpInhibit && 5042d522f475Smrg (i = open(etc_utmp, O_WRONLY)) >= 0) { 5043956cc18dSsnj memset(&utmp, 0, sizeof(utmp)); 5044894e0ac8Smrg copy_filled(utmp.ut_line, 5045894e0ac8Smrg my_pty_name(ttydev), 5046894e0ac8Smrg sizeof(utmp.ut_line)); 5047894e0ac8Smrg copy_filled(utmp.ut_name, login_name, 5048894e0ac8Smrg sizeof(utmp.ut_name)); 5049d522f475Smrg#ifdef HAVE_UTMP_UT_HOST 5050d522f475Smrg SetUtmpHost(utmp.ut_host, screen); 5051d522f475Smrg#endif 5052d522f475Smrg#ifdef HAVE_UTMP_UT_SYSLEN 5053d522f475Smrg SetUtmpSysLen(utmp); 5054d522f475Smrg#endif 5055d522f475Smrg 5056d522f475Smrg utmp.ut_time = time((time_t *) 0); 5057d522f475Smrg lseek(i, (long) (tslot * sizeof(utmp)), 0); 50580bd37d32Smrg IGNORE_RC(write(i, (char *) &utmp, sizeof(utmp))); 5059d522f475Smrg close(i); 5060d522f475Smrg added_utmp_entry = True; 5061d522f475Smrg#if defined(WTMP) 5062d522f475Smrg if (xw->misc.login_shell && 5063d522f475Smrg (i = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 5064d522f475Smrg int status; 5065d522f475Smrg status = write(i, (char *) &utmp, sizeof(utmp)); 5066d522f475Smrg status = close(i); 5067d522f475Smrg } 5068d522f475Smrg#elif defined(MNX_LASTLOG) 5069d522f475Smrg if (xw->misc.login_shell && 5070d522f475Smrg (i = open(_U_LASTLOG, O_WRONLY)) >= 0) { 5071d522f475Smrg lseek(i, (long) (screen->uid * 5072d522f475Smrg sizeof(utmp)), 0); 50730bd37d32Smrg IGNORE_RC(write(i, (char *) &utmp, sizeof(utmp))); 5074d522f475Smrg close(i); 5075d522f475Smrg } 5076d522f475Smrg#endif /* WTMP or MNX_LASTLOG */ 5077d522f475Smrg } else 5078d522f475Smrg tslot = -tslot; 5079d522f475Smrg } 5080d522f475Smrg 5081d522f475Smrg /* Let's pass our ttyslot to our parent so that it can 5082d522f475Smrg * clean up after us. 5083d522f475Smrg */ 5084d522f475Smrg#if OPT_PTY_HANDSHAKE 5085d522f475Smrg if (resource.ptyHandshake) { 5086d522f475Smrg handshake.tty_slot = tslot; 5087d522f475Smrg } 5088d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 5089d522f475Smrg#endif /* USE_SYSV_UTMP */ 5090d522f475Smrg 5091d522f475Smrg#ifdef USE_LASTLOGX 5092d522f475Smrg if (xw->misc.login_shell) { 5093956cc18dSsnj memset(&lastlogx, 0, sizeof(lastlogx)); 5094f2e35a3aSmrg copy_filled(lastlogx.ll_line, 5095f2e35a3aSmrg my_pty_name(ttydev), 5096f2e35a3aSmrg sizeof(lastlogx.ll_line)); 5097d522f475Smrg X_GETTIMEOFDAY(&lastlogx.ll_tv); 5098d522f475Smrg SetUtmpHost(lastlogx.ll_host, screen); 5099d522f475Smrg updlastlogx(_PATH_LASTLOGX, screen->uid, &lastlogx); 5100d522f475Smrg } 5101d522f475Smrg#endif 5102d522f475Smrg 5103d522f475Smrg#ifdef USE_LASTLOG 5104d522f475Smrg if (xw->misc.login_shell && 5105d522f475Smrg (i = open(etc_lastlog, O_WRONLY)) >= 0) { 5106d522f475Smrg size_t size = sizeof(struct lastlog); 5107913cc679Smrg off_t offset = (off_t) ((size_t) screen->uid * size); 5108d522f475Smrg 5109956cc18dSsnj memset(&lastlog, 0, size); 5110f2e35a3aSmrg copy_filled(lastlog.ll_line, 5111f2e35a3aSmrg my_pty_name(ttydev), 5112f2e35a3aSmrg sizeof(lastlog.ll_line)); 5113d522f475Smrg SetUtmpHost(lastlog.ll_host, screen); 5114d522f475Smrg lastlog.ll_time = time((time_t *) 0); 5115d522f475Smrg if (lseek(i, offset, 0) != (off_t) (-1)) { 51160bd37d32Smrg IGNORE_RC(write(i, (char *) &lastlog, size)); 5117d522f475Smrg } 5118d522f475Smrg close(i); 5119d522f475Smrg } 5120d522f475Smrg#endif /* USE_LASTLOG */ 5121d522f475Smrg 5122d522f475Smrg#if defined(USE_UTMP_SETGID) 5123d522f475Smrg disableSetGid(); 5124d522f475Smrg TRACE_IDS; 5125d522f475Smrg#endif 5126d522f475Smrg 5127d522f475Smrg#if OPT_PTY_HANDSHAKE 5128d522f475Smrg /* Let our parent know that we set up our utmp entry 5129d522f475Smrg * so that it can clean up after us. 5130d522f475Smrg */ 5131d522f475Smrg if (resource.ptyHandshake) { 5132d522f475Smrg handshake.status = UTMP_ADDED; 5133d522f475Smrg handshake.error = 0; 5134f2e35a3aSmrg copy_handshake(handshake, ttydev); 5135d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 513620d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], (char *) &handshake, sizeof(handshake))); 5137d522f475Smrg } 5138d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 5139d522f475Smrg#endif /* USE_UTEMPTER */ 5140d522f475Smrg#endif /* HAVE_UTMP */ 5141d522f475Smrg 514220d2c4d2Smrg IGNORE_RC(setgid(screen->gid)); 5143d522f475Smrg TRACE_IDS; 5144e0a2b6dfSmrg#ifdef HAVE_INITGROUPS 51450bd37d32Smrg if (geteuid() == 0 && OkPasswd(&pw)) { 51460bd37d32Smrg if (initgroups(login_name, pw.pw_gid)) { 5147d522f475Smrg perror("initgroups failed"); 5148d522f475Smrg SysError(ERROR_INIGROUPS); 5149d522f475Smrg } 5150d522f475Smrg } 5151d522f475Smrg#endif 5152d522f475Smrg if (setuid(screen->uid)) { 5153d522f475Smrg SysError(ERROR_SETUID); 5154d522f475Smrg } 5155d522f475Smrg TRACE_IDS; 5156d522f475Smrg#if OPT_PTY_HANDSHAKE 5157d522f475Smrg if (resource.ptyHandshake) { 5158d522f475Smrg /* mark the pipes as close on exec */ 51590bd37d32Smrg (void) fcntl(cp_pipe[1], F_SETFD, 1); 51600bd37d32Smrg (void) fcntl(pc_pipe[0], F_SETFD, 1); 5161d522f475Smrg 5162d522f475Smrg /* We are at the point where we are going to 5163d522f475Smrg * exec our shell (or whatever). Let our parent 5164d522f475Smrg * know we arrived safely. 5165d522f475Smrg */ 5166d522f475Smrg handshake.status = PTY_GOOD; 5167d522f475Smrg handshake.error = 0; 5168f2e35a3aSmrg copy_handshake(handshake, ttydev); 5169d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 517020d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], 517120d2c4d2Smrg (const char *) &handshake, 517220d2c4d2Smrg sizeof(handshake))); 5173d522f475Smrg 5174d522f475Smrg if (resource.wait_for_map) { 517520d2c4d2Smrg i = (int) read(pc_pipe[0], (char *) &handshake, 517620d2c4d2Smrg sizeof(handshake)); 5177d522f475Smrg if (i != sizeof(handshake) || 5178d522f475Smrg handshake.status != PTY_EXEC) { 5179d522f475Smrg /* some very bad problem occurred */ 5180d522f475Smrg exit(ERROR_PTY_EXEC); 5181d522f475Smrg } 5182d522f475Smrg if (handshake.rows > 0 && handshake.cols > 0) { 5183913cc679Smrg TRACE(("handshake read ttysize: %dx%d\n", 5184d522f475Smrg handshake.rows, handshake.cols)); 5185d522f475Smrg set_max_row(screen, handshake.rows); 5186d522f475Smrg set_max_col(screen, handshake.cols); 5187d522f475Smrg#ifdef TTYSIZE_STRUCT 5188d522f475Smrg got_handshake_size = True; 5189913cc679Smrg setup_winsize(ts, MaxRows(screen), MaxCols(screen), 5190913cc679Smrg FullHeight(screen), FullWidth(screen)); 5191913cc679Smrg trace_winsize(ts, "got handshake"); 5192d522f475Smrg#endif /* TTYSIZE_STRUCT */ 5193d522f475Smrg } 5194d522f475Smrg } 5195d522f475Smrg } 5196d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 5197d522f475Smrg 5198d522f475Smrg#ifdef USE_SYSV_ENVVARS 5199d522f475Smrg { 5200d522f475Smrg char numbuf[12]; 5201d522f475Smrg sprintf(numbuf, "%d", MaxCols(screen)); 5202d522f475Smrg xtermSetenv("COLUMNS", numbuf); 5203d522f475Smrg sprintf(numbuf, "%d", MaxRows(screen)); 5204d522f475Smrg xtermSetenv("LINES", numbuf); 5205d522f475Smrg } 5206d522f475Smrg#ifdef HAVE_UTMP 52070bd37d32Smrg if (OkPasswd(&pw)) { /* SVR4 doesn't provide these */ 5208d522f475Smrg if (!x_getenv("HOME")) 52090bd37d32Smrg xtermSetenv("HOME", pw.pw_dir); 5210d522f475Smrg if (!x_getenv("SHELL")) 52110bd37d32Smrg xtermSetenv("SHELL", pw.pw_shell); 5212d522f475Smrg } 5213d522f475Smrg#endif /* HAVE_UTMP */ 5214d522f475Smrg#else /* USE_SYSV_ENVVARS */ 521520d2c4d2Smrg if (*(newtc = get_tcap_buffer(xw)) != '\0') { 521620d2c4d2Smrg resize_termcap(xw); 521720d2c4d2Smrg if (xw->misc.titeInhibit && !xw->misc.tiXtraScroll) { 521820d2c4d2Smrg remove_termcap_entry(newtc, "ti="); 521920d2c4d2Smrg remove_termcap_entry(newtc, "te="); 522020d2c4d2Smrg } 522120d2c4d2Smrg /* 522220d2c4d2Smrg * work around broken termcap entries */ 522320d2c4d2Smrg if (resource.useInsertMode) { 522420d2c4d2Smrg remove_termcap_entry(newtc, "ic="); 522520d2c4d2Smrg /* don't get duplicates */ 522620d2c4d2Smrg remove_termcap_entry(newtc, "im="); 522720d2c4d2Smrg remove_termcap_entry(newtc, "ei="); 522820d2c4d2Smrg remove_termcap_entry(newtc, "mi"); 522920d2c4d2Smrg if (*newtc) 523020d2c4d2Smrg strcat(newtc, ":im=\\E[4h:ei=\\E[4l:mi:"); 523120d2c4d2Smrg } 523220d2c4d2Smrg if (*newtc) { 5233d522f475Smrg#if OPT_INITIAL_ERASE 52345307cd1aSmrg#define TERMCAP_ERASE "kb" 523520d2c4d2Smrg unsigned len; 523620d2c4d2Smrg remove_termcap_entry(newtc, TERMCAP_ERASE "="); 523720d2c4d2Smrg len = (unsigned) strlen(newtc); 523820d2c4d2Smrg if (len != 0 && newtc[len - 1] == ':') 523920d2c4d2Smrg len--; 524020d2c4d2Smrg sprintf(newtc + len, ":%s=\\%03o:", 524120d2c4d2Smrg TERMCAP_ERASE, 524220d2c4d2Smrg CharOf(initial_erase)); 524320d2c4d2Smrg#endif 524420d2c4d2Smrg xtermSetenv("TERMCAP", newtc); 524520d2c4d2Smrg } 5246d522f475Smrg } 5247d522f475Smrg#endif /* USE_SYSV_ENVVARS */ 5248913cc679Smrg#ifdef OWN_TERMINFO_ENV 5249913cc679Smrg xtermSetenv("TERMINFO", OWN_TERMINFO_DIR); 5250913cc679Smrg#endif 5251d522f475Smrg 5252d522f475Smrg#if OPT_PTY_HANDSHAKE 5253d522f475Smrg /* 5254d522f475Smrg * Need to reset after all the ioctl bashing we did above. 5255d522f475Smrg * 5256d522f475Smrg * If we expect the waitForMap logic to set the handshake-size, 5257d522f475Smrg * use that to prevent races. 5258d522f475Smrg */ 5259913cc679Smrg TRACE(("should we reset screensize after pty-handshake?\n")); 5260913cc679Smrg TRACE(("... ptyHandshake :%d\n", resource.ptyHandshake)); 5261913cc679Smrg TRACE(("... ptySttySize :%d\n", resource.ptySttySize)); 5262913cc679Smrg TRACE(("... got_handshake_size:%d\n", got_handshake_size)); 5263913cc679Smrg TRACE(("... wait_for_map0 :%d\n", resource.wait_for_map0)); 5264d522f475Smrg if (resource.ptyHandshake 5265d522f475Smrg && resource.ptySttySize 5266d522f475Smrg && (got_handshake_size || !resource.wait_for_map0)) { 5267d522f475Smrg#ifdef TTYSIZE_STRUCT 526820d2c4d2Smrg TRACE_RC(i, SET_TTYSIZE(0, ts)); 5269913cc679Smrg trace_winsize(ts, "ptyHandshake SET_TTYSIZE"); 5270d522f475Smrg#endif /* TTYSIZE_STRUCT */ 5271d522f475Smrg } 5272d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 5273d522f475Smrg signal(SIGHUP, SIG_DFL); 5274d522f475Smrg 52750bd37d32Smrg /* 5276e0a2b6dfSmrg * If we have an explicit shell to run, make that set $SHELL. 5277e0a2b6dfSmrg * Next, allow an existing setting of $SHELL, for absolute paths. 52780bd37d32Smrg * Otherwise, if $SHELL is not set, determine it from the user's 52790bd37d32Smrg * password information, if possible. 52800bd37d32Smrg * 52810bd37d32Smrg * Incidentally, our setting of $SHELL tells luit to use that 52820bd37d32Smrg * program rather than choosing between $SHELL and "/bin/sh". 52830bd37d32Smrg */ 5284e0a2b6dfSmrg if (validShell(explicit_shname)) { 5285e0a2b6dfSmrg xtermSetenv("SHELL", explicit_shname); 5286e0a2b6dfSmrg } else if (validProgram(shell_path = x_getenv("SHELL"))) { 5287e0a2b6dfSmrg if (!validShell(shell_path)) { 5288e0a2b6dfSmrg xtermUnsetenv("SHELL"); 5289d522f475Smrg } 5290e0a2b6dfSmrg } else if ((!OkPasswd(&pw) && !x_getpwuid(screen->uid, &pw)) 5291e0a2b6dfSmrg || *(shell_path = x_strdup(pw.pw_shell)) == 0) { 5292e0a2b6dfSmrg shell_path = resetShell(shell_path); 5293e0a2b6dfSmrg } else if (validShell(shell_path)) { 5294e0a2b6dfSmrg xtermSetenv("SHELL", shell_path); 5295d522f475Smrg } else { 5296e0a2b6dfSmrg shell_path = resetShell(shell_path); 5297d522f475Smrg } 5298e0a2b6dfSmrg 5299e0a2b6dfSmrg /* 5300e0a2b6dfSmrg * Set $XTERM_SHELL, which is not necessarily a valid shell, but 5301e0a2b6dfSmrg * is executable. 5302e0a2b6dfSmrg */ 5303e0a2b6dfSmrg if (validProgram(explicit_shname)) { 5304e0a2b6dfSmrg shell_path = explicit_shname; 5305e0a2b6dfSmrg } else if (shell_path == 0) { 5306e0a2b6dfSmrg /* this could happen if the explicit shname lost a race */ 5307e0a2b6dfSmrg shell_path = resetShell(shell_path); 53080bd37d32Smrg } 53090bd37d32Smrg xtermSetenv("XTERM_SHELL", shell_path); 5310d522f475Smrg 53110bd37d32Smrg shname = x_basename(shell_path); 53120bd37d32Smrg TRACE(("shell path '%s' leaf '%s'\n", shell_path, shname)); 5313d522f475Smrg 5314d522f475Smrg#if OPT_LUIT_PROG 5315d522f475Smrg /* 5316d522f475Smrg * Use two copies of command_to_exec, in case luit is not actually 5317d522f475Smrg * there, or refuses to run. In that case we will fall-through to 5318d522f475Smrg * to command that the user gave anyway. 5319d522f475Smrg */ 53202eaa94a1Schristos if (command_to_exec_with_luit && command_to_exec) { 53210bd37d32Smrg char *myShell = xtermFindShell(*command_to_exec_with_luit, False); 53220bd37d32Smrg xtermSetenv("XTERM_SHELL", myShell); 53230bd37d32Smrg free(myShell); 53240bd37d32Smrg TRACE_ARGV("spawning luit command", command_to_exec_with_luit); 5325d522f475Smrg execvp(*command_to_exec_with_luit, command_to_exec_with_luit); 53260bd37d32Smrg xtermPerror("Can't execvp %s", *command_to_exec_with_luit); 53270bd37d32Smrg xtermWarning("cannot support your locale.\n"); 5328d522f475Smrg } 5329d522f475Smrg#endif 5330d522f475Smrg if (command_to_exec) { 53310bd37d32Smrg char *myShell = xtermFindShell(*command_to_exec, False); 53320bd37d32Smrg xtermSetenv("XTERM_SHELL", myShell); 53330bd37d32Smrg free(myShell); 53340bd37d32Smrg TRACE_ARGV("spawning command", command_to_exec); 5335d522f475Smrg execvp(*command_to_exec, command_to_exec); 5336d522f475Smrg if (command_to_exec[1] == 0) 53370bd37d32Smrg execlp(shell_path, shname, "-c", command_to_exec[0], 53380bd37d32Smrg (void *) 0); 53390bd37d32Smrg xtermPerror("Can't execvp %s", *command_to_exec); 5340d522f475Smrg } 5341d522f475Smrg#ifdef USE_SYSV_SIGHUP 5342d522f475Smrg /* fix pts sh hanging around */ 5343d522f475Smrg signal(SIGHUP, SIG_DFL); 5344d522f475Smrg#endif 5345d522f475Smrg 53465307cd1aSmrg if ((shname_minus = (char *) malloc(strlen(shname) + 2)) != 0) { 534701037d57Smrg (void) strcpy(shname_minus, "-"); 534801037d57Smrg (void) strcat(shname_minus, shname); 534901037d57Smrg } else { 535001037d57Smrg static char default_minus[] = "-sh"; 535101037d57Smrg shname_minus = default_minus; 535201037d57Smrg } 5353d522f475Smrg#ifndef TERMIO_STRUCT 53540bd37d32Smrg ldisc = (!XStrCmp("csh", shname + strlen(shname) - 3) 53550bd37d32Smrg ? NTTYDISC 53560bd37d32Smrg : 0); 5357d522f475Smrg ioctl(0, TIOCSETD, (char *) &ldisc); 5358d522f475Smrg#endif /* !TERMIO_STRUCT */ 5359d522f475Smrg 5360d522f475Smrg#ifdef USE_LOGIN_DASH_P 53610bd37d32Smrg if (xw->misc.login_shell && OkPasswd(&pw) && added_utmp_entry) 5362d522f475Smrg execl(bin_login, "login", "-p", "-f", login_name, (void *) 0); 5363d522f475Smrg#endif 53642eaa94a1Schristos 53652eaa94a1Schristos#if OPT_LUIT_PROG 53662eaa94a1Schristos if (command_to_exec_with_luit) { 53672eaa94a1Schristos if (xw->misc.login_shell) { 53680bd37d32Smrg char *params[4]; 53690bd37d32Smrg params[0] = x_strdup("-argv0"); 53700bd37d32Smrg params[1] = shname_minus; 53710bd37d32Smrg params[2] = NULL; 53720bd37d32Smrg x_appendargv(command_to_exec_with_luit 53730bd37d32Smrg + command_length_with_luit, 53740bd37d32Smrg params); 53752eaa94a1Schristos } 53760bd37d32Smrg TRACE_ARGV("final luit command", command_to_exec_with_luit); 53772eaa94a1Schristos execvp(*command_to_exec_with_luit, command_to_exec_with_luit); 53782eaa94a1Schristos /* Exec failed. */ 53790bd37d32Smrg xtermPerror("Can't execvp %s", *command_to_exec_with_luit); 53802eaa94a1Schristos } 53812eaa94a1Schristos#endif 53820bd37d32Smrg execlp(shell_path, 5383d522f475Smrg (xw->misc.login_shell ? shname_minus : shname), 5384d522f475Smrg (void *) 0); 5385d522f475Smrg 5386d522f475Smrg /* Exec failed. */ 53870bd37d32Smrg xtermPerror("Could not exec %s", shell_path); 538820d2c4d2Smrg IGNORE_RC(sleep(5)); 53890bd37d32Smrg free(shell_path); 5390d522f475Smrg exit(ERROR_EXEC); 5391d522f475Smrg } 5392d522f475Smrg /* end if in child after fork */ 5393d522f475Smrg#if OPT_PTY_HANDSHAKE 5394d522f475Smrg if (resource.ptyHandshake) { 5395d522f475Smrg /* Parent process. Let's handle handshaked requests to our 5396d522f475Smrg * child process. 5397d522f475Smrg */ 5398d522f475Smrg 5399d522f475Smrg /* close childs's sides of the pipes */ 5400d522f475Smrg close(cp_pipe[1]); 5401d522f475Smrg close(pc_pipe[0]); 5402d522f475Smrg 5403d522f475Smrg for (done = 0; !done;) { 5404d522f475Smrg if (read(cp_pipe[0], 5405d522f475Smrg (char *) &handshake, 5406d522f475Smrg sizeof(handshake)) <= 0) { 5407d522f475Smrg /* Our child is done talking to us. If it terminated 5408d522f475Smrg * due to an error, we will catch the death of child 5409d522f475Smrg * and clean up. 5410d522f475Smrg */ 5411d522f475Smrg break; 5412d522f475Smrg } 5413d522f475Smrg 5414d522f475Smrg TRACE_HANDSHAKE("read", &handshake); 5415d522f475Smrg switch (handshake.status) { 5416d522f475Smrg case PTY_GOOD: 5417d522f475Smrg /* Success! Let's free up resources and 5418d522f475Smrg * continue. 5419d522f475Smrg */ 5420d522f475Smrg done = 1; 5421d522f475Smrg break; 5422d522f475Smrg 5423d522f475Smrg case PTY_BAD: 5424d522f475Smrg /* The open of the pty failed! Let's get 5425d522f475Smrg * another one. 5426d522f475Smrg */ 542720d2c4d2Smrg IGNORE_RC(close(screen->respond)); 5428d522f475Smrg if (get_pty(&screen->respond, XDisplayString(screen->display))) { 5429d522f475Smrg /* no more ptys! */ 54300bd37d32Smrg xtermPerror("child process can find no available ptys"); 5431d522f475Smrg handshake.status = PTY_NOMORE; 5432d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 543320d2c4d2Smrg IGNORE_RC(write(pc_pipe[1], 543420d2c4d2Smrg (const char *) &handshake, 543520d2c4d2Smrg sizeof(handshake))); 5436d522f475Smrg exit(ERROR_PTYS); 5437d522f475Smrg } 5438d522f475Smrg handshake.status = PTY_NEW; 5439f2e35a3aSmrg copy_handshake(handshake, ttydev); 5440d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 544120d2c4d2Smrg IGNORE_RC(write(pc_pipe[1], 544220d2c4d2Smrg (const char *) &handshake, 544320d2c4d2Smrg sizeof(handshake))); 5444d522f475Smrg break; 5445d522f475Smrg 5446d522f475Smrg case PTY_FATALERROR: 5447d522f475Smrg errno = handshake.error; 5448d522f475Smrg close(cp_pipe[0]); 5449d522f475Smrg close(pc_pipe[1]); 5450d522f475Smrg SysError(handshake.fatal_error); 5451d522f475Smrg /*NOTREACHED */ 5452d522f475Smrg 5453d522f475Smrg case UTMP_ADDED: 5454d522f475Smrg /* The utmp entry was set by our slave. Remember 5455d522f475Smrg * this so that we can reset it later. 5456d522f475Smrg */ 5457d522f475Smrg added_utmp_entry = True; 5458d522f475Smrg#ifndef USE_SYSV_UTMP 5459d522f475Smrg tslot = handshake.tty_slot; 5460d522f475Smrg#endif /* USE_SYSV_UTMP */ 5461d522f475Smrg free(ttydev); 5462f2e35a3aSmrg handshake.buffer[HANDSHAKE_LEN - 1] = '\0'; 5463d522f475Smrg ttydev = x_strdup(handshake.buffer); 5464d522f475Smrg break; 5465d522f475Smrg case PTY_NEW: 5466d522f475Smrg case PTY_NOMORE: 5467d522f475Smrg case UTMP_TTYSLOT: 5468d522f475Smrg case PTY_EXEC: 5469d522f475Smrg default: 54700bd37d32Smrg xtermWarning("unexpected handshake status %d\n", 54710bd37d32Smrg (int) handshake.status); 5472d522f475Smrg } 5473d522f475Smrg } 5474d522f475Smrg /* close our sides of the pipes */ 5475d522f475Smrg if (!resource.wait_for_map) { 5476d522f475Smrg close(cp_pipe[0]); 5477d522f475Smrg close(pc_pipe[1]); 5478d522f475Smrg } 5479d522f475Smrg } 5480d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 5481d522f475Smrg } 5482d522f475Smrg 5483d522f475Smrg /* end if no slave */ 5484d522f475Smrg /* 5485d522f475Smrg * still in parent (xterm process) 5486d522f475Smrg */ 5487d522f475Smrg#ifdef USE_SYSV_SIGHUP 5488d522f475Smrg /* hung sh problem? */ 5489d522f475Smrg signal(SIGHUP, SIG_DFL); 5490d522f475Smrg#else 5491d522f475Smrg signal(SIGHUP, SIG_IGN); 5492d522f475Smrg#endif 5493d522f475Smrg 5494d522f475Smrg/* 5495d522f475Smrg * Unfortunately, System V seems to have trouble divorcing the child process 5496d522f475Smrg * from the process group of xterm. This is a problem because hitting the 5497d522f475Smrg * INTR or QUIT characters on the keyboard will cause xterm to go away if we 5498d522f475Smrg * don't ignore the signals. This is annoying. 5499d522f475Smrg */ 5500d522f475Smrg 5501d522f475Smrg#if defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP) 5502d522f475Smrg signal(SIGINT, SIG_IGN); 5503d522f475Smrg 5504d522f475Smrg#ifndef SYSV 5505d522f475Smrg /* hung shell problem */ 5506d522f475Smrg signal(SIGQUIT, SIG_IGN); 5507d522f475Smrg#endif 5508d522f475Smrg signal(SIGTERM, SIG_IGN); 5509d522f475Smrg#elif defined(SYSV) || defined(__osf__) 5510d522f475Smrg /* if we were spawned by a jobcontrol smart shell (like ksh or csh), 5511d522f475Smrg * then our pgrp and pid will be the same. If we were spawned by 5512d522f475Smrg * a jobcontrol dumb shell (like /bin/sh), then we will be in our 5513d522f475Smrg * parent's pgrp, and we must ignore keyboard signals, or we will 5514d522f475Smrg * tank on everything. 5515d522f475Smrg */ 5516d522f475Smrg if (getpid() == getpgrp()) { 5517d522f475Smrg (void) signal(SIGINT, Exit); 5518d522f475Smrg (void) signal(SIGQUIT, Exit); 5519d522f475Smrg (void) signal(SIGTERM, Exit); 5520d522f475Smrg } else { 5521d522f475Smrg (void) signal(SIGINT, SIG_IGN); 5522d522f475Smrg (void) signal(SIGQUIT, SIG_IGN); 5523d522f475Smrg (void) signal(SIGTERM, SIG_IGN); 5524d522f475Smrg } 5525d522f475Smrg (void) signal(SIGPIPE, Exit); 5526d522f475Smrg#else /* SYSV */ 5527d522f475Smrg signal(SIGINT, Exit); 5528d522f475Smrg signal(SIGQUIT, Exit); 5529d522f475Smrg signal(SIGTERM, Exit); 5530d522f475Smrg signal(SIGPIPE, Exit); 5531d522f475Smrg#endif /* USE_SYSV_SIGNALS and not SIGTSTP */ 55320bd37d32Smrg#ifdef NO_LEAKS 55330bd37d32Smrg if (ok_termcap != True) 55340bd37d32Smrg free(TermName); 55350bd37d32Smrg#endif 5536d522f475Smrg 5537d522f475Smrg return 0; 5538d522f475Smrg} /* end spawnXTerm */ 5539d522f475Smrg 55400bd37d32Smrgvoid 5541d522f475SmrgExit(int n) 5542d522f475Smrg{ 554320d2c4d2Smrg XtermWidget xw = term; 554420d2c4d2Smrg TScreen *screen = TScreenOf(xw); 5545d522f475Smrg 5546d522f475Smrg#ifdef USE_UTEMPTER 55470bd37d32Smrg DEBUG_MSG("handle:Exit USE_UTEMPTER\n"); 55480bd37d32Smrg if (!resource.utmpInhibit && added_utmp_entry) { 55490bd37d32Smrg TRACE(("...calling removeFromUtmp\n")); 5550f2e35a3aSmrg UTEMPTER_DEL(); 55510bd37d32Smrg } 5552d522f475Smrg#elif defined(HAVE_UTMP) 5553d522f475Smrg#ifdef USE_SYSV_UTMP 5554d522f475Smrg struct UTMP_STR utmp; 5555d522f475Smrg struct UTMP_STR *utptr; 5556d522f475Smrg 55570bd37d32Smrg DEBUG_MSG("handle:Exit USE_SYSV_UTMP\n"); 5558d522f475Smrg /* don't do this more than once */ 55590bd37d32Smrg if (xterm_exiting) { 55600bd37d32Smrg exit(n); 55610bd37d32Smrg } 5562d522f475Smrg xterm_exiting = True; 5563d522f475Smrg 5564d522f475Smrg#ifdef PUCC_PTYD 5565d522f475Smrg closepty(ttydev, ptydev, (resource.utmpInhibit ? OPTY_NOP : OPTY_LOGIN), screen->respond); 5566d522f475Smrg#endif /* PUCC_PTYD */ 5567d522f475Smrg 5568d522f475Smrg /* cleanup the utmp entry we forged earlier */ 5569d522f475Smrg if (!resource.utmpInhibit 5570d522f475Smrg#if OPT_PTY_HANDSHAKE /* without handshake, no way to know */ 5571d522f475Smrg && (resource.ptyHandshake && added_utmp_entry) 5572d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 5573d522f475Smrg ) { 5574d522f475Smrg#if defined(USE_UTMP_SETGID) 5575d522f475Smrg setEffectiveGroup(save_egid); 5576d522f475Smrg TRACE_IDS; 5577d522f475Smrg#endif 5578d522f475Smrg init_utmp(USER_PROCESS, &utmp); 5579d522f475Smrg (void) call_setutent(); 5580d522f475Smrg 5581d522f475Smrg /* 5582d522f475Smrg * We could use getutline() if we didn't support old systems. 5583d522f475Smrg */ 5584d522f475Smrg while ((utptr = find_utmp(&utmp)) != 0) { 5585d522f475Smrg if (utptr->ut_pid == screen->pid) { 5586d522f475Smrg utptr->ut_type = DEAD_PROCESS; 5587d522f475Smrg#if defined(HAVE_UTMP_UT_XTIME) 5588d522f475Smrg#if defined(HAVE_UTMP_UT_SESSION) 5589d522f475Smrg utptr->ut_session = getsid(0); 5590d522f475Smrg#endif 5591d522f475Smrg utptr->ut_xtime = time((time_t *) 0); 5592d522f475Smrg utptr->ut_tv.tv_usec = 0; 5593d522f475Smrg#else 5594d522f475Smrg *utptr->ut_user = 0; 5595d522f475Smrg utptr->ut_time = time((time_t *) 0); 5596d522f475Smrg#endif 5597d522f475Smrg (void) call_pututline(utptr); 5598d522f475Smrg#ifdef WTMP 5599d522f475Smrg#if defined(WTMPX_FILE) && (defined(SVR4) || defined(__SCO__)) 560020d2c4d2Smrg if (xw->misc.login_shell) 5601d522f475Smrg updwtmpx(WTMPX_FILE, utptr); 560204b94745Smrg#elif defined(__linux__) && defined(__GLIBC__) && (__GLIBC__ >= 2) && !(defined(__powerpc__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)) 5603894e0ac8Smrg copy_filled(utmp.ut_line, utptr->ut_line, sizeof(utmp.ut_line)); 560420d2c4d2Smrg if (xw->misc.login_shell) 5605d522f475Smrg call_updwtmp(etc_wtmp, utptr); 5606d522f475Smrg#else 5607d522f475Smrg /* set wtmp entry if wtmp file exists */ 560820d2c4d2Smrg if (xw->misc.login_shell) { 5609d522f475Smrg int fd; 5610d522f475Smrg if ((fd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 56110bd37d32Smrg IGNORE_RC(write(fd, utptr, sizeof(*utptr))); 5612d522f475Smrg close(fd); 5613d522f475Smrg } 5614d522f475Smrg } 5615d522f475Smrg#endif 5616d522f475Smrg#endif 5617d522f475Smrg break; 5618d522f475Smrg } 5619d522f475Smrg memset(utptr, 0, sizeof(*utptr)); /* keep searching */ 5620d522f475Smrg } 5621d522f475Smrg (void) call_endutent(); 5622d522f475Smrg#ifdef USE_UTMP_SETGID 5623d522f475Smrg disableSetGid(); 5624d522f475Smrg TRACE_IDS; 5625d522f475Smrg#endif 5626d522f475Smrg } 5627d522f475Smrg#else /* not USE_SYSV_UTMP */ 5628d522f475Smrg int wfd; 5629d522f475Smrg struct utmp utmp; 5630d522f475Smrg 56310bd37d32Smrg DEBUG_MSG("handle:Exit !USE_SYSV_UTMP\n"); 5632d522f475Smrg if (!resource.utmpInhibit && added_utmp_entry && 5633d522f475Smrg (am_slave < 0 && tslot > 0)) { 5634d522f475Smrg#if defined(USE_UTMP_SETGID) 5635d522f475Smrg setEffectiveGroup(save_egid); 5636d522f475Smrg TRACE_IDS; 5637d522f475Smrg#endif 5638d522f475Smrg if ((wfd = open(etc_utmp, O_WRONLY)) >= 0) { 5639956cc18dSsnj memset(&utmp, 0, sizeof(utmp)); 5640d522f475Smrg lseek(wfd, (long) (tslot * sizeof(utmp)), 0); 56410bd37d32Smrg IGNORE_RC(write(wfd, (char *) &utmp, sizeof(utmp))); 5642d522f475Smrg close(wfd); 5643d522f475Smrg } 5644d522f475Smrg#ifdef WTMP 564520d2c4d2Smrg if (xw->misc.login_shell && 5646d522f475Smrg (wfd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 5647894e0ac8Smrg copy_filled(utmp.ut_line, 5648894e0ac8Smrg my_pty_name(ttydev), 5649894e0ac8Smrg sizeof(utmp.ut_line)); 5650d522f475Smrg utmp.ut_time = time((time_t *) 0); 56510bd37d32Smrg IGNORE_RC(write(wfd, (char *) &utmp, sizeof(utmp))); 5652d522f475Smrg close(wfd); 5653d522f475Smrg } 5654d522f475Smrg#endif /* WTMP */ 5655d522f475Smrg#ifdef USE_UTMP_SETGID 5656d522f475Smrg disableSetGid(); 5657d522f475Smrg TRACE_IDS; 5658d522f475Smrg#endif 5659d522f475Smrg } 5660d522f475Smrg#endif /* USE_SYSV_UTMP */ 5661d522f475Smrg#endif /* HAVE_UTMP */ 5662d522f475Smrg 5663e0a2b6dfSmrg cleanup_colored_cursor(); 5664e0a2b6dfSmrg 5665d522f475Smrg /* 5666d522f475Smrg * Flush pending data before releasing ownership, so nobody else can write 5667d522f475Smrg * in the middle of the data. 5668d522f475Smrg */ 5669d522f475Smrg ttyFlush(screen->respond); 5670d522f475Smrg 5671e39b573cSmrg#ifdef USE_PTY_SEARCH 5672d522f475Smrg if (am_slave < 0) { 5673d522f475Smrg TRACE_IDS; 5674d522f475Smrg /* restore ownership of tty and pty */ 5675d522f475Smrg set_owner(ttydev, 0, 0, 0666U); 5676d522f475Smrg#if (defined(USE_PTY_DEVICE) && !defined(__sgi) && !defined(__hpux)) 5677d522f475Smrg set_owner(ptydev, 0, 0, 0666U); 5678d522f475Smrg#endif 5679d522f475Smrg } 5680e39b573cSmrg#endif 5681d522f475Smrg 5682d522f475Smrg /* 56830bd37d32Smrg * Close after releasing ownership to avoid race condition: other programs 5684d522f475Smrg * grabbing it, and *then* having us release ownership.... 5685d522f475Smrg */ 5686d522f475Smrg close(screen->respond); /* close explicitly to avoid race with slave side */ 5687d522f475Smrg#ifdef ALLOWLOGGING 5688d522f475Smrg if (screen->logging) 568920d2c4d2Smrg CloseLog(xw); 5690d522f475Smrg#endif 5691d522f475Smrg 5692e39b573cSmrg xtermPrintOnXError(xw, n); 5693e39b573cSmrg 5694d522f475Smrg#ifdef NO_LEAKS 5695d522f475Smrg if (n == 0) { 56960bd37d32Smrg Display *dpy = TScreenOf(xw)->display; 56970bd37d32Smrg 5698d522f475Smrg TRACE(("Freeing memory leaks\n")); 5699d522f475Smrg 57000bd37d32Smrg if (toplevel) { 57010bd37d32Smrg XtDestroyWidget(toplevel); 57020bd37d32Smrg TRACE(("destroyed top-level widget\n")); 57030bd37d32Smrg } 57040bd37d32Smrg sortedOpts(0, 0, 0); 57050bd37d32Smrg noleaks_charproc(); 57060bd37d32Smrg noleaks_ptydata(); 5707894e0ac8Smrg#if OPT_GRAPHICS 57084419d26bSmrg noleaks_graphics(dpy); 5709894e0ac8Smrg#endif 5710d522f475Smrg#if OPT_WIDE_CHARS 57110bd37d32Smrg noleaks_CharacterClass(); 5712d522f475Smrg#endif 57130bd37d32Smrg /* XrmSetDatabase(dpy, 0); increases leaks ;-) */ 57140bd37d32Smrg XtCloseDisplay(dpy); 57150bd37d32Smrg XtDestroyApplicationContext(app_con); 57160bd37d32Smrg xtermCloseSession(); 57170bd37d32Smrg TRACE(("closed display\n")); 57180bd37d32Smrg 571920d2c4d2Smrg TRACE_CLOSE(); 5720d522f475Smrg } 5721d522f475Smrg#endif 5722d522f475Smrg 5723d522f475Smrg exit(n); 5724d522f475Smrg} 5725d522f475Smrg 5726d522f475Smrg/* ARGSUSED */ 5727d522f475Smrgstatic void 572820d2c4d2Smrgresize_termcap(XtermWidget xw) 5729d522f475Smrg{ 573020d2c4d2Smrg char *newtc = get_tcap_buffer(xw); 573120d2c4d2Smrg 5732d522f475Smrg#ifndef USE_SYSV_ENVVARS 573304b94745Smrg if (!TEK4014_ACTIVE(xw) && newtc != NULL && *newtc) { 5734d522f475Smrg TScreen *screen = TScreenOf(xw); 5735d522f475Smrg char *ptr1, *ptr2; 5736d522f475Smrg size_t i; 5737d522f475Smrg int li_first = 0; 5738d522f475Smrg char *temp; 5739d522f475Smrg char oldtc[TERMCAP_SIZE]; 5740d522f475Smrg 5741d522f475Smrg strcpy(oldtc, newtc); 5742d522f475Smrg TRACE(("resize %s\n", oldtc)); 5743d522f475Smrg if ((ptr1 = x_strindex(oldtc, "co#")) == NULL) { 5744d522f475Smrg strcat(oldtc, "co#80:"); 5745d522f475Smrg ptr1 = x_strindex(oldtc, "co#"); 5746d522f475Smrg } 5747d522f475Smrg if ((ptr2 = x_strindex(oldtc, "li#")) == NULL) { 5748d522f475Smrg strcat(oldtc, "li#24:"); 5749d522f475Smrg ptr2 = x_strindex(oldtc, "li#"); 5750d522f475Smrg } 5751d522f475Smrg if (ptr1 > ptr2) { 5752d522f475Smrg li_first++; 5753d522f475Smrg temp = ptr1; 5754d522f475Smrg ptr1 = ptr2; 5755d522f475Smrg ptr2 = temp; 5756d522f475Smrg } 5757d522f475Smrg ptr1 += 3; 5758d522f475Smrg ptr2 += 3; 5759956cc18dSsnj strncpy(newtc, oldtc, i = (size_t) (ptr1 - oldtc)); 576004b94745Smrg if (i >= TERMCAP_SIZE - 10) { 576104b94745Smrg TRACE(("...insufficient space: %lu\n", (unsigned long) i)); 576204b94745Smrg return; 576304b94745Smrg } 5764d522f475Smrg temp = newtc + i; 5765d522f475Smrg sprintf(temp, "%d", (li_first 5766d522f475Smrg ? MaxRows(screen) 5767d522f475Smrg : MaxCols(screen))); 5768d522f475Smrg temp += strlen(temp); 57690bd37d32Smrg if ((ptr1 = strchr(ptr1, ':')) != 0 && (ptr1 < ptr2)) { 57700bd37d32Smrg strncpy(temp, ptr1, i = (size_t) (ptr2 - ptr1)); 57710bd37d32Smrg temp += i; 57720bd37d32Smrg sprintf(temp, "%d", (li_first 57730bd37d32Smrg ? MaxCols(screen) 57740bd37d32Smrg : MaxRows(screen))); 57750bd37d32Smrg if ((ptr2 = strchr(ptr2, ':')) != 0) { 57760bd37d32Smrg strcat(temp, ptr2); 57770bd37d32Smrg } 57780bd37d32Smrg } 5779d522f475Smrg TRACE((" ==> %s\n", newtc)); 5780d522f475Smrg TRACE((" new size %dx%d\n", MaxRows(screen), MaxCols(screen))); 5781d522f475Smrg } 5782d522f475Smrg#endif /* USE_SYSV_ENVVARS */ 5783d522f475Smrg} 5784d522f475Smrg 5785d522f475Smrg#endif /* ! VMS */ 5786d522f475Smrg 5787d522f475Smrg/* 5788d522f475Smrg * Does a non-blocking wait for a child process. If the system 5789d522f475Smrg * doesn't support non-blocking wait, do nothing. 5790d522f475Smrg * Returns the pid of the child, or 0 or -1 if none or error. 5791d522f475Smrg */ 5792d522f475Smrgint 5793d522f475Smrgnonblocking_wait(void) 5794d522f475Smrg{ 5795d522f475Smrg#ifdef USE_POSIX_WAIT 5796d522f475Smrg pid_t pid; 5797d522f475Smrg 5798d522f475Smrg pid = waitpid(-1, NULL, WNOHANG); 5799d522f475Smrg#elif defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP)) 5800d522f475Smrg /* cannot do non-blocking wait */ 5801d522f475Smrg int pid = 0; 5802d522f475Smrg#else /* defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP)) */ 5803d522f475Smrg#if defined(Lynx) 5804d522f475Smrg int status; 5805d522f475Smrg#else 5806d522f475Smrg union wait status; 5807d522f475Smrg#endif 5808d522f475Smrg int pid; 5809d522f475Smrg 5810d522f475Smrg pid = wait3(&status, WNOHANG, (struct rusage *) NULL); 5811d522f475Smrg#endif /* USE_POSIX_WAIT else */ 5812d522f475Smrg return pid; 5813d522f475Smrg} 5814d522f475Smrg 5815d522f475Smrg#ifndef VMS 5816d522f475Smrg 5817d522f475Smrg/* ARGSUSED */ 58180bd37d32Smrgstatic void 5819d522f475Smrgreapchild(int n GCC_UNUSED) 5820d522f475Smrg{ 5821d522f475Smrg int olderrno = errno; 5822d522f475Smrg int pid; 5823d522f475Smrg 58240bd37d32Smrg DEBUG_MSG("handle:reapchild\n"); 58250bd37d32Smrg 5826d522f475Smrg pid = wait(NULL); 5827d522f475Smrg 5828d522f475Smrg#ifdef USE_SYSV_SIGNALS 5829d522f475Smrg /* cannot re-enable signal before waiting for child 5830d522f475Smrg * because then SVR4 loops. Sigh. HP-UX 9.01 too. 5831d522f475Smrg */ 5832d522f475Smrg (void) signal(SIGCHLD, reapchild); 5833d522f475Smrg#endif 5834d522f475Smrg 5835d522f475Smrg do { 583620d2c4d2Smrg if (pid == TScreenOf(term)->pid) { 58370bd37d32Smrg DEBUG_MSG("Exiting\n"); 58382e4f8982Smrg if (hold_screen) 58392e4f8982Smrg caught_intr = True; 58402e4f8982Smrg else 5841d522f475Smrg need_cleanup = True; 5842d522f475Smrg } 5843d522f475Smrg } while ((pid = nonblocking_wait()) > 0); 5844d522f475Smrg 5845d522f475Smrg errno = olderrno; 5846d522f475Smrg} 5847d522f475Smrg#endif /* !VMS */ 5848d522f475Smrg 5849d522f475Smrgstatic void 585020d2c4d2Smrgremove_termcap_entry(char *buf, const char *str) 5851d522f475Smrg{ 5852d522f475Smrg char *base = buf; 5853d522f475Smrg char *first = base; 5854d522f475Smrg int count = 0; 5855d522f475Smrg size_t len = strlen(str); 5856d522f475Smrg 5857d522f475Smrg TRACE(("*** remove_termcap_entry('%s', '%s')\n", str, buf)); 5858d522f475Smrg 5859d522f475Smrg while (*buf != 0) { 5860d522f475Smrg if (!count && !strncmp(buf, str, len)) { 5861d522f475Smrg while (*buf != 0) { 5862d522f475Smrg if (*buf == '\\') 5863d522f475Smrg buf++; 5864d522f475Smrg else if (*buf == ':') 5865d522f475Smrg break; 5866d522f475Smrg if (*buf != 0) 5867d522f475Smrg buf++; 5868d522f475Smrg } 58690bd37d32Smrg while ((*first++ = *buf++) != 0) { 58700bd37d32Smrg ; 58710bd37d32Smrg } 5872d522f475Smrg TRACE(("...removed_termcap_entry('%s', '%s')\n", str, base)); 5873d522f475Smrg return; 5874d522f475Smrg } else if (*buf == '\\') { 5875d522f475Smrg buf++; 5876d522f475Smrg } else if (*buf == ':') { 5877d522f475Smrg first = buf; 5878d522f475Smrg count = 0; 5879d522f475Smrg } else if (!isspace(CharOf(*buf))) { 5880d522f475Smrg count++; 5881d522f475Smrg } 5882d522f475Smrg if (*buf != 0) 5883d522f475Smrg buf++; 5884d522f475Smrg } 5885d522f475Smrg TRACE(("...cannot remove\n")); 5886d522f475Smrg} 5887d522f475Smrg 5888d522f475Smrg/* 5889d522f475Smrg * parse_tty_modes accepts lines of the following form: 5890d522f475Smrg * 5891d522f475Smrg * [SETTING] ... 5892d522f475Smrg * 5893f2e35a3aSmrg * where setting consists of the words in the ttyModes[] array followed by a 5894f2e35a3aSmrg * character or ^char. 5895d522f475Smrg */ 5896d522f475Smrgstatic int 5897f2e35a3aSmrgparse_tty_modes(char *s) 5898d522f475Smrg{ 5899d522f475Smrg int c; 5900f2e35a3aSmrg Cardinal j, k; 5901d522f475Smrg int count = 0; 5902f2e35a3aSmrg Boolean found; 5903d522f475Smrg 5904d522f475Smrg TRACE(("parse_tty_modes\n")); 5905a1f3da82Smrg for (;;) { 5906d522f475Smrg size_t len; 5907d522f475Smrg 5908f2e35a3aSmrg while (*s && isspace(CharOf(*s))) { 5909d522f475Smrg s++; 5910f2e35a3aSmrg } 5911f2e35a3aSmrg if (!*s) { 5912d522f475Smrg return count; 5913f2e35a3aSmrg } 5914d522f475Smrg 5915f2e35a3aSmrg for (len = 0; s[len] && !isspace(CharOf(s[len])); ++len) { 5916f2e35a3aSmrg ; 5917f2e35a3aSmrg } 5918f2e35a3aSmrg found = False; 5919f2e35a3aSmrg for (j = 0; j < XtNumber(ttyModes); ++j) { 5920f2e35a3aSmrg if (len == ttyModes[j].len 5921f2e35a3aSmrg && strncmp(s, 5922f2e35a3aSmrg ttyModes[j].name, 5923f2e35a3aSmrg ttyModes[j].len) == 0) { 5924f2e35a3aSmrg found = True; 5925d522f475Smrg break; 5926f2e35a3aSmrg } 5927d522f475Smrg } 5928f2e35a3aSmrg if (!found) { 5929d522f475Smrg return -1; 5930f2e35a3aSmrg } 5931d522f475Smrg 5932f2e35a3aSmrg s += ttyModes[j].len; 5933f2e35a3aSmrg while (*s && isspace(CharOf(*s))) { 5934d522f475Smrg s++; 5935f2e35a3aSmrg } 5936d522f475Smrg 5937f2e35a3aSmrg /* check if this needs a parameter */ 5938f2e35a3aSmrg found = False; 5939f2e35a3aSmrg for (k = 0, c = 0; k < XtNumber(ttyChars); ++k) { 5940f2e35a3aSmrg if ((int) j == ttyChars[k].myMode) { 5941f2e35a3aSmrg if (ttyChars[k].sysMode < 0) { 5942f2e35a3aSmrg found = True; 5943f2e35a3aSmrg c = ttyChars[k].myDefault; 5944f2e35a3aSmrg } 5945f2e35a3aSmrg break; 5946f2e35a3aSmrg } 5947f2e35a3aSmrg } 5948f2e35a3aSmrg 5949f2e35a3aSmrg if (!found) { 5950f2e35a3aSmrg if (!*s 5951f2e35a3aSmrg || (c = decode_keyvalue(&s, False)) == -1) { 5952f2e35a3aSmrg return -1; 5953f2e35a3aSmrg } 5954d522f475Smrg } 5955f2e35a3aSmrg ttyModes[j].value = c; 5956f2e35a3aSmrg ttyModes[j].set = 1; 5957f2e35a3aSmrg count++; 5958f2e35a3aSmrg TRACE(("...parsed #%d: %s=%#x\n", count, ttyModes[j].name, c)); 5959d522f475Smrg } 5960d522f475Smrg} 5961d522f475Smrg 596204b94745Smrg#ifndef GetBytesAvailable 5963d522f475Smrgint 596404b94745SmrgGetBytesAvailable(Display *dpy) 5965d522f475Smrg{ 596604b94745Smrg int fd = ConnectionNumber(dpy); 596704b94745Smrg int result; 5968d522f475Smrg#if defined(FIONREAD) 596904b94745Smrg ioctl(fd, FIONREAD, (char *) &result); 5970d522f475Smrg#elif defined(__CYGWIN__) 5971d522f475Smrg fd_set set; 597220d2c4d2Smrg struct timeval select_timeout = 5973d522f475Smrg {0, 0}; 5974d522f475Smrg 5975d522f475Smrg FD_ZERO(&set); 5976d522f475Smrg FD_SET(fd, &set); 597704b94745Smrg result = (Select(fd + 1, &set, NULL, NULL, &select_timeout) > 0) ? 1 : 0; 597804b94745Smrg#else 5979d522f475Smrg struct pollfd pollfds[1]; 5980d522f475Smrg 5981d522f475Smrg pollfds[0].fd = fd; 5982d522f475Smrg pollfds[0].events = POLLIN; 598304b94745Smrg result = poll(pollfds, 1, 0); 5984d522f475Smrg#endif 598504b94745Smrg return result; 5986d522f475Smrg} 5987d522f475Smrg#endif /* !VMS */ 5988d522f475Smrg 5989d522f475Smrg/* Utility function to try to hide system differences from 5990d522f475Smrg everybody who used to call killpg() */ 5991d522f475Smrg 5992d522f475Smrgint 5993d522f475Smrgkill_process_group(int pid, int sig) 5994d522f475Smrg{ 5995d522f475Smrg TRACE(("kill_process_group(pid=%d, sig=%d)\n", pid, sig)); 5996d522f475Smrg#if defined(SVR4) || defined(SYSV) || !defined(X_NOT_POSIX) 5997d522f475Smrg return kill(-pid, sig); 5998d522f475Smrg#else 5999d522f475Smrg return killpg(pid, sig); 6000d522f475Smrg#endif 6001d522f475Smrg} 6002d522f475Smrg 6003d522f475Smrg#if OPT_EBCDIC 6004d522f475Smrgint 6005d522f475SmrgA2E(int x) 6006d522f475Smrg{ 6007d522f475Smrg char c; 6008d522f475Smrg c = x; 6009d522f475Smrg __atoe_l(&c, 1); 6010d522f475Smrg return c; 6011d522f475Smrg} 6012d522f475Smrg 6013d522f475Smrgint 6014d522f475SmrgE2A(int x) 6015d522f475Smrg{ 6016d522f475Smrg char c; 6017d522f475Smrg c = x; 6018d522f475Smrg __etoa_l(&c, 1); 6019d522f475Smrg return c; 6020d522f475Smrg} 6021d522f475Smrg#endif 6022d522f475Smrg 6023d522f475Smrg#if defined(__QNX__) && !defined(__QNXNTO__) 6024d522f475Smrg#include <sys/types.h> 6025d522f475Smrg#include <sys/proc_msg.h> 6026d522f475Smrg#include <sys/kernel.h> 6027d522f475Smrg#include <string.h> 6028d522f475Smrg#include <errno.h> 6029d522f475Smrg 6030d522f475Smrgstruct _proc_session ps; 6031d522f475Smrgstruct _proc_session_reply rps; 6032d522f475Smrg 6033d522f475Smrgint 6034d522f475Smrgqsetlogin(char *login, char *ttyname) 6035d522f475Smrg{ 6036d522f475Smrg int v = getsid(getpid()); 6037d522f475Smrg 6038d522f475Smrg memset(&ps, 0, sizeof(ps)); 6039d522f475Smrg memset(&rps, 0, sizeof(rps)); 6040d522f475Smrg 6041d522f475Smrg ps.type = _PROC_SESSION; 6042d522f475Smrg ps.subtype = _PROC_SUB_ACTION1; 6043d522f475Smrg ps.sid = v; 6044d522f475Smrg strcpy(ps.name, login); 6045d522f475Smrg 6046d522f475Smrg Send(1, &ps, &rps, sizeof(ps), sizeof(rps)); 6047d522f475Smrg 6048d522f475Smrg if (rps.status < 0) 6049d522f475Smrg return (rps.status); 6050d522f475Smrg 6051d522f475Smrg ps.type = _PROC_SESSION; 6052d522f475Smrg ps.subtype = _PROC_SUB_ACTION2; 6053d522f475Smrg ps.sid = v; 6054d522f475Smrg sprintf(ps.name, "//%d%s", getnid(), ttyname); 6055d522f475Smrg Send(1, &ps, &rps, sizeof(ps), sizeof(rps)); 6056d522f475Smrg 6057d522f475Smrg return (rps.status); 6058d522f475Smrg} 6059d522f475Smrg#endif 606001037d57Smrg 606101037d57Smrg#ifdef __minix 606201037d57Smrgint 606301037d57Smrgsetpgrp(void) 606401037d57Smrg{ 606501037d57Smrg return 0; 606601037d57Smrg} 606701037d57Smrg 606801037d57Smrgvoid 606901037d57Smrg_longjmp(jmp_buf _env, int _val) 607001037d57Smrg{ 607101037d57Smrg longjmp(_env, _val); 607201037d57Smrg} 607301037d57Smrg#endif 6074