main.c revision 4419d26b
14419d26bSmrg/* $XTermId: main.c,v 1.886 2022/02/22 23:35:41 tom Exp $ */ 20bd37d32Smrg 30bd37d32Smrg/* 44419d26bSmrg * Copyright 2002-2021,2022 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 96d522f475Smrg#if OPT_TOOLBAR 97d522f475Smrg 98d522f475Smrg#if defined(HAVE_LIB_XAW) 99d522f475Smrg#include <X11/Xaw/Form.h> 100d522f475Smrg#elif defined(HAVE_LIB_XAW3D) 101d522f475Smrg#include <X11/Xaw3d/Form.h> 10201037d57Smrg#elif defined(HAVE_LIB_XAW3DXFT) 10301037d57Smrg#include <X11/Xaw3dxft/Form.h> 104f2e35a3aSmrg#include <X11/Xaw3dxft/Xaw3dXft.h> 105d522f475Smrg#elif defined(HAVE_LIB_NEXTAW) 106d522f475Smrg#include <X11/neXtaw/Form.h> 107d522f475Smrg#elif defined(HAVE_LIB_XAWPLUS) 108d522f475Smrg#include <X11/XawPlus/Form.h> 109d522f475Smrg#endif 110d522f475Smrg 111f2e35a3aSmrg#else 112f2e35a3aSmrg 113f2e35a3aSmrg#if defined(HAVE_LIB_XAW3DXFT) 114f2e35a3aSmrg#include <X11/Xaw3dxft/Xaw3dXft.h> 115f2e35a3aSmrg#endif 116f2e35a3aSmrg 117d522f475Smrg#endif /* OPT_TOOLBAR */ 118d522f475Smrg 119d522f475Smrg#include <pwd.h> 120d522f475Smrg#include <ctype.h> 121d522f475Smrg 122d522f475Smrg#include <data.h> 123d522f475Smrg#include <error.h> 124d522f475Smrg#include <menu.h> 125d522f475Smrg#include <main.h> 126d522f475Smrg#include <xstrings.h> 127d522f475Smrg#include <xtermcap.h> 128d522f475Smrg#include <xterm_io.h> 129d522f475Smrg 130d522f475Smrg#if OPT_WIDE_CHARS 131d522f475Smrg#include <charclass.h> 132d522f475Smrg#endif 133d522f475Smrg 134d522f475Smrg#ifdef __osf__ 135d522f475Smrg#define USE_SYSV_SIGNALS 136d522f475Smrg#define WTMP 137d522f475Smrg#include <pty.h> /* openpty() */ 138d522f475Smrg#endif 139d522f475Smrg 140d522f475Smrg#ifdef __sgi 141d522f475Smrg#include <grp.h> /* initgroups() */ 142d522f475Smrg#endif 143d522f475Smrg 144ad37e533Smrgstatic GCC_NORETURN void hungtty(int); 145ad37e533Smrgstatic GCC_NORETURN void Syntax(char *); 146ad37e533Smrgstatic GCC_NORETURN void HsSysError(int); 147d522f475Smrg 1482e4f8982Smrg#if defined(__SCO__) || defined(SVR4) || defined(_POSIX_SOURCE) || ( defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 1) ) 149d522f475Smrg#define USE_POSIX_SIGNALS 150d522f475Smrg#endif 151d522f475Smrg 152d522f475Smrg#if defined(SYSV) && !defined(SVR4) && !defined(ISC22) && !defined(ISC30) 153d522f475Smrg/* older SYSV systems cannot ignore SIGHUP. 154d522f475Smrg Shell hangs, or you get extra shells, or something like that */ 155d522f475Smrg#define USE_SYSV_SIGHUP 156d522f475Smrg#endif 157d522f475Smrg 158d522f475Smrg#if defined(sony) && defined(bsd43) && !defined(KANJI) 159d522f475Smrg#define KANJI 160d522f475Smrg#endif 161d522f475Smrg 162d522f475Smrg#ifdef linux 163d522f475Smrg#define USE_SYSV_PGRP 164d522f475Smrg#define USE_SYSV_SIGNALS 165d522f475Smrg#define WTMP 166d522f475Smrg#ifdef __GLIBC__ 167d522f475Smrg#if (__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)) 168d522f475Smrg#include <pty.h> 169d522f475Smrg#endif 170d522f475Smrg#endif 171d522f475Smrg#endif 172d522f475Smrg 173d522f475Smrg#ifdef __MVS__ 174d522f475Smrg#define USE_SYSV_PGRP 175d522f475Smrg#define USE_SYSV_SIGNALS 176d522f475Smrg#endif 177d522f475Smrg 178d522f475Smrg#ifdef __CYGWIN__ 179d522f475Smrg#define WTMP 180d522f475Smrg#endif 181d522f475Smrg 182d522f475Smrg#ifdef __SCO__ 183d522f475Smrg#ifndef _SVID3 184d522f475Smrg#define _SVID3 185d522f475Smrg#endif 186d522f475Smrg#endif 187d522f475Smrg 188d522f475Smrg#if defined(__GLIBC__) && !defined(linux) 189d522f475Smrg#define USE_SYSV_PGRP 190d522f475Smrg#define WTMP 191d522f475Smrg#endif 192d522f475Smrg 193f2e35a3aSmrg#if defined(USE_TTY_GROUP) || defined(USE_UTMP_SETGID) || defined(HAVE_INITGROUPS) 194d522f475Smrg#include <grp.h> 195d522f475Smrg#endif 196d522f475Smrg 197d522f475Smrg#ifndef TTY_GROUP_NAME 198d522f475Smrg#define TTY_GROUP_NAME "tty" 199d522f475Smrg#endif 200d522f475Smrg 201d522f475Smrg#include <sys/stat.h> 202d522f475Smrg 203d522f475Smrg#ifdef Lynx 204d522f475Smrg#ifndef BSDLY 205d522f475Smrg#define BSDLY 0 206d522f475Smrg#endif 207d522f475Smrg#ifndef VTDLY 208d522f475Smrg#define VTDLY 0 209d522f475Smrg#endif 210d522f475Smrg#ifndef FFDLY 211d522f475Smrg#define FFDLY 0 212d522f475Smrg#endif 213d522f475Smrg#endif 214d522f475Smrg 215d522f475Smrg#ifdef SYSV /* { */ 216d522f475Smrg 217d522f475Smrg#ifdef USE_USG_PTYS /* AT&T SYSV has no ptyio.h */ 218d522f475Smrg#include <sys/stropts.h> /* for I_PUSH */ 219d522f475Smrg#include <poll.h> /* for POLLIN */ 220d522f475Smrg#endif /* USE_USG_PTYS */ 221d522f475Smrg 222d522f475Smrg#define USE_SYSV_SIGNALS 223d522f475Smrg#define USE_SYSV_PGRP 224d522f475Smrg 225d522f475Smrg#if !defined(TIOCSWINSZ) || defined(__SCO__) || defined(__UNIXWARE__) 226d522f475Smrg#define USE_SYSV_ENVVARS /* COLUMNS/LINES vs. TERMCAP */ 227d522f475Smrg#endif 228d522f475Smrg 229d522f475Smrg/* 230d522f475Smrg * now get system-specific includes 231d522f475Smrg */ 232d522f475Smrg#ifdef macII 233d522f475Smrg#include <sys/ttychars.h> 234d522f475Smrg#undef USE_SYSV_ENVVARS 235d522f475Smrg#undef FIOCLEX 236d522f475Smrg#undef FIONCLEX 237d522f475Smrg#define setpgrp2 setpgrp 238d522f475Smrg#include <sgtty.h> 239d522f475Smrg#include <sys/resource.h> 240d522f475Smrg#endif 241d522f475Smrg 242d522f475Smrg#ifdef __hpux 243d522f475Smrg#include <sys/ptyio.h> 244d522f475Smrg#endif /* __hpux */ 245d522f475Smrg 246d522f475Smrg#ifdef __osf__ 247d522f475Smrg#undef USE_SYSV_PGRP 248d522f475Smrg#define setpgrp setpgid 249d522f475Smrg#endif 250d522f475Smrg 251d522f475Smrg#ifdef __sgi 252d522f475Smrg#include <sys/sysmacros.h> 253d522f475Smrg#endif /* __sgi */ 254d522f475Smrg 255d522f475Smrg#ifdef sun 256d522f475Smrg#include <sys/strredir.h> 257d522f475Smrg#endif 258d522f475Smrg 259e39b573cSmrg#else /* } !SYSV { */ /* BSD systems */ 260d522f475Smrg 261d522f475Smrg#ifdef __QNX__ 262d522f475Smrg 263d522f475Smrg#ifndef __QNXNTO__ 264d522f475Smrg#define ttyslot() 1 265d522f475Smrg#else 266d522f475Smrg#define USE_SYSV_PGRP 267d522f475Smrgextern __inline__ 268d522f475Smrgint 269d522f475Smrgttyslot(void) 270d522f475Smrg{ 271d522f475Smrg return 1; /* yuk */ 272d522f475Smrg} 273d522f475Smrg#endif 274d522f475Smrg 275d522f475Smrg#else 276d522f475Smrg 277d522f475Smrg#if defined(__INTERIX) || defined(__APPLE__) 278d522f475Smrg#define setpgrp setpgid 279d522f475Smrg#endif 280d522f475Smrg 281d522f475Smrg#ifndef linux 282d522f475Smrg#ifndef VMS 283d522f475Smrg#ifndef USE_POSIX_TERMIOS 284d522f475Smrg#ifndef USE_ANY_SYSV_TERMIO 285d522f475Smrg#include <sgtty.h> 286d522f475Smrg#endif 287d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 288d522f475Smrg#ifdef Lynx 289d522f475Smrg#include <resource.h> 290d522f475Smrg#else 291d522f475Smrg#include <sys/resource.h> 292d522f475Smrg#endif 293d522f475Smrg#endif /* !VMS */ 294d522f475Smrg#endif /* !linux */ 295d522f475Smrg 296d522f475Smrg#endif /* __QNX__ */ 297d522f475Smrg 298d522f475Smrg#endif /* } !SYSV */ 299d522f475Smrg 300d522f475Smrg/* Xpoll.h and <sys/param.h> on glibc 2.1 systems have colliding NBBY's */ 301d522f475Smrg#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))) 302d522f475Smrg#ifndef NOFILE 303d522f475Smrg#define NOFILE OPEN_MAX 304d522f475Smrg#endif 305d522f475Smrg#elif !(defined(VMS) || defined(WIN32) || defined(Lynx) || defined(__GNU__) || defined(__MVS__)) 306d522f475Smrg#include <sys/param.h> /* for NOFILE */ 307d522f475Smrg#endif 308d522f475Smrg 309d522f475Smrg#if defined(BSD) && (BSD >= 199103) 310d522f475Smrg#define WTMP 311d522f475Smrg#endif 312d522f475Smrg 313d522f475Smrg#include <stdio.h> 314d522f475Smrg 315d522f475Smrg#ifdef __hpux 316d522f475Smrg#include <sys/utsname.h> 317d522f475Smrg#endif /* __hpux */ 318d522f475Smrg 319d522f475Smrg#if defined(apollo) && (OSMAJORVERSION == 10) && (OSMINORVERSION < 4) 320d522f475Smrg#define ttyslot() 1 321d522f475Smrg#endif /* apollo */ 322d522f475Smrg 323d522f475Smrg#if defined(UTMPX_FOR_UTMP) 324d522f475Smrg#define UTMP_STR utmpx 325d522f475Smrg#else 326d522f475Smrg#define UTMP_STR utmp 327d522f475Smrg#endif 328d522f475Smrg 329d522f475Smrg#if defined(USE_UTEMPTER) 330d522f475Smrg#include <utempter.h> 331f2e35a3aSmrg#if 1 332f2e35a3aSmrg#define UTEMPTER_ADD(pty,hostname,master_fd) utempter_add_record(master_fd, hostname) 333f2e35a3aSmrg#define UTEMPTER_DEL() utempter_remove_added_record () 334f2e35a3aSmrg#else 335f2e35a3aSmrg#define UTEMPTER_ADD(pty,hostname,master_fd) addToUtmp(pty, hostname, master_fd) 336f2e35a3aSmrg#define UTEMPTER_DEL() removeFromUtmp() 337f2e35a3aSmrg#endif 338d522f475Smrg#endif 339d522f475Smrg 3402e4f8982Smrg#if defined(I_FIND) && defined(I_PUSH) 3412e4f8982Smrg#define PUSH_FAILS(fd,name) ioctl(fd, I_FIND, name) == 0 \ 3422e4f8982Smrg && ioctl(fd, I_PUSH, name) < 0 3432e4f8982Smrg#else 3442e4f8982Smrg#define PUSH_FAILS(fd,name) ioctl(fd, I_PUSH, name) < 0 3452e4f8982Smrg#endif 3462e4f8982Smrg 347d522f475Smrg#if defined(UTMPX_FOR_UTMP) 348d522f475Smrg 349d522f475Smrg#include <utmpx.h> 350d522f475Smrg 351d522f475Smrg#define call_endutent endutxent 352d522f475Smrg#define call_getutid getutxid 353d522f475Smrg#define call_pututline pututxline 354d522f475Smrg#define call_setutent setutxent 355d522f475Smrg#define call_updwtmp updwtmpx 356d522f475Smrg 357d522f475Smrg#elif defined(HAVE_UTMP) 358d522f475Smrg 359d522f475Smrg#include <utmp.h> 360d522f475Smrg 361d522f475Smrg#if defined(_CRAY) && (OSMAJORVERSION < 8) 362d522f475Smrgextern struct utmp *getutid __((struct utmp * _Id)); 363d522f475Smrg#endif 364d522f475Smrg 365d522f475Smrg#define call_endutent endutent 366d522f475Smrg#define call_getutid getutid 367d522f475Smrg#define call_pututline pututline 368d522f475Smrg#define call_setutent setutent 369d522f475Smrg#define call_updwtmp updwtmp 370d522f475Smrg 371d522f475Smrg#endif 372d522f475Smrg 373d522f475Smrg#if defined(USE_LASTLOG) && defined(HAVE_LASTLOG_H) 374d522f475Smrg#include <lastlog.h> /* caution: glibc includes utmp.h here */ 375d522f475Smrg#endif 376d522f475Smrg 377d522f475Smrg#ifndef USE_LASTLOGX 378d522f475Smrg#if defined(_NETBSD_SOURCE) && defined(_PATH_LASTLOGX) 379d522f475Smrg#define USE_LASTLOGX 1 380d522f475Smrg#endif 381d522f475Smrg#endif 382d522f475Smrg 383d522f475Smrg#ifdef PUCC_PTYD 384d522f475Smrg#include <local/openpty.h> 385d522f475Smrg#endif /* PUCC_PTYD */ 386d522f475Smrg 387d522f475Smrg#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) 388d522f475Smrg#include <util.h> /* openpty() */ 389d522f475Smrg#endif 390d522f475Smrg 391956cc18dSsnj#if defined(__FreeBSD__) || defined(__DragonFly__) 392d522f475Smrg#include <libutil.h> /* openpty() */ 393d522f475Smrg#endif 394d522f475Smrg 395d522f475Smrg#if !defined(UTMP_FILENAME) 396d522f475Smrg#if defined(UTMP_FILE) 397d522f475Smrg#define UTMP_FILENAME UTMP_FILE 398d522f475Smrg#elif defined(_PATH_UTMP) 399d522f475Smrg#define UTMP_FILENAME _PATH_UTMP 400d522f475Smrg#else 401d522f475Smrg#define UTMP_FILENAME "/etc/utmp" 402d522f475Smrg#endif 403d522f475Smrg#endif 404d522f475Smrg 405d522f475Smrg#ifndef LASTLOG_FILENAME 406d522f475Smrg#ifdef _PATH_LASTLOG 407d522f475Smrg#define LASTLOG_FILENAME _PATH_LASTLOG 408d522f475Smrg#else 409d522f475Smrg#define LASTLOG_FILENAME "/usr/adm/lastlog" /* only on BSD systems */ 410d522f475Smrg#endif 411d522f475Smrg#endif 412d522f475Smrg 413d522f475Smrg#if !defined(WTMP_FILENAME) 414d522f475Smrg#if defined(WTMP_FILE) 415d522f475Smrg#define WTMP_FILENAME WTMP_FILE 416d522f475Smrg#elif defined(_PATH_WTMP) 417d522f475Smrg#define WTMP_FILENAME _PATH_WTMP 418d522f475Smrg#elif defined(SYSV) 419d522f475Smrg#define WTMP_FILENAME "/etc/wtmp" 420d522f475Smrg#else 421d522f475Smrg#define WTMP_FILENAME "/usr/adm/wtmp" 422d522f475Smrg#endif 423d522f475Smrg#endif 424d522f475Smrg 425d522f475Smrg#include <signal.h> 426d522f475Smrg 427d522f475Smrg#if defined(__SCO__) || (defined(ISC) && !defined(_POSIX_SOURCE)) 428d522f475Smrg#undef SIGTSTP /* defined, but not the BSD way */ 429d522f475Smrg#endif 430d522f475Smrg 431d522f475Smrg#ifdef SIGTSTP 432d522f475Smrg#include <sys/wait.h> 433d522f475Smrg#endif 434d522f475Smrg 435d522f475Smrg#if defined(__SCO__) || defined(__UNIXWARE__) 436d522f475Smrg#undef ECHOKE 437d522f475Smrg#undef ECHOCTL 438d522f475Smrg#endif 439d522f475Smrg 440d522f475Smrg#if defined(HAVE_SYS_TTYDEFAULTS_H) && !defined(CEOF) 441d522f475Smrg#include <sys/ttydefaults.h> 442d522f475Smrg#endif 443d522f475Smrg 444d522f475Smrg#ifdef X_NOT_POSIX 445d522f475Smrgextern long lseek(); 446d522f475Smrg#if defined(USG) || defined(SVR4) 447d522f475Smrgextern unsigned sleep(); 448d522f475Smrg#else 449d522f475Smrgextern void sleep(); 450d522f475Smrg#endif 451d522f475Smrgextern char *ttyname(); 452d522f475Smrg#endif 453d522f475Smrg 454d522f475Smrg#if defined(SYSV) && defined(DECL_PTSNAME) 455d522f475Smrgextern char *ptsname(int); 456d522f475Smrg#endif 457d522f475Smrg 458d522f475Smrg#ifndef VMS 4590bd37d32Smrgstatic void reapchild(int /* n */ ); 4602e4f8982Smrgstatic int spawnXTerm(XtermWidget /* xw */ 4612e4f8982Smrg ,unsigned /* line_speed */ ); 46220d2c4d2Smrgstatic void remove_termcap_entry(char *, const char *); 463d522f475Smrg#ifdef USE_PTY_SEARCH 46420d2c4d2Smrgstatic int pty_search(int * /* pty */ ); 465d522f475Smrg#endif 466d522f475Smrg#endif /* ! VMS */ 467d522f475Smrg 468d522f475Smrgstatic int get_pty(int *pty, char *from); 46920d2c4d2Smrgstatic void resize_termcap(XtermWidget xw); 470e0a2b6dfSmrgstatic void set_owner(char *device, unsigned uid, unsigned gid, unsigned mode); 471d522f475Smrg 472d522f475Smrgstatic Bool added_utmp_entry = False; 473d522f475Smrg 474d522f475Smrg#ifdef HAVE_POSIX_SAVED_IDS 475d522f475Smrgstatic uid_t save_euid; 476d522f475Smrgstatic gid_t save_egid; 477d522f475Smrg#endif 478d522f475Smrg 479d522f475Smrgstatic uid_t save_ruid; 480d522f475Smrgstatic gid_t save_rgid; 481d522f475Smrg 482d522f475Smrg#if defined(USE_UTMP_SETGID) 483d522f475Smrgstatic int really_get_pty(int *pty, char *from); 484d522f475Smrg#endif 485d522f475Smrg 486d522f475Smrg#if defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 487d522f475Smrgstatic Bool xterm_exiting = False; 488d522f475Smrg#endif 489d522f475Smrg 490d522f475Smrgstatic char *explicit_shname = NULL; 491d522f475Smrg 492d522f475Smrg/* 493d522f475Smrg** Ordinarily it should be okay to omit the assignment in the following 494d522f475Smrg** statement. Apparently the c89 compiler on AIX 4.1.3 has a bug, or does 495d522f475Smrg** it? Without the assignment though the compiler will init command_to_exec 496d522f475Smrg** to 0xffffffff instead of NULL; and subsequent usage, e.g. in spawnXTerm() to 497d522f475Smrg** SEGV. 498d522f475Smrg*/ 499d522f475Smrgstatic char **command_to_exec = NULL; 500d522f475Smrg 501d522f475Smrg#if OPT_LUIT_PROG 502d522f475Smrgstatic char **command_to_exec_with_luit = NULL; 5030bd37d32Smrgstatic unsigned command_length_with_luit = 0; 504d522f475Smrg#endif 505d522f475Smrg 506d522f475Smrg#define TERMCAP_ERASE "kb" 507d522f475Smrg#define VAL_INITIAL_ERASE A2E(8) 508d522f475Smrg 509d522f475Smrg/* choose a nice default value for speed - if we make it too low, users who 510d522f475Smrg * mistakenly use $TERM set to vt100 will get padding delays. Setting it to a 511d522f475Smrg * higher value is not useful since legacy applications (termcap) that care 512d522f475Smrg * about padding generally store the code in a short, which does not have 513d522f475Smrg * enough bits for the extended values. 514d522f475Smrg */ 515d522f475Smrg#ifdef B38400 /* everyone should define this */ 516d522f475Smrg#define VAL_LINE_SPEED B38400 517d522f475Smrg#else /* ...but xterm's used this for a long time */ 518d522f475Smrg#define VAL_LINE_SPEED B9600 519d522f475Smrg#endif 520d522f475Smrg 521d522f475Smrg/* 522d522f475Smrg * Allow use of system default characters if defined and reasonable. 523d522f475Smrg * These are based on the BSD ttydefaults.h 524d522f475Smrg */ 525d522f475Smrg#ifndef CBRK 526d522f475Smrg#define CBRK 0xff /* was 0 */ 527d522f475Smrg#endif 528d522f475Smrg#ifndef CDISCARD 529d522f475Smrg#define CDISCARD CONTROL('O') 530d522f475Smrg#endif 531d522f475Smrg#ifndef CDSUSP 532d522f475Smrg#define CDSUSP CONTROL('Y') 533d522f475Smrg#endif 534d522f475Smrg#ifndef CEOF 535d522f475Smrg#define CEOF CONTROL('D') 536d522f475Smrg#endif 537d522f475Smrg#ifndef CEOL 538d522f475Smrg#define CEOL 0xff /* was 0 */ 539d522f475Smrg#endif 540d522f475Smrg#ifndef CERASE 541d522f475Smrg#define CERASE 0177 542d522f475Smrg#endif 543d522f475Smrg#ifndef CERASE2 544d522f475Smrg#define CERASE2 CONTROL('H') 545d522f475Smrg#endif 546d522f475Smrg#ifndef CFLUSH 547d522f475Smrg#define CFLUSH CONTROL('O') 548d522f475Smrg#endif 549d522f475Smrg#ifndef CINTR 550d522f475Smrg#define CINTR CONTROL('C') 551d522f475Smrg#endif 552d522f475Smrg#ifndef CKILL 553d522f475Smrg#define CKILL CONTROL('U') /* was '@' */ 554d522f475Smrg#endif 555d522f475Smrg#ifndef CLNEXT 556d522f475Smrg#define CLNEXT CONTROL('V') 557d522f475Smrg#endif 558d522f475Smrg#ifndef CNUL 559d522f475Smrg#define CNUL 0 560d522f475Smrg#endif 561d522f475Smrg#ifndef CQUIT 562d522f475Smrg#define CQUIT CONTROL('\\') 563d522f475Smrg#endif 564d522f475Smrg#ifndef CRPRNT 565d522f475Smrg#define CRPRNT CONTROL('R') 566d522f475Smrg#endif 567d522f475Smrg#ifndef CREPRINT 568d522f475Smrg#define CREPRINT CRPRNT 569d522f475Smrg#endif 570d522f475Smrg#ifndef CSTART 571d522f475Smrg#define CSTART CONTROL('Q') 572d522f475Smrg#endif 573d522f475Smrg#ifndef CSTATUS 574d522f475Smrg#define CSTATUS CONTROL('T') 575d522f475Smrg#endif 576d522f475Smrg#ifndef CSTOP 577d522f475Smrg#define CSTOP CONTROL('S') 578d522f475Smrg#endif 579d522f475Smrg#ifndef CSUSP 580d522f475Smrg#define CSUSP CONTROL('Z') 581d522f475Smrg#endif 582d522f475Smrg#ifndef CSWTCH 583d522f475Smrg#define CSWTCH 0 584d522f475Smrg#endif 585d522f475Smrg#ifndef CWERASE 586d522f475Smrg#define CWERASE CONTROL('W') 587d522f475Smrg#endif 588d522f475Smrg 589d522f475Smrg#ifdef USE_ANY_SYSV_TERMIO 590d522f475Smrg#define TERMIO_STRUCT struct termio 591d522f475Smrg#define ttySetAttr(fd, datap) ioctl(fd, TCSETA, datap) 592d522f475Smrg#define ttyGetAttr(fd, datap) ioctl(fd, TCGETA, datap) 593d522f475Smrg#define ttyFlush(fd) ioctl(fd, TCFLSH, 1) 594d522f475Smrg#elif defined(USE_POSIX_TERMIOS) 595d522f475Smrg#define TERMIO_STRUCT struct termios 596d522f475Smrg#define ttySetAttr(fd, datap) tcsetattr(fd, TCSANOW, datap) 597d522f475Smrg#define ttyGetAttr(fd, datap) tcgetattr(fd, datap) 598d522f475Smrg#define ttyFlush(fd) tcflush(fd, TCOFLUSH) 599d522f475Smrg#endif /* USE_ANY_SYSV_TERMIO */ 600d522f475Smrg 601d522f475Smrg#ifndef VMS 602d522f475Smrg#ifdef TERMIO_STRUCT 603d522f475Smrg/* The following structures are initialized in main() in order 604d522f475Smrg** to eliminate any assumptions about the internal order of their 605d522f475Smrg** contents. 606d522f475Smrg*/ 607d522f475Smrgstatic TERMIO_STRUCT d_tio; 608d522f475Smrg 609f2e35a3aSmrg#ifndef ONLCR 610f2e35a3aSmrg#define ONLCR 0 611f2e35a3aSmrg#endif 612f2e35a3aSmrg 613f2e35a3aSmrg#ifndef OPOST 614f2e35a3aSmrg#define OPOST 0 615f2e35a3aSmrg#endif 616f2e35a3aSmrg 617f2e35a3aSmrg#define D_TIO_FLAGS (OPOST | ONLCR) 618f2e35a3aSmrg 619d522f475Smrg#ifdef HAS_LTCHARS 620d522f475Smrgstatic struct ltchars d_ltc; 621d522f475Smrg#endif /* HAS_LTCHARS */ 622d522f475Smrg 623d522f475Smrg#ifdef TIOCLSET 624d522f475Smrgstatic unsigned int d_lmode; 625d522f475Smrg#endif /* TIOCLSET */ 626d522f475Smrg 627d522f475Smrg#else /* !TERMIO_STRUCT */ 628f2e35a3aSmrg 629f2e35a3aSmrg#define D_SG_FLAGS (EVENP | ODDP | ECHO | CRMOD) 630f2e35a3aSmrg 631d522f475Smrgstatic struct sgttyb d_sg = 632d522f475Smrg{ 633f2e35a3aSmrg 0, 0, 0177, CKILL, (D_SG_FLAGS | XTABS) 634d522f475Smrg}; 635d522f475Smrgstatic struct tchars d_tc = 636d522f475Smrg{ 637d522f475Smrg CINTR, CQUIT, CSTART, 638d522f475Smrg CSTOP, CEOF, CBRK 639d522f475Smrg}; 640d522f475Smrgstatic struct ltchars d_ltc = 641d522f475Smrg{ 642d522f475Smrg CSUSP, CDSUSP, CRPRNT, 643d522f475Smrg CFLUSH, CWERASE, CLNEXT 644d522f475Smrg}; 645d522f475Smrgstatic int d_disipline = NTTYDISC; 646d522f475Smrgstatic long int d_lmode = LCRTBS | LCRTERA | LCRTKIL | LCTLECH; 647d522f475Smrg#ifdef sony 648d522f475Smrgstatic long int d_jmode = KM_SYSSJIS | KM_ASCII; 649d522f475Smrgstatic struct jtchars d_jtc = 650d522f475Smrg{ 651d522f475Smrg 'J', 'B' 652d522f475Smrg}; 653d522f475Smrg#endif /* sony */ 654d522f475Smrg#endif /* TERMIO_STRUCT */ 655d522f475Smrg#endif /* ! VMS */ 656d522f475Smrg 657d522f475Smrg/* 658d522f475Smrg * SYSV has the termio.c_cc[V] and ltchars; BSD has tchars and ltchars; 659d522f475Smrg * SVR4 has only termio.c_cc, but it includes everything from ltchars. 660d522f475Smrg * POSIX termios has termios.c_cc, which is similar to SVR4. 661d522f475Smrg */ 662d522f475Smrg#define TTYMODE(name) { name, sizeof(name)-1, 0, 0 } 663d522f475Smrgstatic Boolean override_tty_modes = False; 664d522f475Smrg/* *INDENT-OFF* */ 665f2e35a3aSmrgstatic struct { 66620d2c4d2Smrg const char *name; 667d522f475Smrg size_t len; 668d522f475Smrg int set; 669d522f475Smrg int value; 670f2e35a3aSmrg} ttyModes[] = { 671d522f475Smrg TTYMODE("intr"), /* tchars.t_intrc ; VINTR */ 672d522f475Smrg#define XTTYMODE_intr 0 673d522f475Smrg TTYMODE("quit"), /* tchars.t_quitc ; VQUIT */ 674d522f475Smrg#define XTTYMODE_quit 1 675d522f475Smrg TTYMODE("erase"), /* sgttyb.sg_erase ; VERASE */ 676d522f475Smrg#define XTTYMODE_erase 2 677d522f475Smrg TTYMODE("kill"), /* sgttyb.sg_kill ; VKILL */ 678d522f475Smrg#define XTTYMODE_kill 3 679d522f475Smrg TTYMODE("eof"), /* tchars.t_eofc ; VEOF */ 680d522f475Smrg#define XTTYMODE_eof 4 681d522f475Smrg TTYMODE("eol"), /* VEOL */ 682d522f475Smrg#define XTTYMODE_eol 5 683d522f475Smrg TTYMODE("swtch"), /* VSWTCH */ 684d522f475Smrg#define XTTYMODE_swtch 6 685d522f475Smrg TTYMODE("start"), /* tchars.t_startc ; VSTART */ 686d522f475Smrg#define XTTYMODE_start 7 687d522f475Smrg TTYMODE("stop"), /* tchars.t_stopc ; VSTOP */ 688d522f475Smrg#define XTTYMODE_stop 8 689d522f475Smrg TTYMODE("brk"), /* tchars.t_brkc */ 690d522f475Smrg#define XTTYMODE_brk 9 691d522f475Smrg TTYMODE("susp"), /* ltchars.t_suspc ; VSUSP */ 692d522f475Smrg#define XTTYMODE_susp 10 693d522f475Smrg TTYMODE("dsusp"), /* ltchars.t_dsuspc ; VDSUSP */ 694d522f475Smrg#define XTTYMODE_dsusp 11 695d522f475Smrg TTYMODE("rprnt"), /* ltchars.t_rprntc ; VREPRINT */ 696d522f475Smrg#define XTTYMODE_rprnt 12 697d522f475Smrg TTYMODE("flush"), /* ltchars.t_flushc ; VDISCARD */ 698d522f475Smrg#define XTTYMODE_flush 13 699d522f475Smrg TTYMODE("weras"), /* ltchars.t_werasc ; VWERASE */ 700d522f475Smrg#define XTTYMODE_weras 14 701d522f475Smrg TTYMODE("lnext"), /* ltchars.t_lnextc ; VLNEXT */ 702d522f475Smrg#define XTTYMODE_lnext 15 703d522f475Smrg TTYMODE("status"), /* VSTATUS */ 704d522f475Smrg#define XTTYMODE_status 16 705d522f475Smrg TTYMODE("erase2"), /* VERASE2 */ 706d522f475Smrg#define XTTYMODE_erase2 17 707d522f475Smrg TTYMODE("eol2"), /* VEOL2 */ 708d522f475Smrg#define XTTYMODE_eol2 18 709f2e35a3aSmrg TTYMODE("tabs"), /* TAB0 */ 710f2e35a3aSmrg#define XTTYMODE_tabs 19 711f2e35a3aSmrg TTYMODE("-tabs"), /* TAB3 */ 712f2e35a3aSmrg#define XTTYMODE__tabs 20 713d522f475Smrg}; 714d522f475Smrg 715f2e35a3aSmrg#ifndef TAB0 716f2e35a3aSmrg#define TAB0 0 717f2e35a3aSmrg#endif 718f2e35a3aSmrg 719f2e35a3aSmrg#ifndef TAB3 720f2e35a3aSmrg#if defined(OXTABS) 721f2e35a3aSmrg#define TAB3 OXTABS 722f2e35a3aSmrg#elif defined(XTABS) 723f2e35a3aSmrg#define TAB3 XTABS 724f2e35a3aSmrg#endif 725f2e35a3aSmrg#endif 726f2e35a3aSmrg 727f2e35a3aSmrg#ifndef TABDLY 728f2e35a3aSmrg#define TABDLY (TAB0|TAB3) 729f2e35a3aSmrg#endif 730f2e35a3aSmrg 731f2e35a3aSmrg#define isTtyMode(p,q) (ttyChars[p].myMode == q && ttyModes[q].set) 732f2e35a3aSmrg 733f2e35a3aSmrg#define isTabMode(n) \ 734f2e35a3aSmrg (isTtyMode(n, XTTYMODE_tabs) || \ 735f2e35a3aSmrg isTtyMode(n, XTTYMODE__tabs)) 736f2e35a3aSmrg 737f2e35a3aSmrg#define TMODE(ind,var) \ 738f2e35a3aSmrg if (ttyModes[ind].set) \ 739f2e35a3aSmrg var = (cc_t) ttyModes[ind].value 740f2e35a3aSmrg 741d522f475Smrg#define validTtyChar(data, n) \ 742f2e35a3aSmrg (ttyChars[n].sysMode >= 0 && \ 743f2e35a3aSmrg ttyChars[n].sysMode < (int) XtNumber(data.c_cc)) 744d522f475Smrg 745d522f475Smrgstatic const struct { 746d522f475Smrg int sysMode; 747d522f475Smrg int myMode; 748d522f475Smrg int myDefault; 749f2e35a3aSmrg} ttyChars[] = { 750d522f475Smrg#ifdef VINTR 751d522f475Smrg { VINTR, XTTYMODE_intr, CINTR }, 752d522f475Smrg#endif 753d522f475Smrg#ifdef VQUIT 754d522f475Smrg { VQUIT, XTTYMODE_quit, CQUIT }, 755d522f475Smrg#endif 756d522f475Smrg#ifdef VERASE 757d522f475Smrg { VERASE, XTTYMODE_erase, CERASE }, 758d522f475Smrg#endif 759d522f475Smrg#ifdef VKILL 760d522f475Smrg { VKILL, XTTYMODE_kill, CKILL }, 761d522f475Smrg#endif 762d522f475Smrg#ifdef VEOF 763d522f475Smrg { VEOF, XTTYMODE_eof, CEOF }, 764d522f475Smrg#endif 765d522f475Smrg#ifdef VEOL 766d522f475Smrg { VEOL, XTTYMODE_eol, CEOL }, 767d522f475Smrg#endif 768d522f475Smrg#ifdef VSWTCH 769d522f475Smrg { VSWTCH, XTTYMODE_swtch, CNUL }, 770d522f475Smrg#endif 771d522f475Smrg#ifdef VSTART 772d522f475Smrg { VSTART, XTTYMODE_start, CSTART }, 773d522f475Smrg#endif 774d522f475Smrg#ifdef VSTOP 775d522f475Smrg { VSTOP, XTTYMODE_stop, CSTOP }, 776d522f475Smrg#endif 777d522f475Smrg#ifdef VSUSP 778d522f475Smrg { VSUSP, XTTYMODE_susp, CSUSP }, 779d522f475Smrg#endif 780d522f475Smrg#ifdef VDSUSP 781d522f475Smrg { VDSUSP, XTTYMODE_dsusp, CDSUSP }, 782d522f475Smrg#endif 783d522f475Smrg#ifdef VREPRINT 784d522f475Smrg { VREPRINT, XTTYMODE_rprnt, CREPRINT }, 785d522f475Smrg#endif 786d522f475Smrg#ifdef VDISCARD 787d522f475Smrg { VDISCARD, XTTYMODE_flush, CDISCARD }, 788d522f475Smrg#endif 789d522f475Smrg#ifdef VWERASE 790d522f475Smrg { VWERASE, XTTYMODE_weras, CWERASE }, 791d522f475Smrg#endif 792d522f475Smrg#ifdef VLNEXT 793d522f475Smrg { VLNEXT, XTTYMODE_lnext, CLNEXT }, 794d522f475Smrg#endif 795d522f475Smrg#ifdef VSTATUS 796d522f475Smrg { VSTATUS, XTTYMODE_status, CSTATUS }, 797d522f475Smrg#endif 798d522f475Smrg#ifdef VERASE2 799d522f475Smrg { VERASE2, XTTYMODE_erase2, CERASE2 }, 800d522f475Smrg#endif 801d522f475Smrg#ifdef VEOL2 802d522f475Smrg { VEOL2, XTTYMODE_eol2, CNUL }, 803d522f475Smrg#endif 804f2e35a3aSmrg { -1, XTTYMODE_tabs, TAB0 }, 805f2e35a3aSmrg { -1, XTTYMODE__tabs, TAB3 }, 806d522f475Smrg}; 807d522f475Smrg/* *INDENT-ON* */ 808d522f475Smrg 809f2e35a3aSmrgstatic int parse_tty_modes(char *s); 810d522f475Smrg 811d522f475Smrg#ifndef USE_UTEMPTER 812d522f475Smrg#ifdef USE_SYSV_UTMP 813d522f475Smrg#if (defined(AIXV3) && (OSMAJORVERSION < 4)) && !(defined(getutid)) 814d522f475Smrgextern struct utmp *getutid(); 815d522f475Smrg#endif /* AIXV3 */ 816d522f475Smrg 817d522f475Smrg#else /* not USE_SYSV_UTMP */ 818d522f475Smrgstatic char etc_utmp[] = UTMP_FILENAME; 819d522f475Smrg#endif /* USE_SYSV_UTMP */ 820d522f475Smrg 821d522f475Smrg#if defined(USE_LASTLOG) && defined(USE_STRUCT_LASTLOG) 822d522f475Smrgstatic char etc_lastlog[] = LASTLOG_FILENAME; 823d522f475Smrg#else 824d522f475Smrg#undef USE_LASTLOG 825d522f475Smrg#endif 826d522f475Smrg 827d522f475Smrg#ifdef WTMP 828d522f475Smrgstatic char etc_wtmp[] = WTMP_FILENAME; 829d522f475Smrg#endif 830d522f475Smrg#endif /* !USE_UTEMPTER */ 831d522f475Smrg 832d522f475Smrg/* 833d522f475Smrg * Some people with 4.3bsd /bin/login seem to like to use login -p -f user 834d522f475Smrg * to implement xterm -ls. They can turn on USE_LOGIN_DASH_P and turn off 835d522f475Smrg * WTMP and USE_LASTLOG. 836d522f475Smrg */ 837d522f475Smrg#ifdef USE_LOGIN_DASH_P 838d522f475Smrg#ifndef LOGIN_FILENAME 839d522f475Smrg#define LOGIN_FILENAME "/bin/login" 840d522f475Smrg#endif 841d522f475Smrgstatic char bin_login[] = LOGIN_FILENAME; 842d522f475Smrg#endif 843d522f475Smrg 84401037d57Smrgstatic char noPassedPty[2]; 84501037d57Smrgstatic char *passedPty = noPassedPty; /* name if pty if slave */ 846d522f475Smrg 847d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 848d522f475Smrgstatic int Console; 849d522f475Smrg#include <X11/Xmu/SysUtil.h> /* XmuGetHostname */ 850d522f475Smrg#define MIT_CONSOLE_LEN 12 851d522f475Smrg#define MIT_CONSOLE "MIT_CONSOLE_" 852d522f475Smrgstatic char mit_console_name[255 + MIT_CONSOLE_LEN + 1] = MIT_CONSOLE; 853d522f475Smrgstatic Atom mit_console; 854d522f475Smrg#endif /* TIOCCONS */ 855d522f475Smrg 856d522f475Smrg#ifndef USE_SYSV_UTMP 857d522f475Smrgstatic int tslot; 858d522f475Smrg#endif /* USE_SYSV_UTMP */ 859d522f475Smrgstatic sigjmp_buf env; 860d522f475Smrg 861d522f475Smrg#define SetUtmpHost(dst, screen) \ 862d522f475Smrg { \ 863d522f475Smrg char host[sizeof(dst) + 1]; \ 864f2e35a3aSmrg strncpy(host, DisplayString(screen->display), sizeof(host) - 1); \ 865f2e35a3aSmrg host[sizeof(dst)] = '\0'; \ 866d522f475Smrg TRACE(("DisplayString(%s)\n", host)); \ 867d522f475Smrg if (!resource.utmpDisplayId) { \ 868d522f475Smrg char *endptr = strrchr(host, ':'); \ 869d522f475Smrg if (endptr) { \ 870d522f475Smrg TRACE(("trimming display-id '%s'\n", host)); \ 871d522f475Smrg *endptr = '\0'; \ 872d522f475Smrg } \ 873d522f475Smrg } \ 874894e0ac8Smrg copy_filled(dst, host, sizeof(dst)); \ 875d522f475Smrg } 876d522f475Smrg 877d522f475Smrg#ifdef HAVE_UTMP_UT_SYSLEN 878d522f475Smrg# define SetUtmpSysLen(utmp) \ 879d522f475Smrg { \ 880d522f475Smrg utmp.ut_host[sizeof(utmp.ut_host)-1] = '\0'; \ 881f2e35a3aSmrg utmp.ut_syslen = (short) ((int) strlen(utmp.ut_host) + 1); \ 882d522f475Smrg } 883d522f475Smrg#endif 884d522f475Smrg 885d522f475Smrg/* used by VT (charproc.c) */ 886d522f475Smrg 887d522f475Smrgstatic XtResource application_resources[] = 888d522f475Smrg{ 889d522f475Smrg Sres("iconGeometry", "IconGeometry", icon_geometry, NULL), 890d522f475Smrg Sres(XtNtitle, XtCTitle, title, NULL), 8910bd37d32Smrg Sres(XtNiconHint, XtCIconHint, icon_hint, NULL), 892d522f475Smrg Sres(XtNiconName, XtCIconName, icon_name, NULL), 893d522f475Smrg Sres("termName", "TermName", term_name, NULL), 894d522f475Smrg Sres("ttyModes", "TtyModes", tty_modes, NULL), 895f2e35a3aSmrg Sres("validShells", "ValidShells", valid_shells, NULL), 896d522f475Smrg Bres("hold", "Hold", hold_screen, False), 897d522f475Smrg Bres("utmpInhibit", "UtmpInhibit", utmpInhibit, False), 898d522f475Smrg Bres("utmpDisplayId", "UtmpDisplayId", utmpDisplayId, True), 899d522f475Smrg Bres("messages", "Messages", messages, True), 900d522f475Smrg Ires("minBufSize", "MinBufSize", minBufSize, 4096), 901d522f475Smrg Ires("maxBufSize", "MaxBufSize", maxBufSize, 32768), 90220d2c4d2Smrg Sres("menuLocale", "MenuLocale", menuLocale, DEF_MENU_LOCALE), 903a1f3da82Smrg Sres("omitTranslation", "OmitTranslation", omitTranslation, NULL), 904d522f475Smrg Sres("keyboardType", "KeyboardType", keyboardType, "unknown"), 905ad37e533Smrg#ifdef HAVE_LIB_XCURSOR 906ad37e533Smrg Sres("cursorTheme", "CursorTheme", cursorTheme, "none"), 907ad37e533Smrg#endif 908e39b573cSmrg#if OPT_PRINT_ON_EXIT 909e39b573cSmrg Ires("printModeImmediate", "PrintModeImmediate", printModeNow, 0), 910e39b573cSmrg Ires("printOptsImmediate", "PrintOptsImmediate", printOptsNow, 9), 911e39b573cSmrg Sres("printFileImmediate", "PrintFileImmediate", printFileNow, NULL), 912e39b573cSmrg Ires("printModeOnXError", "PrintModeOnXError", printModeOnXError, 0), 913e39b573cSmrg Ires("printOptsOnXError", "PrintOptsOnXError", printOptsOnXError, 9), 914e39b573cSmrg Sres("printFileOnXError", "PrintFileOnXError", printFileOnXError, NULL), 915e39b573cSmrg#endif 916d522f475Smrg#if OPT_SUNPC_KBD 917d522f475Smrg Bres("sunKeyboard", "SunKeyboard", sunKeyboard, False), 918d522f475Smrg#endif 919d522f475Smrg#if OPT_HP_FUNC_KEYS 920d522f475Smrg Bres("hpFunctionKeys", "HpFunctionKeys", hpFunctionKeys, False), 921d522f475Smrg#endif 922d522f475Smrg#if OPT_SCO_FUNC_KEYS 923d522f475Smrg Bres("scoFunctionKeys", "ScoFunctionKeys", scoFunctionKeys, False), 924d522f475Smrg#endif 925d522f475Smrg#if OPT_SUN_FUNC_KEYS 926d522f475Smrg Bres("sunFunctionKeys", "SunFunctionKeys", sunFunctionKeys, False), 927d522f475Smrg#endif 928d522f475Smrg#if OPT_TCAP_FKEYS 929d522f475Smrg Bres("tcapFunctionKeys", "TcapFunctionKeys", termcapKeys, False), 930d522f475Smrg#endif 931d522f475Smrg#if OPT_INITIAL_ERASE 932d522f475Smrg Bres("ptyInitialErase", "PtyInitialErase", ptyInitialErase, DEF_INITIAL_ERASE), 933d522f475Smrg Bres("backarrowKeyIsErase", "BackarrowKeyIsErase", backarrow_is_erase, DEF_BACKARO_ERASE), 934d522f475Smrg#endif 935d522f475Smrg Bres("useInsertMode", "UseInsertMode", useInsertMode, False), 936d522f475Smrg#if OPT_ZICONBEEP 937d522f475Smrg Ires("zIconBeep", "ZIconBeep", zIconBeep, 0), 9380bd37d32Smrg Sres("zIconTitleFormat", "ZIconTitleFormat", zIconFormat, "*** %s"), 939d522f475Smrg#endif 940d522f475Smrg#if OPT_PTY_HANDSHAKE 941d522f475Smrg Bres("waitForMap", "WaitForMap", wait_for_map, False), 942d522f475Smrg Bres("ptyHandshake", "PtyHandshake", ptyHandshake, True), 943d522f475Smrg Bres("ptySttySize", "PtySttySize", ptySttySize, DEF_PTY_STTY_SIZE), 944d522f475Smrg#endif 945913cc679Smrg#if OPT_REPORT_CCLASS 946913cc679Smrg Bres("reportCClass", "ReportCClass", reportCClass, False), 947913cc679Smrg#endif 948e0a2b6dfSmrg#if OPT_REPORT_COLORS 949e0a2b6dfSmrg Bres("reportColors", "ReportColors", reportColors, False), 950e0a2b6dfSmrg#endif 951e0a2b6dfSmrg#if OPT_REPORT_FONTS 952e0a2b6dfSmrg Bres("reportFonts", "ReportFonts", reportFonts, False), 953e0a2b6dfSmrg#endif 954f2e35a3aSmrg#if OPT_REPORT_ICONS 955f2e35a3aSmrg Bres("reportIcons", "ReportIcons", reportIcons, False), 956f2e35a3aSmrg#endif 957f2e35a3aSmrg#if OPT_XRES_QUERY 958f2e35a3aSmrg Bres("reportXRes", "ReportXRes", reportXRes, False), 959f2e35a3aSmrg#endif 960d522f475Smrg#if OPT_SAME_NAME 961d522f475Smrg Bres("sameName", "SameName", sameName, True), 962d522f475Smrg#endif 963d522f475Smrg#if OPT_SESSION_MGT 964d522f475Smrg Bres("sessionMgt", "SessionMgt", sessionMgt, True), 965d522f475Smrg#endif 966d522f475Smrg#if OPT_TOOLBAR 967d522f475Smrg Bres(XtNtoolBar, XtCToolBar, toolBar, True), 968d522f475Smrg#endif 969956cc18dSsnj#if OPT_MAXIMIZE 970956cc18dSsnj Bres(XtNmaximized, XtCMaximized, maximized, False), 971a1f3da82Smrg Sres(XtNfullscreen, XtCFullscreen, fullscreen_s, "off"), 972956cc18dSsnj#endif 973f2e35a3aSmrg#if USE_DOUBLE_BUFFER 974f2e35a3aSmrg Bres(XtNbuffered, XtCBuffered, buffered, DEF_DOUBLE_BUFFER), 975f2e35a3aSmrg Ires(XtNbufferedFPS, XtCBufferedFPS, buffered_fps, 40), 976f2e35a3aSmrg#endif 977d522f475Smrg}; 978d522f475Smrg 97920d2c4d2Smrgstatic String fallback_resources[] = 980d522f475Smrg{ 981e39b573cSmrg#if OPT_TOOLBAR 982e39b573cSmrg "*toolBar: false", 983e39b573cSmrg#endif 984d522f475Smrg "*SimpleMenu*menuLabel.vertSpace: 100", 985d522f475Smrg "*SimpleMenu*HorizontalMargins: 16", 986d522f475Smrg "*SimpleMenu*Sme.height: 16", 987d522f475Smrg "*SimpleMenu*Cursor: left_ptr", 988d522f475Smrg "*mainMenu.Label: Main Options (no app-defaults)", 989d522f475Smrg "*vtMenu.Label: VT Options (no app-defaults)", 990d522f475Smrg "*fontMenu.Label: VT Fonts (no app-defaults)", 991d522f475Smrg#if OPT_TEK4014 992d522f475Smrg "*tekMenu.Label: Tek Options (no app-defaults)", 993d522f475Smrg#endif 994d522f475Smrg NULL 995d522f475Smrg}; 996d522f475Smrg 997d522f475Smrg/* Command line options table. Only resources are entered here...there is a 998d522f475Smrg pass over the remaining options after XrmParseCommand is let loose. */ 999d522f475Smrg/* *INDENT-OFF* */ 1000f2e35a3aSmrg#define DATA(option,pattern,type,value) { (char *) option, (char *) pattern, type, (XPointer) value } 1001d522f475Smrgstatic XrmOptionDescRec optionDescList[] = { 1002f2e35a3aSmrgDATA("-geometry", "*vt100.geometry",XrmoptionSepArg, NULL), 1003f2e35a3aSmrgDATA("-132", "*c132", XrmoptionNoArg, "on"), 1004f2e35a3aSmrgDATA("+132", "*c132", XrmoptionNoArg, "off"), 1005f2e35a3aSmrgDATA("-ah", "*alwaysHighlight", XrmoptionNoArg, "on"), 1006f2e35a3aSmrgDATA("+ah", "*alwaysHighlight", XrmoptionNoArg, "off"), 1007f2e35a3aSmrgDATA("-aw", "*autoWrap", XrmoptionNoArg, "on"), 1008f2e35a3aSmrgDATA("+aw", "*autoWrap", XrmoptionNoArg, "off"), 1009d522f475Smrg#ifndef NO_ACTIVE_ICON 1010f2e35a3aSmrgDATA("-ai", "*activeIcon", XrmoptionNoArg, "off"), 1011f2e35a3aSmrgDATA("+ai", "*activeIcon", XrmoptionNoArg, "on"), 1012d522f475Smrg#endif /* NO_ACTIVE_ICON */ 1013f2e35a3aSmrgDATA("-b", "*internalBorder",XrmoptionSepArg, NULL), 1014f2e35a3aSmrgDATA("-bc", "*cursorBlink", XrmoptionNoArg, "on"), 1015f2e35a3aSmrgDATA("+bc", "*cursorBlink", XrmoptionNoArg, "off"), 1016f2e35a3aSmrgDATA("-bcf", "*cursorOffTime",XrmoptionSepArg, NULL), 1017f2e35a3aSmrgDATA("-bcn", "*cursorOnTime",XrmoptionSepArg, NULL), 1018f2e35a3aSmrgDATA("-bdc", "*colorBDMode", XrmoptionNoArg, "off"), 1019f2e35a3aSmrgDATA("+bdc", "*colorBDMode", XrmoptionNoArg, "on"), 1020f2e35a3aSmrgDATA("-cb", "*cutToBeginningOfLine", XrmoptionNoArg, "off"), 1021f2e35a3aSmrgDATA("+cb", "*cutToBeginningOfLine", XrmoptionNoArg, "on"), 1022f2e35a3aSmrgDATA("-cc", "*charClass", XrmoptionSepArg, NULL), 1023f2e35a3aSmrgDATA("-cm", "*colorMode", XrmoptionNoArg, "off"), 1024f2e35a3aSmrgDATA("+cm", "*colorMode", XrmoptionNoArg, "on"), 1025f2e35a3aSmrgDATA("-cn", "*cutNewline", XrmoptionNoArg, "off"), 1026f2e35a3aSmrgDATA("+cn", "*cutNewline", XrmoptionNoArg, "on"), 1027f2e35a3aSmrgDATA("-cr", "*cursorColor", XrmoptionSepArg, NULL), 1028f2e35a3aSmrgDATA("-cu", "*curses", XrmoptionNoArg, "on"), 1029f2e35a3aSmrgDATA("+cu", "*curses", XrmoptionNoArg, "off"), 1030f2e35a3aSmrgDATA("-dc", "*dynamicColors",XrmoptionNoArg, "off"), 1031f2e35a3aSmrgDATA("+dc", "*dynamicColors",XrmoptionNoArg, "on"), 1032f2e35a3aSmrgDATA("-fb", "*boldFont", XrmoptionSepArg, NULL), 1033f2e35a3aSmrgDATA("-fbb", "*freeBoldBox", XrmoptionNoArg, "off"), 1034f2e35a3aSmrgDATA("+fbb", "*freeBoldBox", XrmoptionNoArg, "on"), 1035f2e35a3aSmrgDATA("-fbx", "*forceBoxChars", XrmoptionNoArg, "off"), 1036f2e35a3aSmrgDATA("+fbx", "*forceBoxChars", XrmoptionNoArg, "on"), 1037f2e35a3aSmrgDATA("-fc", "*initialFont", XrmoptionSepArg, NULL), 1038d522f475Smrg#ifndef NO_ACTIVE_ICON 1039f2e35a3aSmrgDATA("-fi", "*iconFont", XrmoptionSepArg, NULL), 1040d522f475Smrg#endif /* NO_ACTIVE_ICON */ 1041d522f475Smrg#if OPT_RENDERFONT 1042f2e35a3aSmrgDATA("-fa", "*faceName", XrmoptionSepArg, NULL), 1043f2e35a3aSmrgDATA("-fd", "*faceNameDoublesize", XrmoptionSepArg, NULL), 1044f2e35a3aSmrgDATA("-fs", "*faceSize", XrmoptionSepArg, NULL), 1045d522f475Smrg#endif 104601037d57Smrg#if OPT_WIDE_ATTRS && OPT_ISO_COLORS 1047f2e35a3aSmrgDATA("-itc", "*colorITMode", XrmoptionNoArg, "off"), 1048f2e35a3aSmrgDATA("+itc", "*colorITMode", XrmoptionNoArg, "on"), 104901037d57Smrg#endif 1050d522f475Smrg#if OPT_WIDE_CHARS 1051f2e35a3aSmrgDATA("-fw", "*wideFont", XrmoptionSepArg, NULL), 1052f2e35a3aSmrgDATA("-fwb", "*wideBoldFont", XrmoptionSepArg, NULL), 1053d522f475Smrg#endif 1054d522f475Smrg#if OPT_INPUT_METHOD 1055f2e35a3aSmrgDATA("-fx", "*ximFont", XrmoptionSepArg, NULL), 1056d522f475Smrg#endif 1057d522f475Smrg#if OPT_HIGHLIGHT_COLOR 1058f2e35a3aSmrgDATA("-hc", "*highlightColor", XrmoptionSepArg, NULL), 1059f2e35a3aSmrgDATA("-hm", "*highlightColorMode", XrmoptionNoArg, "on"), 1060f2e35a3aSmrgDATA("+hm", "*highlightColorMode", XrmoptionNoArg, "off"), 1061f2e35a3aSmrgDATA("-selfg", "*highlightTextColor", XrmoptionSepArg, NULL), 1062f2e35a3aSmrgDATA("-selbg", "*highlightColor", XrmoptionSepArg, NULL), 1063d522f475Smrg#endif 1064d522f475Smrg#if OPT_HP_FUNC_KEYS 1065f2e35a3aSmrgDATA("-hf", "*hpFunctionKeys",XrmoptionNoArg, "on"), 1066f2e35a3aSmrgDATA("+hf", "*hpFunctionKeys",XrmoptionNoArg, "off"), 1067d522f475Smrg#endif 1068f2e35a3aSmrgDATA("-hold", "*hold", XrmoptionNoArg, "on"), 1069f2e35a3aSmrgDATA("+hold", "*hold", XrmoptionNoArg, "off"), 1070d522f475Smrg#if OPT_INITIAL_ERASE 1071f2e35a3aSmrgDATA("-ie", "*ptyInitialErase", XrmoptionNoArg, "on"), 1072f2e35a3aSmrgDATA("+ie", "*ptyInitialErase", XrmoptionNoArg, "off"), 1073d522f475Smrg#endif 1074f2e35a3aSmrgDATA("-j", "*jumpScroll", XrmoptionNoArg, "on"), 1075f2e35a3aSmrgDATA("+j", "*jumpScroll", XrmoptionNoArg, "off"), 1076d522f475Smrg#if OPT_C1_PRINT 1077f2e35a3aSmrgDATA("-k8", "*allowC1Printable", XrmoptionNoArg, "on"), 1078f2e35a3aSmrgDATA("+k8", "*allowC1Printable", XrmoptionNoArg, "off"), 1079d522f475Smrg#endif 1080f2e35a3aSmrgDATA("-kt", "*keyboardType", XrmoptionSepArg, NULL), 1081d522f475Smrg/* parse logging options anyway for compatibility */ 1082f2e35a3aSmrgDATA("-l", "*logging", XrmoptionNoArg, "on"), 1083f2e35a3aSmrgDATA("+l", "*logging", XrmoptionNoArg, "off"), 1084f2e35a3aSmrgDATA("-lf", "*logFile", XrmoptionSepArg, NULL), 1085f2e35a3aSmrgDATA("-ls", "*loginShell", XrmoptionNoArg, "on"), 1086f2e35a3aSmrgDATA("+ls", "*loginShell", XrmoptionNoArg, "off"), 1087f2e35a3aSmrgDATA("-mb", "*marginBell", XrmoptionNoArg, "on"), 1088f2e35a3aSmrgDATA("+mb", "*marginBell", XrmoptionNoArg, "off"), 1089f2e35a3aSmrgDATA("-mc", "*multiClickTime", XrmoptionSepArg, NULL), 1090f2e35a3aSmrgDATA("-mesg", "*messages", XrmoptionNoArg, "off"), 1091f2e35a3aSmrgDATA("+mesg", "*messages", XrmoptionNoArg, "on"), 1092f2e35a3aSmrgDATA("-ms", "*pointerColor",XrmoptionSepArg, NULL), 1093f2e35a3aSmrgDATA("-nb", "*nMarginBell", XrmoptionSepArg, NULL), 1094f2e35a3aSmrgDATA("-nul", "*underLine", XrmoptionNoArg, "off"), 1095f2e35a3aSmrgDATA("+nul", "*underLine", XrmoptionNoArg, "on"), 1096f2e35a3aSmrgDATA("-pc", "*boldColors", XrmoptionNoArg, "on"), 1097f2e35a3aSmrgDATA("+pc", "*boldColors", XrmoptionNoArg, "off"), 1098f2e35a3aSmrgDATA("-pf", "*pointerFont", XrmoptionSepArg, NULL), 1099f2e35a3aSmrgDATA("-rw", "*reverseWrap", XrmoptionNoArg, "on"), 1100f2e35a3aSmrgDATA("+rw", "*reverseWrap", XrmoptionNoArg, "off"), 1101f2e35a3aSmrgDATA("-s", "*multiScroll", XrmoptionNoArg, "on"), 1102f2e35a3aSmrgDATA("+s", "*multiScroll", XrmoptionNoArg, "off"), 1103f2e35a3aSmrgDATA("-sb", "*scrollBar", XrmoptionNoArg, "on"), 1104f2e35a3aSmrgDATA("+sb", "*scrollBar", XrmoptionNoArg, "off"), 1105913cc679Smrg#if OPT_REPORT_CCLASS 1106f2e35a3aSmrgDATA("-report-charclass","*reportCClass", XrmoptionNoArg, "on"), 1107913cc679Smrg#endif 1108e0a2b6dfSmrg#if OPT_REPORT_COLORS 1109f2e35a3aSmrgDATA("-report-colors", "*reportColors", XrmoptionNoArg, "on"), 1110f2e35a3aSmrg#endif 1111f2e35a3aSmrg#if OPT_REPORT_ICONS 1112f2e35a3aSmrgDATA("-report-icons", "*reportIcons", XrmoptionNoArg, "on"), 1113e0a2b6dfSmrg#endif 1114e0a2b6dfSmrg#if OPT_REPORT_FONTS 1115f2e35a3aSmrgDATA("-report-fonts", "*reportFonts", XrmoptionNoArg, "on"), 1116f2e35a3aSmrg#endif 1117f2e35a3aSmrg#if OPT_XRES_QUERY 1118f2e35a3aSmrgDATA("-report-xres", "*reportXRes", XrmoptionNoArg, "on"), 1119e0a2b6dfSmrg#endif 1120d522f475Smrg#ifdef SCROLLBAR_RIGHT 1121f2e35a3aSmrgDATA("-leftbar", "*rightScrollBar", XrmoptionNoArg, "off"), 1122f2e35a3aSmrgDATA("-rightbar", "*rightScrollBar", XrmoptionNoArg, "on"), 1123f2e35a3aSmrg#endif 1124f2e35a3aSmrgDATA("-rvc", "*colorRVMode", XrmoptionNoArg, "off"), 1125f2e35a3aSmrgDATA("+rvc", "*colorRVMode", XrmoptionNoArg, "on"), 1126f2e35a3aSmrgDATA("-sf", "*sunFunctionKeys", XrmoptionNoArg, "on"), 1127f2e35a3aSmrgDATA("+sf", "*sunFunctionKeys", XrmoptionNoArg, "off"), 1128f2e35a3aSmrgDATA("-sh", "*scaleHeight", XrmoptionSepArg, NULL), 1129f2e35a3aSmrgDATA("-si", "*scrollTtyOutput", XrmoptionNoArg, "off"), 1130f2e35a3aSmrgDATA("+si", "*scrollTtyOutput", XrmoptionNoArg, "on"), 1131f2e35a3aSmrgDATA("-sk", "*scrollKey", XrmoptionNoArg, "on"), 1132f2e35a3aSmrgDATA("+sk", "*scrollKey", XrmoptionNoArg, "off"), 1133f2e35a3aSmrgDATA("-sl", "*saveLines", XrmoptionSepArg, NULL), 1134d522f475Smrg#if OPT_SUNPC_KBD 1135f2e35a3aSmrgDATA("-sp", "*sunKeyboard", XrmoptionNoArg, "on"), 1136f2e35a3aSmrgDATA("+sp", "*sunKeyboard", XrmoptionNoArg, "off"), 1137d522f475Smrg#endif 1138d522f475Smrg#if OPT_TEK4014 1139f2e35a3aSmrgDATA("-t", "*tekStartup", XrmoptionNoArg, "on"), 1140f2e35a3aSmrgDATA("+t", "*tekStartup", XrmoptionNoArg, "off"), 1141d522f475Smrg#endif 1142f2e35a3aSmrgDATA("-ti", "*decTerminalID",XrmoptionSepArg, NULL), 1143f2e35a3aSmrgDATA("-tm", "*ttyModes", XrmoptionSepArg, NULL), 1144f2e35a3aSmrgDATA("-tn", "*termName", XrmoptionSepArg, NULL), 1145d522f475Smrg#if OPT_WIDE_CHARS 1146f2e35a3aSmrgDATA("-u8", "*utf8", XrmoptionNoArg, "2"), 1147f2e35a3aSmrgDATA("+u8", "*utf8", XrmoptionNoArg, "0"), 1148d522f475Smrg#endif 1149d522f475Smrg#if OPT_LUIT_PROG 1150f2e35a3aSmrgDATA("-lc", "*locale", XrmoptionNoArg, "on"), 1151f2e35a3aSmrgDATA("+lc", "*locale", XrmoptionNoArg, "off"), 1152f2e35a3aSmrgDATA("-lcc", "*localeFilter",XrmoptionSepArg, NULL), 1153f2e35a3aSmrgDATA("-en", "*locale", XrmoptionSepArg, NULL), 1154f2e35a3aSmrg#endif 1155f2e35a3aSmrgDATA("-uc", "*cursorUnderLine", XrmoptionNoArg, "on"), 1156f2e35a3aSmrgDATA("+uc", "*cursorUnderLine", XrmoptionNoArg, "off"), 1157f2e35a3aSmrgDATA("-ulc", "*colorULMode", XrmoptionNoArg, "off"), 1158f2e35a3aSmrgDATA("+ulc", "*colorULMode", XrmoptionNoArg, "on"), 1159f2e35a3aSmrgDATA("-ulit", "*italicULMode", XrmoptionNoArg, "off"), 1160f2e35a3aSmrgDATA("+ulit", "*italicULMode", XrmoptionNoArg, "on"), 1161f2e35a3aSmrgDATA("-ut", "*utmpInhibit", XrmoptionNoArg, "on"), 1162f2e35a3aSmrgDATA("+ut", "*utmpInhibit", XrmoptionNoArg, "off"), 1163f2e35a3aSmrgDATA("-im", "*useInsertMode", XrmoptionNoArg, "on"), 1164f2e35a3aSmrgDATA("+im", "*useInsertMode", XrmoptionNoArg, "off"), 1165f2e35a3aSmrgDATA("-vb", "*visualBell", XrmoptionNoArg, "on"), 1166f2e35a3aSmrgDATA("+vb", "*visualBell", XrmoptionNoArg, "off"), 1167f2e35a3aSmrgDATA("-pob", "*popOnBell", XrmoptionNoArg, "on"), 1168f2e35a3aSmrgDATA("+pob", "*popOnBell", XrmoptionNoArg, "off"), 1169d522f475Smrg#if OPT_WIDE_CHARS 1170f2e35a3aSmrgDATA("-wc", "*wideChars", XrmoptionNoArg, "on"), 1171f2e35a3aSmrgDATA("+wc", "*wideChars", XrmoptionNoArg, "off"), 1172f2e35a3aSmrgDATA("-mk_width", "*mkWidth", XrmoptionNoArg, "on"), 1173f2e35a3aSmrgDATA("+mk_width", "*mkWidth", XrmoptionNoArg, "off"), 1174f2e35a3aSmrgDATA("-cjk_width", "*cjkWidth", XrmoptionNoArg, "on"), 1175f2e35a3aSmrgDATA("+cjk_width", "*cjkWidth", XrmoptionNoArg, "off"), 1176f2e35a3aSmrg#endif 1177f2e35a3aSmrgDATA("-wf", "*waitForMap", XrmoptionNoArg, "on"), 1178f2e35a3aSmrgDATA("+wf", "*waitForMap", XrmoptionNoArg, "off"), 1179d522f475Smrg#if OPT_ZICONBEEP 1180f2e35a3aSmrgDATA("-ziconbeep", "*zIconBeep", XrmoptionSepArg, NULL), 1181d522f475Smrg#endif 1182d522f475Smrg#if OPT_SAME_NAME 1183f2e35a3aSmrgDATA("-samename", "*sameName", XrmoptionNoArg, "on"), 1184f2e35a3aSmrgDATA("+samename", "*sameName", XrmoptionNoArg, "off"), 1185d522f475Smrg#endif 1186d522f475Smrg#if OPT_SESSION_MGT 1187f2e35a3aSmrgDATA("-sm", "*sessionMgt", XrmoptionNoArg, "on"), 1188f2e35a3aSmrgDATA("+sm", "*sessionMgt", XrmoptionNoArg, "off"), 1189d522f475Smrg#endif 1190d522f475Smrg#if OPT_TOOLBAR 1191f2e35a3aSmrgDATA("-tb", "*"XtNtoolBar, XrmoptionNoArg, "on"), 1192f2e35a3aSmrgDATA("+tb", "*"XtNtoolBar, XrmoptionNoArg, "off"), 1193d522f475Smrg#endif 1194956cc18dSsnj#if OPT_MAXIMIZE 1195f2e35a3aSmrgDATA("-maximized", "*maximized", XrmoptionNoArg, "on"), 1196f2e35a3aSmrgDATA("+maximized", "*maximized", XrmoptionNoArg, "off"), 1197f2e35a3aSmrgDATA("-fullscreen", "*fullscreen", XrmoptionNoArg, "on"), 1198f2e35a3aSmrgDATA("+fullscreen", "*fullscreen", XrmoptionNoArg, "off"), 1199956cc18dSsnj#endif 1200d522f475Smrg/* options that we process ourselves */ 1201f2e35a3aSmrgDATA("-help", NULL, XrmoptionSkipNArgs, NULL), 1202f2e35a3aSmrgDATA("-version", NULL, XrmoptionSkipNArgs, NULL), 1203f2e35a3aSmrgDATA("-baudrate", NULL, XrmoptionSkipArg, NULL), 1204f2e35a3aSmrgDATA("-class", NULL, XrmoptionSkipArg, NULL), 1205f2e35a3aSmrgDATA("-e", NULL, XrmoptionSkipLine, NULL), 1206f2e35a3aSmrgDATA("-into", NULL, XrmoptionSkipArg, NULL), 1207d522f475Smrg/* bogus old compatibility stuff for which there are 1208d522f475Smrg standard XtOpenApplication options now */ 1209f2e35a3aSmrgDATA("%", "*tekGeometry", XrmoptionStickyArg, NULL), 1210f2e35a3aSmrgDATA("#", ".iconGeometry",XrmoptionStickyArg, NULL), 1211f2e35a3aSmrgDATA("-T", ".title", XrmoptionSepArg, NULL), 1212f2e35a3aSmrgDATA("-n", "*iconName", XrmoptionSepArg, NULL), 1213f2e35a3aSmrgDATA("-r", "*reverseVideo",XrmoptionNoArg, "on"), 1214f2e35a3aSmrgDATA("+r", "*reverseVideo",XrmoptionNoArg, "off"), 1215f2e35a3aSmrgDATA("-rv", "*reverseVideo",XrmoptionNoArg, "on"), 1216f2e35a3aSmrgDATA("+rv", "*reverseVideo",XrmoptionNoArg, "off"), 1217f2e35a3aSmrgDATA("-w", ".borderWidth", XrmoptionSepArg, NULL), 1218f2e35a3aSmrg#undef DATA 1219d522f475Smrg}; 1220d522f475Smrg 1221d522f475Smrgstatic OptionHelp xtermOptions[] = { 1222d522f475Smrg{ "-version", "print the version number" }, 1223d522f475Smrg{ "-help", "print out this message" }, 1224d522f475Smrg{ "-display displayname", "X server to contact" }, 1225d522f475Smrg{ "-geometry geom", "size (in characters) and position" }, 1226d522f475Smrg{ "-/+rv", "turn on/off reverse video" }, 1227d522f475Smrg{ "-bg color", "background color" }, 1228d522f475Smrg{ "-fg color", "foreground color" }, 1229d522f475Smrg{ "-bd color", "border color" }, 1230d522f475Smrg{ "-bw number", "border width in pixels" }, 1231d522f475Smrg{ "-fn fontname", "normal text font" }, 1232d522f475Smrg{ "-fb fontname", "bold text font" }, 1233f2e35a3aSmrg{ "-fc fontmenu", "start with named fontmenu choice" }, 1234d522f475Smrg{ "-/+fbb", "turn on/off normal/bold font comparison inhibit"}, 1235d522f475Smrg{ "-/+fbx", "turn off/on linedrawing characters"}, 1236d522f475Smrg#if OPT_RENDERFONT 1237d522f475Smrg{ "-fa pattern", "FreeType font-selection pattern" }, 1238d522f475Smrg{ "-fd pattern", "FreeType Doublesize font-selection pattern" }, 1239d522f475Smrg{ "-fs size", "FreeType font-size" }, 1240d522f475Smrg#endif 1241d522f475Smrg#if OPT_WIDE_CHARS 1242d522f475Smrg{ "-fw fontname", "doublewidth text font" }, 1243d522f475Smrg{ "-fwb fontname", "doublewidth bold text font" }, 1244d522f475Smrg#endif 1245d522f475Smrg#if OPT_INPUT_METHOD 1246d522f475Smrg{ "-fx fontname", "XIM fontset" }, 1247d522f475Smrg#endif 1248d522f475Smrg{ "-iconic", "start iconic" }, 1249d522f475Smrg{ "-name string", "client instance, icon, and title strings" }, 12502e4f8982Smrg{ "-baudrate rate", "set line-speed (default 38400)" }, 1251d522f475Smrg{ "-class string", "class string (XTerm)" }, 1252d522f475Smrg{ "-title string", "title string" }, 1253d522f475Smrg{ "-xrm resourcestring", "additional resource specifications" }, 1254d522f475Smrg{ "-/+132", "turn on/off 80/132 column switching" }, 1255d522f475Smrg{ "-/+ah", "turn on/off always highlight" }, 1256d522f475Smrg#ifndef NO_ACTIVE_ICON 1257d522f475Smrg{ "-/+ai", "turn off/on active icon" }, 1258d522f475Smrg{ "-fi fontname", "icon font for active icon" }, 1259d522f475Smrg#endif /* NO_ACTIVE_ICON */ 1260d522f475Smrg{ "-b number", "internal border in pixels" }, 1261d522f475Smrg{ "-/+bc", "turn on/off text cursor blinking" }, 1262d522f475Smrg{ "-bcf milliseconds", "time text cursor is off when blinking"}, 1263d522f475Smrg{ "-bcn milliseconds", "time text cursor is on when blinking"}, 1264d522f475Smrg{ "-/+bdc", "turn off/on display of bold as color"}, 1265d522f475Smrg{ "-/+cb", "turn on/off cut-to-beginning-of-line inhibit" }, 1266d522f475Smrg{ "-cc classrange", "specify additional character classes" }, 1267d522f475Smrg{ "-/+cm", "turn off/on ANSI color mode" }, 1268d522f475Smrg{ "-/+cn", "turn on/off cut newline inhibit" }, 1269f2e35a3aSmrg{ "-pf fontname", "cursor font for text area pointer" }, 1270d522f475Smrg{ "-cr color", "text cursor color" }, 1271d522f475Smrg{ "-/+cu", "turn on/off curses emulation" }, 1272d522f475Smrg{ "-/+dc", "turn off/on dynamic color selection" }, 1273d522f475Smrg#if OPT_HIGHLIGHT_COLOR 1274d522f475Smrg{ "-/+hm", "turn on/off selection-color override" }, 1275d522f475Smrg{ "-selbg color", "selection background color" }, 1276d522f475Smrg{ "-selfg color", "selection foreground color" }, 12770bd37d32Smrg/* -hc is deprecated, not shown in help message */ 1278d522f475Smrg#endif 1279d522f475Smrg#if OPT_HP_FUNC_KEYS 1280d522f475Smrg{ "-/+hf", "turn on/off HP Function Key escape codes" }, 1281d522f475Smrg#endif 1282d522f475Smrg{ "-/+hold", "turn on/off logic that retains window after exit" }, 1283d522f475Smrg#if OPT_INITIAL_ERASE 1284d522f475Smrg{ "-/+ie", "turn on/off initialization of 'erase' from pty" }, 1285d522f475Smrg#endif 1286d522f475Smrg{ "-/+im", "use insert mode for TERMCAP" }, 1287d522f475Smrg{ "-/+j", "turn on/off jump scroll" }, 1288d522f475Smrg#if OPT_C1_PRINT 1289d522f475Smrg{ "-/+k8", "turn on/off C1-printable classification"}, 1290d522f475Smrg#endif 1291d522f475Smrg{ "-kt keyboardtype", "set keyboard type:" KEYBOARD_TYPES }, 1292d522f475Smrg#ifdef ALLOWLOGGING 1293d522f475Smrg{ "-/+l", "turn on/off logging" }, 1294f2e35a3aSmrg{ "-lf filename", "logging filename (use '-' for standard out)" }, 1295d522f475Smrg#else 1296d522f475Smrg{ "-/+l", "turn on/off logging (not supported)" }, 1297d522f475Smrg{ "-lf filename", "logging filename (not supported)" }, 1298d522f475Smrg#endif 1299d522f475Smrg{ "-/+ls", "turn on/off login shell" }, 1300d522f475Smrg{ "-/+mb", "turn on/off margin bell" }, 1301d522f475Smrg{ "-mc milliseconds", "multiclick time in milliseconds" }, 1302d522f475Smrg{ "-/+mesg", "forbid/allow messages" }, 1303d522f475Smrg{ "-ms color", "pointer color" }, 1304d522f475Smrg{ "-nb number", "margin bell in characters from right end" }, 1305d522f475Smrg{ "-/+nul", "turn off/on display of underlining" }, 1306d522f475Smrg{ "-/+aw", "turn on/off auto wraparound" }, 1307d522f475Smrg{ "-/+pc", "turn on/off PC-style bold colors" }, 1308d522f475Smrg{ "-/+rw", "turn on/off reverse wraparound" }, 1309d522f475Smrg{ "-/+s", "turn on/off multiscroll" }, 1310d522f475Smrg{ "-/+sb", "turn on/off scrollbar" }, 1311913cc679Smrg#if OPT_REPORT_CCLASS 1312913cc679Smrg{"-report-charclass", "report \"charClass\" after initialization"}, 1313913cc679Smrg#endif 1314e0a2b6dfSmrg#if OPT_REPORT_COLORS 1315e0a2b6dfSmrg{ "-report-colors", "report colors as they are allocated" }, 1316e0a2b6dfSmrg#endif 1317e0a2b6dfSmrg#if OPT_REPORT_FONTS 1318e0a2b6dfSmrg{ "-report-fonts", "report fonts as loaded to stdout" }, 1319e0a2b6dfSmrg#endif 1320f2e35a3aSmrg#if OPT_REPORT_ICONS 1321f2e35a3aSmrg{ "-report-icons", "report title/icon updates" }, 1322f2e35a3aSmrg#endif 1323f2e35a3aSmrg#if OPT_XRES_QUERY 1324f2e35a3aSmrg{ "-report-xres", "report X resources for VT100 widget" }, 1325f2e35a3aSmrg#endif 1326d522f475Smrg#ifdef SCROLLBAR_RIGHT 1327d522f475Smrg{ "-rightbar", "force scrollbar right (default left)" }, 1328d522f475Smrg{ "-leftbar", "force scrollbar left" }, 1329d522f475Smrg#endif 1330d522f475Smrg{ "-/+rvc", "turn off/on display of reverse as color" }, 1331d522f475Smrg{ "-/+sf", "turn on/off Sun Function Key escape codes" }, 1332894e0ac8Smrg{ "-sh number", "scale line-height values by the given number" }, 1333d522f475Smrg{ "-/+si", "turn on/off scroll-on-tty-output inhibit" }, 1334d522f475Smrg{ "-/+sk", "turn on/off scroll-on-keypress" }, 1335d522f475Smrg{ "-sl number", "number of scrolled lines to save" }, 1336d522f475Smrg#if OPT_SUNPC_KBD 1337d522f475Smrg{ "-/+sp", "turn on/off Sun/PC Function/Keypad mapping" }, 1338d522f475Smrg#endif 1339d522f475Smrg#if OPT_TEK4014 1340d522f475Smrg{ "-/+t", "turn on/off Tek emulation window" }, 1341d522f475Smrg#endif 1342d522f475Smrg#if OPT_TOOLBAR 1343d522f475Smrg{ "-/+tb", "turn on/off toolbar" }, 1344d522f475Smrg#endif 1345d522f475Smrg{ "-ti termid", "terminal identifier" }, 1346d522f475Smrg{ "-tm string", "terminal mode keywords and characters" }, 1347d522f475Smrg{ "-tn name", "TERM environment variable name" }, 1348d522f475Smrg#if OPT_WIDE_CHARS 1349d522f475Smrg{ "-/+u8", "turn on/off UTF-8 mode (implies wide-characters)" }, 1350d522f475Smrg#endif 1351d522f475Smrg#if OPT_LUIT_PROG 1352d522f475Smrg{ "-/+lc", "turn on/off locale mode using luit" }, 1353d522f475Smrg{ "-lcc path", "filename of locale converter (" DEFLOCALEFILTER ")" }, 13540bd37d32Smrg/* -en is deprecated, not shown in help message */ 1355d522f475Smrg#endif 13562eaa94a1Schristos{ "-/+uc", "turn on/off underline cursor" }, 1357d522f475Smrg{ "-/+ulc", "turn off/on display of underline as color" }, 1358d522f475Smrg{ "-/+ulit", "turn off/on display of underline as italics" }, 1359d522f475Smrg#ifdef HAVE_UTMP 1360d522f475Smrg{ "-/+ut", "turn on/off utmp support" }, 1361d522f475Smrg#else 1362d522f475Smrg{ "-/+ut", "turn on/off utmp support (not available)" }, 1363d522f475Smrg#endif 1364d522f475Smrg{ "-/+vb", "turn on/off visual bell" }, 1365d522f475Smrg{ "-/+pob", "turn on/off pop on bell" }, 136601037d57Smrg#if OPT_WIDE_ATTRS && OPT_ISO_COLORS 136701037d57Smrg{ "-/+itc", "turn off/on display of italic as color"}, 136801037d57Smrg#endif 1369d522f475Smrg#if OPT_WIDE_CHARS 1370d522f475Smrg{ "-/+wc", "turn on/off wide-character mode" }, 1371d522f475Smrg{ "-/+mk_width", "turn on/off simple width convention" }, 1372d522f475Smrg{ "-/+cjk_width", "turn on/off legacy CJK width convention" }, 1373d522f475Smrg#endif 1374d522f475Smrg{ "-/+wf", "turn on/off wait for map before command exec" }, 1375d522f475Smrg{ "-e command args ...", "command to execute" }, 1376d522f475Smrg#if OPT_TEK4014 1377d522f475Smrg{ "%geom", "Tek window geometry" }, 1378d522f475Smrg#endif 1379d522f475Smrg{ "#geom", "icon window geometry" }, 1380d522f475Smrg{ "-T string", "title name for window" }, 1381d522f475Smrg{ "-n string", "icon name for window" }, 1382d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 1383d522f475Smrg{ "-C", "intercept console messages" }, 1384d522f475Smrg#else 1385d522f475Smrg{ "-C", "intercept console messages (not supported)" }, 1386d522f475Smrg#endif 1387d522f475Smrg{ "-Sccn", "slave mode on \"ttycc\", file descriptor \"n\"" }, 1388d522f475Smrg{ "-into windowId", "use the window id given to -into as the parent window rather than the default root window" }, 1389d522f475Smrg#if OPT_ZICONBEEP 1390d522f475Smrg{ "-ziconbeep percent", "beep and flag icon of window having hidden output" }, 1391d522f475Smrg#endif 1392d522f475Smrg#if OPT_SAME_NAME 1393d522f475Smrg{ "-/+samename", "turn on/off the no-flicker option for title and icon name" }, 1394d522f475Smrg#endif 1395d522f475Smrg#if OPT_SESSION_MGT 1396d522f475Smrg{ "-/+sm", "turn on/off the session-management support" }, 1397d522f475Smrg#endif 1398956cc18dSsnj#if OPT_MAXIMIZE 1399ad37e533Smrg{"-/+maximized", "turn on/off maximize on startup" }, 1400a1f3da82Smrg{"-/+fullscreen", "turn on/off fullscreen on startup" }, 1401956cc18dSsnj#endif 1402d522f475Smrg{ NULL, NULL }}; 1403d522f475Smrg/* *INDENT-ON* */ 1404d522f475Smrg 140501037d57Smrgstatic const char *const message[] = 1406d522f475Smrg{ 1407d522f475Smrg "Fonts should be fixed width and, if both normal and bold are specified, should", 1408d522f475Smrg "have the same size. If only a normal font is specified, it will be used for", 1409d522f475Smrg "both normal and bold text (by doing overstriking). The -e option, if given,", 1410d522f475Smrg "must appear at the end of the command line, otherwise the user's default shell", 1411d522f475Smrg "will be started. Options that start with a plus sign (+) restore the default.", 1412d522f475Smrg NULL}; 1413d522f475Smrg 1414d522f475Smrg/* 1415d522f475Smrg * Decode a key-definition. This combines the termcap and ttyModes, for 1416d522f475Smrg * comparison. Note that octal escapes in ttyModes are done by the normal 1417d522f475Smrg * resource translation. Also, ttyModes allows '^-' as a synonym for disabled. 1418d522f475Smrg */ 1419d522f475Smrgstatic int 1420d522f475Smrgdecode_keyvalue(char **ptr, int termcap) 1421d522f475Smrg{ 1422d522f475Smrg char *string = *ptr; 1423d522f475Smrg int value = -1; 1424d522f475Smrg 142520d2c4d2Smrg TRACE(("decode_keyvalue '%s'\n", string)); 1426d522f475Smrg if (*string == '^') { 1427d522f475Smrg switch (*++string) { 1428d522f475Smrg case '?': 1429d522f475Smrg value = A2E(ANSI_DEL); 1430d522f475Smrg break; 1431d522f475Smrg case '-': 1432d522f475Smrg if (!termcap) { 1433d522f475Smrg errno = 0; 1434d522f475Smrg#if defined(_POSIX_VDISABLE) && defined(HAVE_UNISTD_H) 1435d522f475Smrg value = _POSIX_VDISABLE; 1436d522f475Smrg#endif 1437d522f475Smrg#if defined(_PC_VDISABLE) 1438d522f475Smrg if (value == -1) { 143920d2c4d2Smrg value = (int) fpathconf(0, _PC_VDISABLE); 1440d522f475Smrg if (value == -1) { 1441d522f475Smrg if (errno != 0) 1442d522f475Smrg break; /* skip this (error) */ 1443d522f475Smrg value = 0377; 1444d522f475Smrg } 1445d522f475Smrg } 1446d522f475Smrg#elif defined(VDISABLE) 1447d522f475Smrg if (value == -1) 1448d522f475Smrg value = VDISABLE; 1449d522f475Smrg#endif 1450d522f475Smrg break; 1451d522f475Smrg } 1452d522f475Smrg /* FALLTHRU */ 1453d522f475Smrg default: 1454d522f475Smrg value = CONTROL(*string); 1455d522f475Smrg break; 1456d522f475Smrg } 1457d522f475Smrg ++string; 1458d522f475Smrg } else if (termcap && (*string == '\\')) { 14592e4f8982Smrg char *s = (string + 1); 1460d522f475Smrg char *d; 14612e4f8982Smrg int temp = (int) strtol(s, &d, 8); 14622e4f8982Smrg if (PartS2L(s, d) && temp > 0) { 1463d522f475Smrg value = temp; 1464d522f475Smrg string = d; 1465d522f475Smrg } 1466d522f475Smrg } else { 1467d522f475Smrg value = CharOf(*string); 1468d522f475Smrg ++string; 1469d522f475Smrg } 1470d522f475Smrg *ptr = string; 147120d2c4d2Smrg TRACE(("...decode_keyvalue %#x\n", value)); 1472d522f475Smrg return value; 1473d522f475Smrg} 1474d522f475Smrg 1475d522f475Smrgstatic int 14760bd37d32SmrgmatchArg(XrmOptionDescRec * table, const char *param) 14770bd37d32Smrg{ 14780bd37d32Smrg int result = -1; 14790bd37d32Smrg int n; 14800bd37d32Smrg int ch; 14810bd37d32Smrg 14820bd37d32Smrg for (n = 0; (ch = table->option[n]) != '\0'; ++n) { 14830bd37d32Smrg if (param[n] == ch) { 14840bd37d32Smrg result = n; 14850bd37d32Smrg } else { 14860bd37d32Smrg if (param[n] != '\0') 14870bd37d32Smrg result = -1; 14880bd37d32Smrg break; 14890bd37d32Smrg } 14900bd37d32Smrg } 14910bd37d32Smrg 14920bd37d32Smrg return result; 14930bd37d32Smrg} 14940bd37d32Smrg 14950bd37d32Smrg/* return the number of argv[] entries which constitute arguments of option */ 14960bd37d32Smrgstatic int 14970bd37d32SmrgcountArg(XrmOptionDescRec * item) 1498d522f475Smrg{ 14990bd37d32Smrg int result = 0; 15000bd37d32Smrg 15010bd37d32Smrg switch (item->argKind) { 15020bd37d32Smrg case XrmoptionNoArg: 15030bd37d32Smrg /* FALLTHRU */ 15040bd37d32Smrg case XrmoptionIsArg: 15050bd37d32Smrg /* FALLTHRU */ 15060bd37d32Smrg case XrmoptionStickyArg: 15070bd37d32Smrg break; 15080bd37d32Smrg case XrmoptionSepArg: 15090bd37d32Smrg /* FALLTHRU */ 15100bd37d32Smrg case XrmoptionResArg: 15110bd37d32Smrg /* FALLTHRU */ 15120bd37d32Smrg case XrmoptionSkipArg: 15130bd37d32Smrg result = 1; 15140bd37d32Smrg break; 15150bd37d32Smrg case XrmoptionSkipLine: 15160bd37d32Smrg break; 15170bd37d32Smrg case XrmoptionSkipNArgs: 15180bd37d32Smrg result = (int) (long) (item->value); 15190bd37d32Smrg break; 15200bd37d32Smrg } 15210bd37d32Smrg return result; 15220bd37d32Smrg} 15230bd37d32Smrg 15240bd37d32Smrg#define isOption(string) (Boolean)((string)[0] == '-' || (string)[0] == '+') 15250bd37d32Smrg 15260bd37d32Smrg/* 15270bd37d32Smrg * Parse the argument list, more/less as XtInitialize, etc., would do, so we 15280bd37d32Smrg * can find our own "-help" and "-version" options reliably. Improve on just 15290bd37d32Smrg * doing that, by detecting ambiguous options (things that happen to match the 15300bd37d32Smrg * abbreviated option we are examining), and making it smart enough to handle 15310bd37d32Smrg * "-d" as an abbreviation for "-display". Doing this requires checking the 15320bd37d32Smrg * standard table (something that the X libraries should do). 15330bd37d32Smrg */ 15340bd37d32Smrgstatic XrmOptionDescRec * 15350bd37d32SmrgparseArg(int *num, char **argv, char **valuep) 15360bd37d32Smrg{ 15370bd37d32Smrg /* table adapted from XtInitialize, used here to improve abbreviations */ 15380bd37d32Smrg /* *INDENT-OFF* */ 1539f2e35a3aSmrg#define DATA(option,kind) { (char *) option, NULL, kind, (XtPointer) NULL } 15400bd37d32Smrg static XrmOptionDescRec opTable[] = { 15410bd37d32Smrg DATA("+synchronous", XrmoptionNoArg), 15420bd37d32Smrg DATA("-background", XrmoptionSepArg), 15430bd37d32Smrg DATA("-bd", XrmoptionSepArg), 15440bd37d32Smrg DATA("-bg", XrmoptionSepArg), 15450bd37d32Smrg DATA("-bordercolor", XrmoptionSepArg), 15460bd37d32Smrg DATA("-borderwidth", XrmoptionSepArg), 15470bd37d32Smrg DATA("-bw", XrmoptionSepArg), 15480bd37d32Smrg DATA("-display", XrmoptionSepArg), 15490bd37d32Smrg DATA("-fg", XrmoptionSepArg), 15500bd37d32Smrg DATA("-fn", XrmoptionSepArg), 15510bd37d32Smrg DATA("-font", XrmoptionSepArg), 15520bd37d32Smrg DATA("-foreground", XrmoptionSepArg), 15530bd37d32Smrg DATA("-iconic", XrmoptionNoArg), 15540bd37d32Smrg DATA("-name", XrmoptionSepArg), 15550bd37d32Smrg DATA("-reverse", XrmoptionNoArg), 15560bd37d32Smrg DATA("-selectionTimeout", XrmoptionSepArg), 15570bd37d32Smrg DATA("-synchronous", XrmoptionNoArg), 15580bd37d32Smrg DATA("-title", XrmoptionSepArg), 15590bd37d32Smrg DATA("-xnllanguage", XrmoptionSepArg), 15600bd37d32Smrg DATA("-xrm", XrmoptionResArg), 15610bd37d32Smrg DATA("-xtsessionID", XrmoptionSepArg), 15620bd37d32Smrg /* These xterm options are processed after XtOpenApplication */ 15630bd37d32Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 15640bd37d32Smrg DATA("-C", XrmoptionNoArg), 15650bd37d32Smrg#endif /* TIOCCONS */ 15660bd37d32Smrg DATA("-S", XrmoptionStickyArg), 15670bd37d32Smrg DATA("-D", XrmoptionNoArg), 15680bd37d32Smrg }; 15690bd37d32Smrg#undef DATA 15700bd37d32Smrg /* *INDENT-ON* */ 15710bd37d32Smrg XrmOptionDescRec *result = 0; 15720bd37d32Smrg Cardinal inlist; 15730bd37d32Smrg Cardinal limit = XtNumber(optionDescList) + XtNumber(opTable); 15740bd37d32Smrg int atbest = -1; 15750bd37d32Smrg int best = -1; 15760bd37d32Smrg int test; 15770bd37d32Smrg Boolean exact = False; 15780bd37d32Smrg int ambiguous1 = -1; 15790bd37d32Smrg int ambiguous2 = -1; 15800bd37d32Smrg char *option; 15810bd37d32Smrg char *value; 15820bd37d32Smrg 15830bd37d32Smrg#define ITEM(n) ((Cardinal)(n) < XtNumber(optionDescList) \ 15840bd37d32Smrg ? &optionDescList[n] \ 15850bd37d32Smrg : &opTable[(Cardinal)(n) - XtNumber(optionDescList)]) 15860bd37d32Smrg 15870bd37d32Smrg if ((option = argv[*num]) != 0) { 15880bd37d32Smrg Boolean need_value; 15890bd37d32Smrg Boolean have_value = False; 15900bd37d32Smrg 15910bd37d32Smrg TRACE(("parseArg %s\n", option)); 15920bd37d32Smrg if ((value = argv[(*num) + 1]) != 0) { 1593e0a2b6dfSmrg have_value = (Boolean) !isOption(value); 15940bd37d32Smrg } 15950bd37d32Smrg for (inlist = 0; inlist < limit; ++inlist) { 15960bd37d32Smrg XrmOptionDescRec *check = ITEM(inlist); 15970bd37d32Smrg 15980bd37d32Smrg test = matchArg(check, option); 15990bd37d32Smrg if (test < 0) 16000bd37d32Smrg continue; 16010bd37d32Smrg 16020bd37d32Smrg /* check for exact match */ 16030bd37d32Smrg if ((test + 1) == (int) strlen(check->option)) { 16040bd37d32Smrg if (check->argKind == XrmoptionStickyArg) { 16050bd37d32Smrg if (strlen(option) > strlen(check->option)) { 16060bd37d32Smrg exact = True; 16070bd37d32Smrg atbest = (int) inlist; 16080bd37d32Smrg break; 16090bd37d32Smrg } 16100bd37d32Smrg } else if ((test + 1) == (int) strlen(option)) { 16110bd37d32Smrg exact = True; 16120bd37d32Smrg atbest = (int) inlist; 16130bd37d32Smrg break; 16140bd37d32Smrg } 16150bd37d32Smrg } 16160bd37d32Smrg 16170bd37d32Smrg need_value = (Boolean) (test > 0 && countArg(check) > 0); 16180bd37d32Smrg 16190bd37d32Smrg if (need_value && value != 0) { 16200bd37d32Smrg ; 16210bd37d32Smrg } else if (need_value ^ have_value) { 16220bd37d32Smrg TRACE(("...skipping, need %d vs have %d\n", need_value, have_value)); 16230bd37d32Smrg continue; 16240bd37d32Smrg } 16250bd37d32Smrg 16260bd37d32Smrg /* special-case for our own options - always allow abbreviation */ 16270bd37d32Smrg if (test > 0 16280bd37d32Smrg && ITEM(inlist)->argKind >= XrmoptionSkipArg) { 16290bd37d32Smrg atbest = (int) inlist; 1630e0a2b6dfSmrg if (ITEM(inlist)->argKind == XrmoptionSkipNArgs) { 1631e0a2b6dfSmrg /* in particular, silence a warning about ambiguity */ 1632e0a2b6dfSmrg exact = 1; 1633e0a2b6dfSmrg } 16340bd37d32Smrg break; 16350bd37d32Smrg } 16360bd37d32Smrg if (test > best) { 16370bd37d32Smrg best = test; 16380bd37d32Smrg atbest = (int) inlist; 16390bd37d32Smrg } else if (test == best) { 16400bd37d32Smrg if (atbest >= 0) { 16410bd37d32Smrg if (atbest > 0) { 16420bd37d32Smrg ambiguous1 = (int) inlist; 16430bd37d32Smrg ambiguous2 = (int) atbest; 16440bd37d32Smrg } 16450bd37d32Smrg atbest = -1; 16460bd37d32Smrg } 16470bd37d32Smrg } 16480bd37d32Smrg } 16490bd37d32Smrg } 16500bd37d32Smrg 16510bd37d32Smrg *valuep = 0; 16520bd37d32Smrg if (atbest >= 0) { 16530bd37d32Smrg result = ITEM(atbest); 16540bd37d32Smrg if (!exact) { 16550bd37d32Smrg if (ambiguous1 >= 0 && ambiguous2 >= 0) { 16560bd37d32Smrg xtermWarning("ambiguous option \"%s\" vs \"%s\"\n", 16570bd37d32Smrg ITEM(ambiguous1)->option, 16580bd37d32Smrg ITEM(ambiguous2)->option); 16590bd37d32Smrg } else if (strlen(option) > strlen(result->option)) { 16600bd37d32Smrg result = 0; 16610bd37d32Smrg } 16620bd37d32Smrg } 16630bd37d32Smrg if (result != 0) { 16640bd37d32Smrg TRACE(("...result %s\n", result->option)); 16650bd37d32Smrg /* expand abbreviations */ 16660bd37d32Smrg if (result->argKind != XrmoptionStickyArg) { 16670bd37d32Smrg if (strcmp(argv[*num], result->option)) { 16680bd37d32Smrg argv[*num] = x_strdup(result->option); 16690bd37d32Smrg } 16700bd37d32Smrg } 16710bd37d32Smrg 16720bd37d32Smrg /* adjust (*num) to skip option value */ 16730bd37d32Smrg (*num) += countArg(result); 16740bd37d32Smrg TRACE(("...next %s\n", NonNull(argv[*num]))); 16750bd37d32Smrg if (result->argKind == XrmoptionSkipArg) { 16760bd37d32Smrg *valuep = argv[*num]; 16770bd37d32Smrg TRACE(("...parameter %s\n", NonNull(*valuep))); 16780bd37d32Smrg } 16790bd37d32Smrg } 16800bd37d32Smrg } 16810bd37d32Smrg#undef ITEM 16820bd37d32Smrg return result; 1683d522f475Smrg} 1684d522f475Smrg 1685d522f475Smrgstatic void 1686d522f475SmrgSyntax(char *badOption) 1687d522f475Smrg{ 1688d522f475Smrg OptionHelp *opt; 1689d522f475Smrg OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList)); 1690d522f475Smrg int col; 1691d522f475Smrg 16920bd37d32Smrg TRACE(("Syntax error at %s\n", badOption)); 16930bd37d32Smrg xtermWarning("bad command line option \"%s\"\r\n\n", badOption); 1694d522f475Smrg 1695d522f475Smrg fprintf(stderr, "usage: %s", ProgramName); 1696956cc18dSsnj col = 8 + (int) strlen(ProgramName); 1697d522f475Smrg for (opt = list; opt->opt; opt++) { 1698956cc18dSsnj int len = 3 + (int) strlen(opt->opt); /* space [ string ] */ 1699d522f475Smrg if (col + len > 79) { 1700d522f475Smrg fprintf(stderr, "\r\n "); /* 3 spaces */ 1701d522f475Smrg col = 3; 1702d522f475Smrg } 1703d522f475Smrg fprintf(stderr, " [%s]", opt->opt); 1704d522f475Smrg col += len; 1705d522f475Smrg } 1706d522f475Smrg 1707d522f475Smrg fprintf(stderr, "\r\n\nType %s -help for a full description.\r\n\n", 1708d522f475Smrg ProgramName); 1709d522f475Smrg exit(1); 1710d522f475Smrg} 1711d522f475Smrg 1712d522f475Smrgstatic void 1713d522f475SmrgVersion(void) 1714d522f475Smrg{ 1715d522f475Smrg printf("%s\n", xtermVersion()); 1716d522f475Smrg fflush(stdout); 1717d522f475Smrg} 1718d522f475Smrg 1719d522f475Smrgstatic void 1720d522f475SmrgHelp(void) 1721d522f475Smrg{ 1722d522f475Smrg OptionHelp *opt; 1723d522f475Smrg OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList)); 172401037d57Smrg const char *const *cpp; 1725d522f475Smrg 1726d522f475Smrg printf("%s usage:\n %s [-options ...] [-e command args]\n\n", 1727d522f475Smrg xtermVersion(), ProgramName); 1728d522f475Smrg printf("where options include:\n"); 1729d522f475Smrg for (opt = list; opt->opt; opt++) { 1730d522f475Smrg printf(" %-28s %s\n", opt->opt, opt->desc); 1731d522f475Smrg } 1732d522f475Smrg 1733d522f475Smrg putchar('\n'); 1734d522f475Smrg for (cpp = message; *cpp; cpp++) 1735d522f475Smrg puts(*cpp); 1736d522f475Smrg putchar('\n'); 1737d522f475Smrg fflush(stdout); 1738d522f475Smrg} 1739d522f475Smrg 1740f2e35a3aSmrgstatic void 1741f2e35a3aSmrgNeedParam(XrmOptionDescRec * option_ptr, const char *option_val) 1742f2e35a3aSmrg{ 1743f2e35a3aSmrg if (IsEmpty(option_val)) { 1744f2e35a3aSmrg xtermWarning("option %s requires a value\n", option_ptr->option); 1745f2e35a3aSmrg exit(1); 1746f2e35a3aSmrg } 1747f2e35a3aSmrg} 1748f2e35a3aSmrg 1749d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 1750d522f475Smrg/* ARGSUSED */ 1751d522f475Smrgstatic Boolean 1752d522f475SmrgConvertConsoleSelection(Widget w GCC_UNUSED, 1753894e0ac8Smrg Atom *selection GCC_UNUSED, 1754894e0ac8Smrg Atom *target GCC_UNUSED, 1755894e0ac8Smrg Atom *type GCC_UNUSED, 1756d522f475Smrg XtPointer *value GCC_UNUSED, 1757d522f475Smrg unsigned long *length GCC_UNUSED, 1758d522f475Smrg int *format GCC_UNUSED) 1759d522f475Smrg{ 1760d522f475Smrg /* we don't save console output, so can't offer it */ 1761d522f475Smrg return False; 1762d522f475Smrg} 1763d522f475Smrg#endif /* TIOCCONS */ 1764d522f475Smrg 1765d522f475Smrg/* 1766d522f475Smrg * DeleteWindow(): Action proc to implement ICCCM delete_window. 1767d522f475Smrg */ 1768d522f475Smrg/* ARGSUSED */ 1769d522f475Smrgstatic void 1770d522f475SmrgDeleteWindow(Widget w, 1771894e0ac8Smrg XEvent *event GCC_UNUSED, 1772e0a2b6dfSmrg String *params GCC_UNUSED, 1773d522f475Smrg Cardinal *num_params GCC_UNUSED) 1774d522f475Smrg{ 1775d522f475Smrg#if OPT_TEK4014 1776d522f475Smrg if (w == toplevel) { 1777d522f475Smrg if (TEK4014_SHOWN(term)) 1778d522f475Smrg hide_vt_window(); 1779d522f475Smrg else 1780d522f475Smrg do_hangup(w, (XtPointer) 0, (XtPointer) 0); 178120d2c4d2Smrg } else if (TScreenOf(term)->Vshow) 1782d522f475Smrg hide_tek_window(); 1783d522f475Smrg else 1784d522f475Smrg#endif 1785d522f475Smrg do_hangup(w, (XtPointer) 0, (XtPointer) 0); 1786d522f475Smrg} 1787d522f475Smrg 1788d522f475Smrg/* ARGSUSED */ 1789d522f475Smrgstatic void 1790d522f475SmrgKeyboardMapping(Widget w GCC_UNUSED, 1791894e0ac8Smrg XEvent *event, 1792e0a2b6dfSmrg String *params GCC_UNUSED, 1793d522f475Smrg Cardinal *num_params GCC_UNUSED) 1794d522f475Smrg{ 1795d522f475Smrg switch (event->type) { 1796d522f475Smrg case MappingNotify: 1797d522f475Smrg XRefreshKeyboardMapping(&event->xmapping); 1798d522f475Smrg break; 1799d522f475Smrg } 1800d522f475Smrg} 1801d522f475Smrg 1802d522f475Smrgstatic XtActionsRec actionProcs[] = 1803d522f475Smrg{ 1804d522f475Smrg {"DeleteWindow", DeleteWindow}, 1805d522f475Smrg {"KeyboardMapping", KeyboardMapping}, 1806d522f475Smrg}; 1807d522f475Smrg 1808d522f475Smrg/* 1809d522f475Smrg * Some platforms use names such as /dev/tty01, others /dev/pts/1. Parse off 1810d522f475Smrg * the "tty01" or "pts/1" portion, and return that for use as an identifier for 1811d522f475Smrg * utmp. 1812d522f475Smrg */ 1813d522f475Smrgstatic char * 1814d522f475Smrgmy_pty_name(char *device) 1815d522f475Smrg{ 1816d522f475Smrg size_t len = strlen(device); 1817d522f475Smrg Bool name = False; 1818d522f475Smrg 1819d522f475Smrg while (len != 0) { 1820d522f475Smrg int ch = device[len - 1]; 1821d522f475Smrg if (isdigit(ch)) { 1822d522f475Smrg len--; 1823d522f475Smrg } else if (ch == '/') { 1824d522f475Smrg if (name) 1825d522f475Smrg break; 1826d522f475Smrg len--; 1827d522f475Smrg } else if (isalpha(ch)) { 1828d522f475Smrg name = True; 1829d522f475Smrg len--; 1830d522f475Smrg } else { 1831d522f475Smrg break; 1832d522f475Smrg } 1833d522f475Smrg } 1834d522f475Smrg TRACE(("my_pty_name(%s) -> '%s'\n", device, device + len)); 1835d522f475Smrg return device + len; 1836d522f475Smrg} 1837d522f475Smrg 1838d522f475Smrg/* 1839d522f475Smrg * If the name contains a '/', it is a "pts/1" case. Otherwise, return the 1840d522f475Smrg * last few characters for a utmp identifier. 1841d522f475Smrg */ 1842d522f475Smrgstatic char * 1843d522f475Smrgmy_pty_id(char *device) 1844d522f475Smrg{ 1845d522f475Smrg char *name = my_pty_name(device); 1846d522f475Smrg char *leaf = x_basename(name); 1847d522f475Smrg 1848d522f475Smrg if (name == leaf) { /* no '/' in the name */ 1849956cc18dSsnj int len = (int) strlen(leaf); 1850d522f475Smrg if (PTYCHARLEN < len) 1851d522f475Smrg leaf = leaf + (len - PTYCHARLEN); 1852d522f475Smrg } 1853d522f475Smrg TRACE(("my_pty_id (%s) -> '%s'\n", device, leaf)); 1854d522f475Smrg return leaf; 1855d522f475Smrg} 1856d522f475Smrg 1857d522f475Smrg/* 1858d522f475Smrg * Set the tty/pty identifier 1859d522f475Smrg */ 1860d522f475Smrgstatic void 1861d522f475Smrgset_pty_id(char *device, char *id) 1862d522f475Smrg{ 1863d522f475Smrg char *name = my_pty_name(device); 1864d522f475Smrg char *leaf = x_basename(name); 1865d522f475Smrg 1866d522f475Smrg if (name == leaf) { 1867d522f475Smrg strcpy(my_pty_id(device), id); 1868d522f475Smrg } else { 1869d522f475Smrg strcpy(leaf, id); 1870d522f475Smrg } 1871d522f475Smrg TRACE(("set_pty_id(%s) -> '%s'\n", id, device)); 1872d522f475Smrg} 1873d522f475Smrg 1874d522f475Smrg/* 1875d522f475Smrg * The original -S option accepts two characters to identify the pty, and a 1876d522f475Smrg * file-descriptor (assumed to be nonzero). That is not general enough, so we 1877d522f475Smrg * check first if the option contains a '/' to delimit the two fields, and if 1878d522f475Smrg * not, fall-thru to the original logic. 1879d522f475Smrg */ 1880d522f475Smrgstatic Bool 1881d522f475SmrgParseSccn(char *option) 1882d522f475Smrg{ 1883d522f475Smrg char *leaf = x_basename(option); 1884d522f475Smrg Bool code = False; 1885d522f475Smrg 188601037d57Smrg passedPty = x_strdup(option); 1887d522f475Smrg if (leaf != option) { 1888d522f475Smrg if (leaf - option > 0 1889d522f475Smrg && isdigit(CharOf(*leaf)) 1890d522f475Smrg && sscanf(leaf, "%d", &am_slave) == 1) { 1891956cc18dSsnj size_t len = (size_t) (leaf - option - 1); 1892d522f475Smrg /* 1893d522f475Smrg * If we have a slash, we only care about the part after the slash, 1894d522f475Smrg * which is a file-descriptor. The part before the slash can be 1895d522f475Smrg * the /dev/pts/XXX value, but since we do not need to reopen it, 1896d522f475Smrg * it is useful mainly for display in a "ps -ef". 1897d522f475Smrg */ 1898d522f475Smrg passedPty[len] = 0; 1899d522f475Smrg code = True; 1900d522f475Smrg } 1901d522f475Smrg } else { 1902d522f475Smrg code = (sscanf(option, "%c%c%d", 1903d522f475Smrg passedPty, passedPty + 1, &am_slave) == 3); 190401037d57Smrg passedPty[2] = '\0'; 1905d522f475Smrg } 1906d522f475Smrg TRACE(("ParseSccn(%s) = '%s' %d (%s)\n", option, 1907d522f475Smrg passedPty, am_slave, code ? "OK" : "ERR")); 1908d522f475Smrg return code; 1909d522f475Smrg} 1910d522f475Smrg 1911d522f475Smrg#if defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 1912d522f475Smrg/* 1913d522f475Smrg * From "man utmp": 1914d522f475Smrg * xterm and other terminal emulators directly create a USER_PROCESS record 1915d522f475Smrg * and generate the ut_id by using the last two letters of /dev/ttyp%c or by 1916d522f475Smrg * using p%d for /dev/pts/%d. If they find a DEAD_PROCESS for this id, they 1917d522f475Smrg * recycle it, otherwise they create a new entry. If they can, they will mark 1918d522f475Smrg * it as DEAD_PROCESS on exiting and it is advised that they null ut_line, 1919d522f475Smrg * ut_time, ut_user and ut_host as well. 1920d522f475Smrg * 1921d522f475Smrg * Generally ut_id allows no more than 3 characters (plus null), even if the 1922d522f475Smrg * pty implementation allows more than 3 digits. 1923d522f475Smrg */ 1924d522f475Smrgstatic char * 1925d522f475Smrgmy_utmp_id(char *device) 1926d522f475Smrg{ 1927d522f475Smrg typedef struct UTMP_STR UTMP_STRUCT; 1928d522f475Smrg#define UTIDSIZE (sizeof(((UTMP_STRUCT *)NULL)->ut_id)) 1929d522f475Smrg static char result[UTIDSIZE + 1]; 1930d522f475Smrg 1931d522f475Smrg#if defined(__SCO__) || defined(__UNIXWARE__) 1932d522f475Smrg /* 1933d522f475Smrg * Legend does not support old-style pty's, has no related compatibility 1934d522f475Smrg * issues, and can use the available space in ut_id differently from the 1935d522f475Smrg * default convention. 1936d522f475Smrg * 1937d522f475Smrg * This scheme is intended to avoid conflicts both with other users of 1938d522f475Smrg * utmpx as well as between multiple xterms. First, Legend uses all of the 1939d522f475Smrg * characters of ut_id, and adds no terminating NUL is required (the 1940d522f475Smrg * default scheme may add a trailing NUL). Second, all xterm entries will 1941d522f475Smrg * start with the letter 'x' followed by three digits, which will be the 1942d522f475Smrg * last three digits of the device name, regardless of the format of the 1943d522f475Smrg * device name, with leading 0's added where necessary. For instance, an 1944d522f475Smrg * xterm on /dev/pts/3 will have a ut_id of x003; an xterm on /dev/pts123 1945d522f475Smrg * will have a ut_id of x123. Under the other convention, /dev/pts/3 would 1946d522f475Smrg * have a ut_id of p3 and /dev/pts123 would have a ut_id of p123. 1947d522f475Smrg */ 1948d522f475Smrg int len, n; 1949d522f475Smrg 1950d522f475Smrg len = strlen(device); 1951d522f475Smrg n = UTIDSIZE; 1952d522f475Smrg result[n] = '\0'; 1953d522f475Smrg while ((n > 0) && (len > 0) && isdigit(device[len - 1])) 1954d522f475Smrg result[--n] = device[--len]; 1955d522f475Smrg while (n > 0) 1956d522f475Smrg result[--n] = '0'; 1957d522f475Smrg result[0] = 'x'; 1958d522f475Smrg#else 1959d522f475Smrg char *name = my_pty_name(device); 1960d522f475Smrg char *leaf = x_basename(name); 1961d522f475Smrg size_t len = strlen(leaf); 1962d522f475Smrg 1963d522f475Smrg if ((UTIDSIZE - 1) < len) 1964d522f475Smrg leaf = leaf + (len - (UTIDSIZE - 1)); 1965d522f475Smrg sprintf(result, "p%s", leaf); 1966d522f475Smrg#endif 1967d522f475Smrg 1968d522f475Smrg TRACE(("my_utmp_id (%s) -> '%s'\n", device, result)); 1969d522f475Smrg return result; 1970d522f475Smrg} 1971d522f475Smrg#endif /* USE_SYSV_UTMP */ 1972d522f475Smrg 1973d522f475Smrg#ifdef USE_POSIX_SIGNALS 1974d522f475Smrg 1975d522f475Smrgtypedef void (*sigfunc) (int); 1976d522f475Smrg 1977d522f475Smrg/* make sure we sure we ignore SIGCHLD for the cases parent 1978d522f475Smrg has just been stopped and not actually killed */ 1979d522f475Smrg 1980d522f475Smrgstatic sigfunc 1981d522f475Smrgposix_signal(int signo, sigfunc func) 1982d522f475Smrg{ 1983d522f475Smrg struct sigaction act, oact; 1984d522f475Smrg 1985d522f475Smrg act.sa_handler = func; 1986d522f475Smrg sigemptyset(&act.sa_mask); 1987d522f475Smrg#ifdef SA_RESTART 1988d522f475Smrg act.sa_flags = SA_NOCLDSTOP | SA_RESTART; 1989d522f475Smrg#else 1990d522f475Smrg act.sa_flags = SA_NOCLDSTOP; 1991d522f475Smrg#endif 1992d522f475Smrg if (sigaction(signo, &act, &oact) < 0) 1993d522f475Smrg return (SIG_ERR); 1994d522f475Smrg return (oact.sa_handler); 1995d522f475Smrg} 1996d522f475Smrg 19970bd37d32Smrg#endif /* USE_POSIX_SIGNALS */ 1998d522f475Smrg 1999d522f475Smrg#if defined(DISABLE_SETUID) || defined(USE_UTMP_SETGID) 2000d522f475Smrgstatic void 2001d522f475SmrgdisableSetUid(void) 2002d522f475Smrg{ 2003d522f475Smrg TRACE(("process %d disableSetUid\n", (int) getpid())); 2004d522f475Smrg if (setuid(save_ruid) == -1) { 20050bd37d32Smrg xtermWarning("unable to reset uid\n"); 2006d522f475Smrg exit(1); 2007d522f475Smrg } 2008d522f475Smrg TRACE_IDS; 2009d522f475Smrg} 2010d522f475Smrg#else 2011d522f475Smrg#define disableSetUid() /* nothing */ 2012d522f475Smrg#endif /* DISABLE_SETUID */ 2013d522f475Smrg 2014d522f475Smrg#if defined(DISABLE_SETGID) || defined(USE_UTMP_SETGID) 2015d522f475Smrgstatic void 2016d522f475SmrgdisableSetGid(void) 2017d522f475Smrg{ 2018d522f475Smrg TRACE(("process %d disableSetGid\n", (int) getpid())); 2019d522f475Smrg if (setegid(save_rgid) == -1) { 20200bd37d32Smrg xtermWarning("unable to reset effective gid\n"); 2021d522f475Smrg exit(1); 2022d522f475Smrg } 2023d522f475Smrg TRACE_IDS; 2024d522f475Smrg} 2025d522f475Smrg#else 2026d522f475Smrg#define disableSetGid() /* nothing */ 2027d522f475Smrg#endif /* DISABLE_SETGID */ 2028d522f475Smrg 2029d522f475Smrg#if defined(HAVE_POSIX_SAVED_IDS) 2030d522f475Smrg#if (!defined(USE_UTEMPTER) || !defined(DISABLE_SETGID)) 2031d522f475Smrgstatic void 2032d522f475SmrgsetEffectiveGroup(gid_t group) 2033d522f475Smrg{ 2034d522f475Smrg TRACE(("process %d setEffectiveGroup(%d)\n", (int) getpid(), (int) group)); 2035d522f475Smrg if (setegid(group) == -1) { 2036d522f475Smrg#ifdef __MVS__ 2037d522f475Smrg if (!(errno == EMVSERR)) /* could happen if _BPX_SHAREAS=REUSE */ 2038d522f475Smrg#endif 2039d522f475Smrg { 20400bd37d32Smrg xtermPerror("setegid(%d)", (int) group); 2041d522f475Smrg } 2042d522f475Smrg } 2043d522f475Smrg TRACE_IDS; 2044d522f475Smrg} 2045d522f475Smrg#endif 2046d522f475Smrg 2047d522f475Smrg#if !defined(USE_UTMP_SETGID) && (!defined(USE_UTEMPTER) || !defined(DISABLE_SETUID)) 2048d522f475Smrgstatic void 2049d522f475SmrgsetEffectiveUser(uid_t user) 2050d522f475Smrg{ 2051d522f475Smrg TRACE(("process %d setEffectiveUser(%d)\n", (int) getpid(), (int) user)); 2052d522f475Smrg if (seteuid(user) == -1) { 2053d522f475Smrg#ifdef __MVS__ 2054d522f475Smrg if (!(errno == EMVSERR)) 2055d522f475Smrg#endif 2056d522f475Smrg { 20570bd37d32Smrg xtermPerror("seteuid(%d)", (int) user); 2058d522f475Smrg } 2059d522f475Smrg } 2060d522f475Smrg TRACE_IDS; 2061d522f475Smrg} 2062d522f475Smrg#endif 2063d522f475Smrg#endif /* HAVE_POSIX_SAVED_IDS */ 2064d522f475Smrg 20652e4f8982Smrg#if OPT_LUIT_PROG 20662e4f8982Smrgstatic Boolean 20672e4f8982Smrgcomplex_command(char **args) 20682e4f8982Smrg{ 20692e4f8982Smrg Boolean result = False; 20702e4f8982Smrg if (x_countargv(args) == 1) { 20712e4f8982Smrg char *check = xtermFindShell(args[0], False); 20722e4f8982Smrg if (check == 0) { 20732e4f8982Smrg result = True; 20742e4f8982Smrg } else { 20752e4f8982Smrg free(check); 20762e4f8982Smrg } 20772e4f8982Smrg } 20782e4f8982Smrg return result; 20792e4f8982Smrg} 20802e4f8982Smrg#endif 20812e4f8982Smrg 20822e4f8982Smrgstatic unsigned 20832e4f8982Smrglookup_baudrate(const char *value) 20842e4f8982Smrg{ 20852e4f8982Smrg struct speed { 20862e4f8982Smrg unsigned given_speed; /* values for 'ospeed' */ 20872e4f8982Smrg unsigned actual_speed; /* the actual speed */ 20882e4f8982Smrg }; 20892e4f8982Smrg 20902e4f8982Smrg#define DATA(number) { B##number, number } 20912e4f8982Smrg 20922e4f8982Smrg static struct speed const speeds[] = 20932e4f8982Smrg { 20942e4f8982Smrg DATA(0), 20952e4f8982Smrg DATA(50), 20962e4f8982Smrg DATA(75), 20972e4f8982Smrg DATA(110), 20982e4f8982Smrg DATA(134), 20992e4f8982Smrg DATA(150), 21002e4f8982Smrg DATA(200), 21012e4f8982Smrg DATA(300), 21022e4f8982Smrg DATA(600), 21032e4f8982Smrg DATA(1200), 21042e4f8982Smrg DATA(1800), 21052e4f8982Smrg DATA(2400), 21062e4f8982Smrg DATA(4800), 21072e4f8982Smrg DATA(9600), 21082e4f8982Smrg#ifdef B19200 21092e4f8982Smrg DATA(19200), 21102e4f8982Smrg#elif defined(EXTA) 21112e4f8982Smrg {EXTA, 19200}, 21122e4f8982Smrg#endif 21132e4f8982Smrg#ifdef B28800 21142e4f8982Smrg DATA(28800), 21152e4f8982Smrg#endif 21162e4f8982Smrg#ifdef B38400 21172e4f8982Smrg DATA(38400), 21182e4f8982Smrg#elif defined(EXTB) 21192e4f8982Smrg {EXTB, 38400}, 21202e4f8982Smrg#endif 21212e4f8982Smrg#ifdef B57600 21222e4f8982Smrg DATA(57600), 21232e4f8982Smrg#endif 21242e4f8982Smrg#ifdef B76800 21252e4f8982Smrg DATA(76800), 21262e4f8982Smrg#endif 21272e4f8982Smrg#ifdef B115200 21282e4f8982Smrg DATA(115200), 21292e4f8982Smrg#endif 21302e4f8982Smrg#ifdef B153600 21312e4f8982Smrg DATA(153600), 21322e4f8982Smrg#endif 21332e4f8982Smrg#ifdef B230400 21342e4f8982Smrg DATA(230400), 21352e4f8982Smrg#endif 21362e4f8982Smrg#ifdef B307200 21372e4f8982Smrg DATA(307200), 21382e4f8982Smrg#endif 21392e4f8982Smrg#ifdef B460800 21402e4f8982Smrg DATA(460800), 21412e4f8982Smrg#endif 21422e4f8982Smrg#ifdef B500000 21432e4f8982Smrg DATA(500000), 21442e4f8982Smrg#endif 21452e4f8982Smrg#ifdef B576000 21462e4f8982Smrg DATA(576000), 21472e4f8982Smrg#endif 21482e4f8982Smrg#ifdef B921600 21492e4f8982Smrg DATA(921600), 21502e4f8982Smrg#endif 21512e4f8982Smrg#ifdef B1000000 21522e4f8982Smrg DATA(1000000), 21532e4f8982Smrg#endif 21542e4f8982Smrg#ifdef B1152000 21552e4f8982Smrg DATA(1152000), 21562e4f8982Smrg#endif 21572e4f8982Smrg#ifdef B1500000 21582e4f8982Smrg DATA(1500000), 21592e4f8982Smrg#endif 21602e4f8982Smrg#ifdef B2000000 21612e4f8982Smrg DATA(2000000), 21622e4f8982Smrg#endif 21632e4f8982Smrg#ifdef B2500000 21642e4f8982Smrg DATA(2500000), 21652e4f8982Smrg#endif 21662e4f8982Smrg#ifdef B3000000 21672e4f8982Smrg DATA(3000000), 21682e4f8982Smrg#endif 21692e4f8982Smrg#ifdef B3500000 21702e4f8982Smrg DATA(3500000), 21712e4f8982Smrg#endif 21722e4f8982Smrg#ifdef B4000000 21732e4f8982Smrg DATA(4000000), 21742e4f8982Smrg#endif 21752e4f8982Smrg }; 21762e4f8982Smrg#undef DATA 21772e4f8982Smrg unsigned result = 0; 21782e4f8982Smrg long check; 21792e4f8982Smrg char *next; 21802e4f8982Smrg if (x_toupper(*value) == 'B') 21812e4f8982Smrg value++; 21822e4f8982Smrg if (isdigit(CharOf(*value))) { 21832e4f8982Smrg check = strtol(value, &next, 10); 21842e4f8982Smrg if (FullS2L(value, next) && (check > 0)) { 21852e4f8982Smrg Cardinal n; 21862e4f8982Smrg for (n = 0; n < XtNumber(speeds); ++n) { 21872e4f8982Smrg if (speeds[n].actual_speed == (unsigned) check) { 21882e4f8982Smrg result = speeds[n].given_speed; 21892e4f8982Smrg break; 21902e4f8982Smrg } 21912e4f8982Smrg } 21922e4f8982Smrg } 21932e4f8982Smrg } 21942e4f8982Smrg if (result == 0) { 21952e4f8982Smrg fprintf(stderr, "unsupported value for baudrate: %s\n", value); 21962e4f8982Smrg } 21972e4f8982Smrg return result; 21982e4f8982Smrg} 21992e4f8982Smrg 2200d522f475Smrgint 2201d522f475Smrgmain(int argc, char *argv[]ENVP_ARG) 2202d522f475Smrg{ 2203a1f3da82Smrg#if OPT_MAXIMIZE 2204a1f3da82Smrg#define DATA(name) { #name, es##name } 220501037d57Smrg static const FlagList tblFullscreen[] = 2206a1f3da82Smrg { 2207a1f3da82Smrg DATA(Always), 2208a1f3da82Smrg DATA(Never) 2209a1f3da82Smrg }; 2210a1f3da82Smrg#undef DATA 2211a1f3da82Smrg#endif 2212a1f3da82Smrg 2213d522f475Smrg Widget form_top, menu_top; 2214d522f475Smrg Dimension menu_high; 2215d522f475Smrg TScreen *screen; 2216d522f475Smrg int mode; 2217e0a2b6dfSmrg char *my_class = x_strdup(DEFCLASS); 22182e4f8982Smrg unsigned line_speed = VAL_LINE_SPEED; 2219d522f475Smrg Window winToEmbedInto = None; 2220f2e35a3aSmrg#if defined(HAVE_LIB_XAW3DXFT) 2221f2e35a3aSmrg Xaw3dXftData *xaw3dxft_data; 2222f2e35a3aSmrg#endif 2223d522f475Smrg 2224ae137402Smrg ProgramName = x_strdup(x_basename(argv[0])); 2225ae137402Smrg ProgramPath = xtermFindShell(argv[0], True); 2226ae137402Smrg if (ProgramPath != NULL) 2227ae137402Smrg argv[0] = ProgramPath; 2228d522f475Smrg 2229d522f475Smrg#ifdef HAVE_POSIX_SAVED_IDS 2230d522f475Smrg save_euid = geteuid(); 2231d522f475Smrg save_egid = getegid(); 2232d522f475Smrg#endif 2233d522f475Smrg 2234d522f475Smrg save_ruid = getuid(); 2235d522f475Smrg save_rgid = getgid(); 2236d522f475Smrg 2237d522f475Smrg#if defined(DISABLE_SETUID) || defined(DISABLE_SETGID) 2238d522f475Smrg#if defined(DISABLE_SETUID) 2239d522f475Smrg disableSetUid(); 2240d522f475Smrg#endif 2241d522f475Smrg#if defined(DISABLE_SETGID) 2242d522f475Smrg disableSetGid(); 2243d522f475Smrg#endif 2244d522f475Smrg TRACE_IDS; 2245d522f475Smrg#endif 2246d522f475Smrg 2247d522f475Smrg /* extra length in case longer tty name like /dev/ttyq255 */ 2248d522f475Smrg ttydev = TypeMallocN(char, sizeof(TTYDEV) + 80); 2249d522f475Smrg#ifdef USE_PTY_DEVICE 2250d522f475Smrg ptydev = TypeMallocN(char, sizeof(PTYDEV) + 80); 2251d522f475Smrg if (!ttydev || !ptydev) 2252d522f475Smrg#else 2253d522f475Smrg if (!ttydev) 2254d522f475Smrg#endif 2255d522f475Smrg { 22560bd37d32Smrg xtermWarning("unable to allocate memory for ttydev or ptydev\n"); 2257d522f475Smrg exit(1); 2258d522f475Smrg } 2259d522f475Smrg strcpy(ttydev, TTYDEV); 2260d522f475Smrg#ifdef USE_PTY_DEVICE 2261d522f475Smrg strcpy(ptydev, PTYDEV); 2262d522f475Smrg#endif 2263d522f475Smrg 2264d522f475Smrg#if defined(USE_UTMP_SETGID) 2265d522f475Smrg get_pty(NULL, NULL); 2266d522f475Smrg disableSetUid(); 2267d522f475Smrg disableSetGid(); 2268d522f475Smrg TRACE_IDS; 2269d522f475Smrg#define get_pty(pty, from) really_get_pty(pty, from) 2270d522f475Smrg#endif 2271d522f475Smrg 2272d522f475Smrg /* Do these first, since we may not be able to open the display */ 2273d522f475Smrg TRACE_OPTS(xtermOptions, optionDescList, XtNumber(optionDescList)); 2274d522f475Smrg TRACE_ARGV("Before XtOpenApplication", argv); 2275ae137402Smrg restart_params = 0; 2276d522f475Smrg if (argc > 1) { 22770bd37d32Smrg XrmOptionDescRec *option_ptr; 22780bd37d32Smrg char *option_value; 2279d522f475Smrg int n; 2280e39b573cSmrg Bool quit = False; 2281d522f475Smrg 2282d522f475Smrg for (n = 1; n < argc; n++) { 22830bd37d32Smrg if ((option_ptr = parseArg(&n, argv, &option_value)) == 0) { 22840bd37d32Smrg if (argv[n] == 0) { 22850bd37d32Smrg break; 22860bd37d32Smrg } else if (isOption(argv[n])) { 22870bd37d32Smrg Syntax(argv[n]); 22880bd37d32Smrg } else if (explicit_shname != 0) { 22890bd37d32Smrg xtermWarning("Explicit shell already was %s\n", explicit_shname); 22900bd37d32Smrg Syntax(argv[n]); 22910bd37d32Smrg } 22920bd37d32Smrg explicit_shname = xtermFindShell(argv[n], True); 22930bd37d32Smrg if (explicit_shname == 0) 22940bd37d32Smrg exit(0); 22950bd37d32Smrg TRACE(("...explicit shell %s\n", explicit_shname)); 2296ae137402Smrg restart_params = (argc - n); 22970bd37d32Smrg } else if (!strcmp(option_ptr->option, "-e")) { 22980bd37d32Smrg command_to_exec = (argv + n + 1); 22990bd37d32Smrg if (!command_to_exec[0]) 23000bd37d32Smrg Syntax(argv[n]); 2301ae137402Smrg restart_params = (argc - n); 23020bd37d32Smrg break; 23030bd37d32Smrg } else if (!strcmp(option_ptr->option, "-version")) { 2304d522f475Smrg Version(); 2305e39b573cSmrg quit = True; 23060bd37d32Smrg } else if (!strcmp(option_ptr->option, "-help")) { 2307d522f475Smrg Help(); 2308e39b573cSmrg quit = True; 23092e4f8982Smrg } else if (!strcmp(option_ptr->option, "-baudrate")) { 2310f2e35a3aSmrg NeedParam(option_ptr, option_value); 23112e4f8982Smrg if ((line_speed = lookup_baudrate(option_value)) == 0) { 23122e4f8982Smrg Help(); 23132e4f8982Smrg quit = True; 23142e4f8982Smrg } 23150bd37d32Smrg } else if (!strcmp(option_ptr->option, "-class")) { 2316f2e35a3aSmrg NeedParam(option_ptr, option_value); 2317e0a2b6dfSmrg free(my_class); 23180bd37d32Smrg if ((my_class = x_strdup(option_value)) == 0) { 2319d522f475Smrg Help(); 2320e39b573cSmrg quit = True; 2321d522f475Smrg } 23220bd37d32Smrg } else if (!strcmp(option_ptr->option, "-into")) { 23230bd37d32Smrg char *endPtr; 2324f2e35a3aSmrg NeedParam(option_ptr, option_value); 23250bd37d32Smrg winToEmbedInto = (Window) strtol(option_value, &endPtr, 0); 23262e4f8982Smrg if (!FullS2L(option_value, endPtr)) { 23272e4f8982Smrg Help(); 23282e4f8982Smrg quit = True; 23292e4f8982Smrg } 2330d522f475Smrg } 2331d522f475Smrg } 2332d522f475Smrg if (quit) 2333d522f475Smrg exit(0); 23340bd37d32Smrg /* 23350bd37d32Smrg * If there is anything left unparsed, and we're not using "-e", 23360bd37d32Smrg * then give up. 23370bd37d32Smrg */ 23380bd37d32Smrg if (n < argc && !command_to_exec) { 23390bd37d32Smrg Syntax(argv[n]); 23400bd37d32Smrg } 2341d522f475Smrg } 2342d522f475Smrg 23430bd37d32Smrg /* This dumped core on HP-UX 9.05 with X11R5 */ 2344d522f475Smrg#if OPT_I18N_SUPPORT 2345d522f475Smrg XtSetLanguageProc(NULL, NULL, NULL); 2346d522f475Smrg#endif 2347d522f475Smrg 2348f2e35a3aSmrg /* enable Xft support in Xaw3DXft */ 2349f2e35a3aSmrg#if defined(HAVE_LIB_XAW3DXFT) 2350f2e35a3aSmrg GET_XAW3DXFT_DATA(xaw3dxft_data); 2351f2e35a3aSmrg xaw3dxft_data->encoding = -1; 2352f2e35a3aSmrg#endif 2353f2e35a3aSmrg 2354d522f475Smrg#ifdef TERMIO_STRUCT /* { */ 2355d522f475Smrg /* Initialization is done here rather than above in order 2356d522f475Smrg * to prevent any assumptions about the order of the contents 2357d522f475Smrg * of the various terminal structures (which may change from 2358d522f475Smrg * implementation to implementation). 2359d522f475Smrg */ 2360d522f475Smrg memset(&d_tio, 0, sizeof(d_tio)); 2361d522f475Smrg d_tio.c_iflag = ICRNL | IXON; 2362f2e35a3aSmrg d_tio.c_oflag = TAB3 | D_TIO_FLAGS; 2363d522f475Smrg { 2364d522f475Smrg Cardinal nn; 2365d522f475Smrg 2366d522f475Smrg /* fill in default-values */ 2367f2e35a3aSmrg for (nn = 0; nn < XtNumber(ttyChars); ++nn) { 2368d522f475Smrg if (validTtyChar(d_tio, nn)) { 2369f2e35a3aSmrg d_tio.c_cc[ttyChars[nn].sysMode] = 2370f2e35a3aSmrg (cc_t) ttyChars[nn].myDefault; 2371d522f475Smrg } 2372d522f475Smrg } 2373d522f475Smrg } 2374d522f475Smrg#if defined(macII) || defined(ATT) || defined(CRAY) /* { */ 23752e4f8982Smrg d_tio.c_cflag = line_speed | CS8 | CREAD | PARENB | HUPCL; 2376d522f475Smrg d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK; 2377d522f475Smrg#ifdef ECHOKE 2378d522f475Smrg d_tio.c_lflag |= ECHOKE | IEXTEN; 2379d522f475Smrg#endif 2380d522f475Smrg#ifdef ECHOCTL 2381d522f475Smrg d_tio.c_lflag |= ECHOCTL | IEXTEN; 2382d522f475Smrg#endif 2383d522f475Smrg#ifndef USE_TERMIOS /* { */ 2384d522f475Smrg d_tio.c_line = 0; 2385d522f475Smrg#endif /* } */ 2386d522f475Smrg#ifdef HAS_LTCHARS /* { */ 2387d522f475Smrg d_ltc.t_suspc = CSUSP; /* t_suspc */ 2388d522f475Smrg d_ltc.t_dsuspc = CDSUSP; /* t_dsuspc */ 2389d522f475Smrg d_ltc.t_rprntc = CRPRNT; 2390d522f475Smrg d_ltc.t_flushc = CFLUSH; 2391d522f475Smrg d_ltc.t_werasc = CWERASE; 2392d522f475Smrg d_ltc.t_lnextc = CLNEXT; 2393d522f475Smrg#endif /* } HAS_LTCHARS */ 2394d522f475Smrg#ifdef TIOCLSET /* { */ 2395d522f475Smrg d_lmode = 0; 2396d522f475Smrg#endif /* } TIOCLSET */ 2397d522f475Smrg#else /* }{ else !macII, ATT, CRAY */ 2398d522f475Smrg#ifndef USE_POSIX_TERMIOS 2399d522f475Smrg#ifdef BAUD_0 /* { */ 2400d522f475Smrg d_tio.c_cflag = CS8 | CREAD | PARENB | HUPCL; 2401d522f475Smrg#else /* }{ !BAUD_0 */ 24022e4f8982Smrg d_tio.c_cflag = line_speed | CS8 | CREAD | PARENB | HUPCL; 2403d522f475Smrg#endif /* } !BAUD_0 */ 2404d522f475Smrg#else /* USE_POSIX_TERMIOS */ 2405d522f475Smrg d_tio.c_cflag = CS8 | CREAD | PARENB | HUPCL; 24062e4f8982Smrg cfsetispeed(&d_tio, line_speed); 24072e4f8982Smrg cfsetospeed(&d_tio, line_speed); 2408d522f475Smrg#endif 2409d522f475Smrg d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK; 2410d522f475Smrg#ifdef ECHOKE 2411d522f475Smrg d_tio.c_lflag |= ECHOKE | IEXTEN; 2412d522f475Smrg#endif 2413d522f475Smrg#ifdef ECHOCTL 2414d522f475Smrg d_tio.c_lflag |= ECHOCTL | IEXTEN; 2415d522f475Smrg#endif 2416d522f475Smrg#ifndef USE_POSIX_TERMIOS 2417d522f475Smrg#ifdef NTTYDISC 2418d522f475Smrg d_tio.c_line = NTTYDISC; 2419d522f475Smrg#else 2420d522f475Smrg d_tio.c_line = 0; 2421d522f475Smrg#endif 2422d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 2423d522f475Smrg#ifdef __sgi 2424d522f475Smrg d_tio.c_cflag &= ~(HUPCL | PARENB); 2425d522f475Smrg d_tio.c_iflag |= BRKINT | ISTRIP | IGNPAR; 2426d522f475Smrg#endif 2427d522f475Smrg#ifdef __MVS__ 2428d522f475Smrg d_tio.c_cflag &= ~(HUPCL | PARENB); 2429d522f475Smrg#endif 2430d522f475Smrg { 2431d522f475Smrg Cardinal nn; 2432d522f475Smrg int i; 2433d522f475Smrg 2434d522f475Smrg /* try to inherit tty settings */ 2435d522f475Smrg for (i = 0; i <= 2; i++) { 2436d522f475Smrg TERMIO_STRUCT deftio; 2437d522f475Smrg if (ttyGetAttr(i, &deftio) == 0) { 2438f2e35a3aSmrg for (nn = 0; nn < XtNumber(ttyChars); ++nn) { 2439d522f475Smrg if (validTtyChar(d_tio, nn)) { 2440f2e35a3aSmrg d_tio.c_cc[ttyChars[nn].sysMode] = 2441f2e35a3aSmrg deftio.c_cc[ttyChars[nn].sysMode]; 2442d522f475Smrg } 2443d522f475Smrg } 2444d522f475Smrg break; 2445d522f475Smrg } 2446d522f475Smrg } 2447d522f475Smrg } 2448d522f475Smrg#if defined(USE_TERMIOS) || defined(USE_POSIX_TERMIOS) /* { */ 2449d522f475Smrg d_tio.c_cc[VMIN] = 1; 2450d522f475Smrg d_tio.c_cc[VTIME] = 0; 2451d522f475Smrg#endif /* } */ 2452d522f475Smrg#ifdef HAS_LTCHARS /* { */ 2453d522f475Smrg d_ltc.t_suspc = CharOf('\000'); /* t_suspc */ 2454d522f475Smrg d_ltc.t_dsuspc = CharOf('\000'); /* t_dsuspc */ 2455d522f475Smrg d_ltc.t_rprntc = CharOf('\377'); /* reserved... */ 2456d522f475Smrg d_ltc.t_flushc = CharOf('\377'); 2457d522f475Smrg d_ltc.t_werasc = CharOf('\377'); 2458d522f475Smrg d_ltc.t_lnextc = CharOf('\377'); 2459d522f475Smrg#endif /* } HAS_LTCHARS */ 2460d522f475Smrg 2461d522f475Smrg#ifdef TIOCLSET /* { */ 2462d522f475Smrg d_lmode = 0; 2463d522f475Smrg#endif /* } TIOCLSET */ 2464d522f475Smrg#endif /* } macII, ATT, CRAY */ 2465d522f475Smrg#endif /* } TERMIO_STRUCT */ 2466d522f475Smrg 2467d522f475Smrg /* Init the Toolkit. */ 2468d522f475Smrg { 2469d522f475Smrg#if defined(HAVE_POSIX_SAVED_IDS) && !defined(USE_UTMP_SETGID) && !defined(USE_UTEMPTER) 2470d522f475Smrg setEffectiveGroup(save_rgid); 2471d522f475Smrg setEffectiveUser(save_ruid); 2472d522f475Smrg TRACE_IDS; 2473d522f475Smrg#endif 24740bd37d32Smrg toplevel = xtermOpenApplication(&app_con, 24750bd37d32Smrg my_class, 24760bd37d32Smrg optionDescList, 24770bd37d32Smrg XtNumber(optionDescList), 2478f2e35a3aSmrg &argc, argv, 24790bd37d32Smrg fallback_resources, 24800bd37d32Smrg sessionShellWidgetClass, 24810bd37d32Smrg NULL, 0); 2482ae137402Smrg TRACE(("created toplevel widget %p, window %#lx\n", 2483ae137402Smrg (void *) toplevel, XtWindow(toplevel))); 2484d522f475Smrg 2485d522f475Smrg XtGetApplicationResources(toplevel, (XtPointer) &resource, 2486d522f475Smrg application_resources, 2487d522f475Smrg XtNumber(application_resources), NULL, 0); 2488d522f475Smrg TRACE_XRES(); 2489ad37e533Smrg#ifdef HAVE_LIB_XCURSOR 2490ad37e533Smrg if (!strcmp(resource.cursorTheme, "none")) { 2491ad37e533Smrg TRACE(("startup with no cursorTheme\n")); 2492ad37e533Smrg init_colored_cursor(XtDisplay(toplevel)); 2493ad37e533Smrg } else { 2494ad37e533Smrg const char *theme = resource.cursorTheme; 2495ad37e533Smrg if (IsEmpty(theme)) 2496ad37e533Smrg theme = "default"; 2497ad37e533Smrg TRACE(("startup with \"%s\" cursorTheme\n", theme)); 2498ad37e533Smrg xtermSetenv("XCURSOR_THEME", theme); 2499ad37e533Smrg } 2500ad37e533Smrg#endif 2501f2e35a3aSmrg#if USE_DOUBLE_BUFFER 2502f2e35a3aSmrg if (resource.buffered_fps <= 0) 2503f2e35a3aSmrg resource.buffered_fps = DEF_BUFFER_RATE; 2504f2e35a3aSmrg if (resource.buffered_fps > 100) 2505f2e35a3aSmrg resource.buffered_fps = 100; 2506f2e35a3aSmrg#endif 2507a1f3da82Smrg#if OPT_MAXIMIZE 2508a1f3da82Smrg resource.fullscreen = extendedBoolean(resource.fullscreen_s, 2509a1f3da82Smrg tblFullscreen, 2510f2e35a3aSmrg esLAST); 2511a1f3da82Smrg#endif 2512e39b573cSmrg VTInitTranslations(); 2513d522f475Smrg#if OPT_PTY_HANDSHAKE 2514d522f475Smrg resource.wait_for_map0 = resource.wait_for_map; 2515d522f475Smrg#endif 2516d522f475Smrg 2517d522f475Smrg#if defined(HAVE_POSIX_SAVED_IDS) && !defined(USE_UTMP_SETGID) 2518d522f475Smrg#if !defined(DISABLE_SETUID) || !defined(DISABLE_SETGID) 2519d522f475Smrg#if !defined(DISABLE_SETUID) 2520d522f475Smrg setEffectiveUser(save_euid); 2521d522f475Smrg#endif 2522d522f475Smrg#if !defined(DISABLE_SETGID) 2523d522f475Smrg setEffectiveGroup(save_egid); 2524d522f475Smrg#endif 2525d522f475Smrg TRACE_IDS; 2526d522f475Smrg#endif 2527d522f475Smrg#endif 2528d522f475Smrg } 2529d522f475Smrg 2530d522f475Smrg /* 2531d522f475Smrg * ICCCM delete_window. 2532d522f475Smrg */ 2533d522f475Smrg XtAppAddActions(app_con, actionProcs, XtNumber(actionProcs)); 2534d522f475Smrg 2535d522f475Smrg /* 2536d522f475Smrg * fill in terminal modes 2537d522f475Smrg */ 2538d522f475Smrg if (resource.tty_modes) { 2539f2e35a3aSmrg int n = parse_tty_modes(resource.tty_modes); 2540d522f475Smrg if (n < 0) { 25410bd37d32Smrg xtermWarning("bad tty modes \"%s\"\n", resource.tty_modes); 2542d522f475Smrg } else if (n > 0) { 2543d522f475Smrg override_tty_modes = True; 2544d522f475Smrg } 2545d522f475Smrg } 25460bd37d32Smrg initZIconBeep(); 2547d522f475Smrg hold_screen = resource.hold_screen ? 1 : 0; 2548d522f475Smrg if (resource.icon_geometry != NULL) { 2549d522f475Smrg int scr, junk; 2550d522f475Smrg int ix, iy; 2551d522f475Smrg Arg args[2]; 2552d522f475Smrg 2553d522f475Smrg for (scr = 0; /* yyuucchh */ 2554d522f475Smrg XtScreen(toplevel) != ScreenOfDisplay(XtDisplay(toplevel), scr); 2555d522f475Smrg scr++) ; 2556d522f475Smrg 2557d522f475Smrg args[0].name = XtNiconX; 2558d522f475Smrg args[1].name = XtNiconY; 2559d522f475Smrg XGeometry(XtDisplay(toplevel), scr, resource.icon_geometry, "", 2560d522f475Smrg 0, 0, 0, 0, 0, &ix, &iy, &junk, &junk); 2561d522f475Smrg args[0].value = (XtArgVal) ix; 2562d522f475Smrg args[1].value = (XtArgVal) iy; 2563d522f475Smrg XtSetValues(toplevel, args, 2); 2564d522f475Smrg } 2565d522f475Smrg 2566d522f475Smrg XtSetValues(toplevel, ourTopLevelShellArgs, 2567d522f475Smrg number_ourTopLevelShellArgs); 2568d522f475Smrg 2569d522f475Smrg#if OPT_WIDE_CHARS 2570d522f475Smrg /* seems as good a place as any */ 2571d522f475Smrg init_classtab(); 2572d522f475Smrg#endif 2573d522f475Smrg 2574d522f475Smrg /* Parse the rest of the command line */ 2575d522f475Smrg TRACE_ARGV("After XtOpenApplication", argv); 2576d522f475Smrg for (argc--, argv++; argc > 0; argc--, argv++) { 25770bd37d32Smrg if (!isOption(*argv)) { 2578d522f475Smrg#ifdef VMS 2579d522f475Smrg Syntax(*argv); 2580d522f475Smrg#else 2581d522f475Smrg if (argc > 1) 2582d522f475Smrg Syntax(*argv); 2583d522f475Smrg continue; 2584d522f475Smrg#endif 25850bd37d32Smrg } 2586d522f475Smrg 2587d522f475Smrg TRACE(("parsing %s\n", argv[0])); 2588d522f475Smrg switch (argv[0][1]) { 2589d522f475Smrg case 'C': 2590d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 2591d522f475Smrg#ifndef __sgi 2592d522f475Smrg { 2593d522f475Smrg struct stat sbuf; 2594d522f475Smrg 2595d522f475Smrg /* Must be owner and have read/write permission. 2596d522f475Smrg xdm cooperates to give the console the right user. */ 2597d522f475Smrg if (!stat("/dev/console", &sbuf) && 2598d522f475Smrg (sbuf.st_uid == save_ruid) && 2599d522f475Smrg !access("/dev/console", R_OK | W_OK)) { 2600d522f475Smrg Console = True; 2601d522f475Smrg } else 2602d522f475Smrg Console = False; 2603d522f475Smrg } 2604d522f475Smrg#else /* __sgi */ 2605d522f475Smrg Console = True; 2606d522f475Smrg#endif /* __sgi */ 2607d522f475Smrg#endif /* TIOCCONS */ 2608d522f475Smrg continue; 2609d522f475Smrg case 'S': 2610d522f475Smrg if (!ParseSccn(*argv + 2)) 2611d522f475Smrg Syntax(*argv); 2612d522f475Smrg continue; 2613d522f475Smrg#ifdef DEBUG 2614d522f475Smrg case 'D': 2615d522f475Smrg debug = True; 2616d522f475Smrg continue; 2617d522f475Smrg#endif /* DEBUG */ 26182e4f8982Smrg case 'b': 26192e4f8982Smrg if (strcmp(argv[0], "-baudrate")) 26202e4f8982Smrg Syntax(*argv); 2621f2e35a3aSmrg argc--; 2622f2e35a3aSmrg argv++; 26232e4f8982Smrg continue; 26240bd37d32Smrg case 'c': 26250bd37d32Smrg if (strcmp(argv[0], "-class")) 2626d522f475Smrg Syntax(*argv); 2627f2e35a3aSmrg argc--; 2628f2e35a3aSmrg argv++; 2629d522f475Smrg continue; 2630d522f475Smrg case 'e': 26310bd37d32Smrg if (strcmp(argv[0], "-e")) 2632d522f475Smrg Syntax(*argv); 26330bd37d32Smrg command_to_exec = (argv + 1); 2634d522f475Smrg break; 2635d522f475Smrg case 'i': 26360bd37d32Smrg if (strcmp(argv[0], "-into")) 2637d522f475Smrg Syntax(*argv); 2638f2e35a3aSmrg argc--; 2639f2e35a3aSmrg argv++; 2640d522f475Smrg continue; 2641d522f475Smrg 2642d522f475Smrg default: 2643d522f475Smrg Syntax(*argv); 2644d522f475Smrg } 2645d522f475Smrg break; 2646d522f475Smrg } 2647d522f475Smrg 2648d522f475Smrg SetupMenus(toplevel, &form_top, &menu_top, &menu_high); 2649d522f475Smrg 2650d522f475Smrg term = (XtermWidget) XtVaCreateManagedWidget("vt100", xtermWidgetClass, 2651d522f475Smrg form_top, 2652d522f475Smrg#if OPT_TOOLBAR 2653d522f475Smrg XtNmenuBar, menu_top, 2654d522f475Smrg XtNresizable, True, 2655d522f475Smrg XtNfromVert, menu_top, 2656d522f475Smrg XtNleft, XawChainLeft, 2657d522f475Smrg XtNright, XawChainRight, 2658d522f475Smrg XtNtop, XawChainTop, 2659d522f475Smrg XtNbottom, XawChainBottom, 2660d522f475Smrg XtNmenuHeight, menu_high, 2661d522f475Smrg#endif 2662d522f475Smrg (XtPointer) 0); 2663ae137402Smrg TRACE(("created vt100 widget %p, window %#lx\n", 2664ae137402Smrg (void *) term, XtWindow(term))); 2665d522f475Smrg decode_keyboard_type(term, &resource); 2666d522f475Smrg 2667d522f475Smrg screen = TScreenOf(term); 2668d522f475Smrg screen->inhibit = 0; 2669d522f475Smrg 2670d522f475Smrg#ifdef ALLOWLOGGING 2671d522f475Smrg if (term->misc.logInhibit) 2672d522f475Smrg screen->inhibit |= I_LOG; 2673d522f475Smrg#endif 2674d522f475Smrg if (term->misc.signalInhibit) 2675d522f475Smrg screen->inhibit |= I_SIGNAL; 2676d522f475Smrg#if OPT_TEK4014 2677d522f475Smrg if (term->misc.tekInhibit) 2678d522f475Smrg screen->inhibit |= I_TEK; 2679d522f475Smrg#endif 2680d522f475Smrg 2681d522f475Smrg /* 2682d522f475Smrg * We might start by showing the tek4014 window. 2683d522f475Smrg */ 2684d522f475Smrg#if OPT_TEK4014 2685d522f475Smrg if (screen->inhibit & I_TEK) 2686d522f475Smrg TEK4014_ACTIVE(term) = False; 2687d522f475Smrg 2688d522f475Smrg if (TEK4014_ACTIVE(term) && !TekInit()) 2689d522f475Smrg SysError(ERROR_INIT); 2690d522f475Smrg#endif 2691d522f475Smrg 2692d522f475Smrg /* 2693d522f475Smrg * Start the toolbar at this point, after the first window has been setup. 2694d522f475Smrg */ 2695d522f475Smrg#if OPT_TOOLBAR 2696d522f475Smrg ShowToolbar(resource.toolBar); 2697d522f475Smrg#endif 2698d522f475Smrg 26990bd37d32Smrg xtermOpenSession(); 2700d522f475Smrg 2701d522f475Smrg /* 2702d522f475Smrg * Set title and icon name if not specified 2703d522f475Smrg */ 2704d522f475Smrg if (command_to_exec) { 2705d522f475Smrg Arg args[2]; 2706d522f475Smrg 2707d522f475Smrg if (!resource.title) { 2708d522f475Smrg if (command_to_exec) { 2709d522f475Smrg resource.title = x_basename(command_to_exec[0]); 2710d522f475Smrg } /* else not reached */ 2711d522f475Smrg } 2712d522f475Smrg 2713d522f475Smrg if (!resource.icon_name) 2714d522f475Smrg resource.icon_name = resource.title; 2715d522f475Smrg XtSetArg(args[0], XtNtitle, resource.title); 2716d522f475Smrg XtSetArg(args[1], XtNiconName, resource.icon_name); 2717d522f475Smrg 27180bd37d32Smrg TRACE(("setting:\n\ttitle \"%s\"\n\ticon \"%s\"\n\thint \"%s\"\n\tbased on command \"%s\"\n", 2719d522f475Smrg resource.title, 2720d522f475Smrg resource.icon_name, 27210bd37d32Smrg NonNull(resource.icon_hint), 2722d522f475Smrg *command_to_exec)); 2723d522f475Smrg 2724d522f475Smrg XtSetValues(toplevel, args, 2); 2725d522f475Smrg } 2726d522f475Smrg#if OPT_LUIT_PROG 2727d522f475Smrg if (term->misc.callfilter) { 27280bd37d32Smrg char **split_filter = x_splitargs(term->misc.localefilter); 27290bd37d32Smrg unsigned count_split = x_countargv(split_filter); 27300bd37d32Smrg unsigned count_exec = x_countargv(command_to_exec); 27310bd37d32Smrg unsigned count_using = (unsigned) (term->misc.use_encoding ? 2 : 0); 27320bd37d32Smrg 27330bd37d32Smrg command_to_exec_with_luit = TypeCallocN(char *, 27340bd37d32Smrg (count_split 27350bd37d32Smrg + count_exec 27360bd37d32Smrg + count_using 27370bd37d32Smrg + 8)); 27380bd37d32Smrg if (command_to_exec_with_luit == NULL) 27390bd37d32Smrg SysError(ERROR_LUMALLOC); 27400bd37d32Smrg 27410bd37d32Smrg x_appendargv(command_to_exec_with_luit, split_filter); 27420bd37d32Smrg if (count_using) { 27430bd37d32Smrg char *encoding_opt[4]; 27440bd37d32Smrg encoding_opt[0] = x_strdup("-encoding"); 27450bd37d32Smrg encoding_opt[1] = term->misc.locale_str; 27460bd37d32Smrg encoding_opt[2] = 0; 27470bd37d32Smrg x_appendargv(command_to_exec_with_luit, encoding_opt); 27480bd37d32Smrg } 27490bd37d32Smrg command_length_with_luit = x_countargv(command_to_exec_with_luit); 27500bd37d32Smrg if (count_exec) { 27512e4f8982Smrg static char *fixup_shell[] = 2752f2e35a3aSmrg {(char *) "sh", (char *) "-c", 0}; 27530bd37d32Smrg char *delimiter[2]; 27540bd37d32Smrg delimiter[0] = x_strdup("--"); 27550bd37d32Smrg delimiter[1] = 0; 27560bd37d32Smrg x_appendargv(command_to_exec_with_luit, delimiter); 27572e4f8982Smrg if (complex_command(command_to_exec)) { 27582e4f8982Smrg x_appendargv(command_to_exec_with_luit, fixup_shell); 27592e4f8982Smrg } 27600bd37d32Smrg x_appendargv(command_to_exec_with_luit, command_to_exec); 2761d522f475Smrg } 27620bd37d32Smrg TRACE_ARGV("luit command", command_to_exec_with_luit); 27630bd37d32Smrg xtermSetenv("XTERM_FILTER", *command_to_exec_with_luit); 2764d522f475Smrg } 2765d522f475Smrg#endif 2766d522f475Smrg 27670bd37d32Smrg if_DEBUG({ 2768d522f475Smrg /* Set up stderr properly. Opening this log file cannot be 2769d522f475Smrg done securely by a privileged xterm process (although we try), 2770d522f475Smrg so the debug feature is disabled by default. */ 2771e39b573cSmrg char dbglogfile[TIMESTAMP_LEN + 20]; 2772d522f475Smrg int i = -1; 27730bd37d32Smrg timestamp_filename(dbglogfile, "xterm.debug.log."); 27740bd37d32Smrg if (creat_as(save_ruid, save_rgid, False, dbglogfile, 0600) > 0) { 27750bd37d32Smrg i = open(dbglogfile, O_WRONLY | O_TRUNC); 2776d522f475Smrg } 2777d522f475Smrg if (i >= 0) { 2778d522f475Smrg dup2(i, 2); 2779d522f475Smrg 2780d522f475Smrg /* mark this file as close on exec */ 2781d522f475Smrg (void) fcntl(i, F_SETFD, 1); 2782d522f475Smrg } 27830bd37d32Smrg }); 2784d522f475Smrg 27852e4f8982Smrg spawnXTerm(term, line_speed); 2786d522f475Smrg 2787d522f475Smrg#ifndef VMS 2788d522f475Smrg /* Child process is out there, let's catch its termination */ 2789d522f475Smrg 2790d522f475Smrg#ifdef USE_POSIX_SIGNALS 2791d522f475Smrg (void) posix_signal(SIGCHLD, reapchild); 2792d522f475Smrg#else 2793d522f475Smrg (void) signal(SIGCHLD, reapchild); 2794d522f475Smrg#endif 2795d522f475Smrg /* Realize procs have now been executed */ 2796d522f475Smrg 2797d522f475Smrg if (am_slave >= 0) { /* Write window id so master end can read and use */ 2798d522f475Smrg char buf[80]; 2799d522f475Smrg 2800d522f475Smrg buf[0] = '\0'; 2801d522f475Smrg sprintf(buf, "%lx\n", XtWindow(SHELL_OF(CURRENT_EMU()))); 280220d2c4d2Smrg IGNORE_RC(write(screen->respond, buf, strlen(buf))); 2803d522f475Smrg } 2804d522f475Smrg#ifdef AIXV3 2805d522f475Smrg#if (OSMAJORVERSION < 4) 2806d522f475Smrg /* In AIXV3, xterms started from /dev/console have CLOCAL set. 2807d522f475Smrg * This means we need to clear CLOCAL so that SIGHUP gets sent 2808d522f475Smrg * to the slave-pty process when xterm exits. 2809d522f475Smrg */ 2810d522f475Smrg 2811d522f475Smrg { 2812d522f475Smrg TERMIO_STRUCT tio; 2813d522f475Smrg 2814d522f475Smrg if (ttyGetAttr(screen->respond, &tio) == -1) 2815d522f475Smrg SysError(ERROR_TIOCGETP); 2816d522f475Smrg 2817d522f475Smrg tio.c_cflag &= ~(CLOCAL); 2818d522f475Smrg 2819d522f475Smrg if (ttySetAttr(screen->respond, &tio) == -1) 2820d522f475Smrg SysError(ERROR_TIOCSETP); 2821d522f475Smrg } 2822d522f475Smrg#endif 2823d522f475Smrg#endif 282401037d57Smrg#if defined(USE_ANY_SYSV_TERMIO) || defined(__MVS__) || defined(__minix) 2825d522f475Smrg if (0 > (mode = fcntl(screen->respond, F_GETFL, 0))) 2826d522f475Smrg SysError(ERROR_F_GETFL); 2827d522f475Smrg#ifdef O_NDELAY 2828d522f475Smrg mode |= O_NDELAY; 2829d522f475Smrg#else 2830d522f475Smrg mode |= O_NONBLOCK; 2831d522f475Smrg#endif /* O_NDELAY */ 2832d522f475Smrg if (fcntl(screen->respond, F_SETFL, mode)) 2833d522f475Smrg SysError(ERROR_F_SETFL); 2834d522f475Smrg#else /* !USE_ANY_SYSV_TERMIO */ 2835d522f475Smrg mode = 1; 2836d522f475Smrg if (ioctl(screen->respond, FIONBIO, (char *) &mode) == -1) 2837d522f475Smrg SysError(ERROR_FIONBIO); 2838d522f475Smrg#endif /* USE_ANY_SYSV_TERMIO, etc */ 2839d522f475Smrg 2840d522f475Smrg /* The erase character is used to delete the current completion */ 2841d522f475Smrg#if OPT_DABBREV 2842d522f475Smrg#ifdef TERMIO_STRUCT 2843d522f475Smrg screen->dabbrev_erase_char = d_tio.c_cc[VERASE]; 2844d522f475Smrg#else 2845d522f475Smrg screen->dabbrev_erase_char = d_sg.sg_erase; 2846d522f475Smrg#endif 2847d522f475Smrg TRACE(("set dabbrev erase_char %#x\n", screen->dabbrev_erase_char)); 2848d522f475Smrg#endif 2849d522f475Smrg 2850d522f475Smrg FD_ZERO(&pty_mask); 2851d522f475Smrg FD_ZERO(&X_mask); 2852d522f475Smrg FD_ZERO(&Select_mask); 2853d522f475Smrg FD_SET(screen->respond, &pty_mask); 2854d522f475Smrg FD_SET(ConnectionNumber(screen->display), &X_mask); 2855d522f475Smrg FD_SET(screen->respond, &Select_mask); 2856d522f475Smrg FD_SET(ConnectionNumber(screen->display), &Select_mask); 2857d522f475Smrg max_plus1 = ((screen->respond < ConnectionNumber(screen->display)) 2858d522f475Smrg ? (1 + ConnectionNumber(screen->display)) 2859d522f475Smrg : (1 + screen->respond)); 2860d522f475Smrg 2861d522f475Smrg#endif /* !VMS */ 28620bd37d32Smrg if_DEBUG({ 28630bd37d32Smrg TRACE(("debugging on pid %d\n", (int) getpid())); 28640bd37d32Smrg }); 2865d522f475Smrg XSetErrorHandler(xerror); 2866d522f475Smrg XSetIOErrorHandler(xioerror); 286701037d57Smrg#if OPT_SESSION_MGT 2868e39b573cSmrg IceSetIOErrorHandler(ice_error); 286901037d57Smrg#endif 2870d522f475Smrg 2871d522f475Smrg initPtyData(&VTbuffer); 2872d522f475Smrg#ifdef ALLOWLOGGING 2873d522f475Smrg if (term->misc.log_on) { 287420d2c4d2Smrg StartLog(term); 2875d522f475Smrg } 2876d522f475Smrg#endif 2877d522f475Smrg 28780bd37d32Smrg xtermEmbedWindow(winToEmbedInto); 2879a5ae21e4Smrg 2880a1f3da82Smrg TRACE(("checking reverseVideo before rv %s fg %s, bg %s\n", 2881a1f3da82Smrg term->misc.re_verse0 ? "reverse" : "normal", 288220d2c4d2Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_FG].resource), 288320d2c4d2Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_BG].resource))); 2884d522f475Smrg 2885a1f3da82Smrg if (term->misc.re_verse0) { 2886a1f3da82Smrg if (isDefaultForeground(TScreenOf(term)->Tcolors[TEXT_FG].resource) 2887a1f3da82Smrg && isDefaultBackground(TScreenOf(term)->Tcolors[TEXT_BG].resource)) { 2888a1f3da82Smrg TScreenOf(term)->Tcolors[TEXT_FG].resource = x_strdup(XtDefaultBackground); 2889a1f3da82Smrg TScreenOf(term)->Tcolors[TEXT_BG].resource = x_strdup(XtDefaultForeground); 2890a1f3da82Smrg } else { 2891a1f3da82Smrg ReverseVideo(term); 2892a1f3da82Smrg } 2893a1f3da82Smrg term->misc.re_verse = True; 2894a1f3da82Smrg update_reversevideo(); 2895a1f3da82Smrg TRACE(("updated reverseVideo after rv %s fg %s, bg %s\n", 2896a1f3da82Smrg term->misc.re_verse ? "reverse" : "normal", 2897a1f3da82Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_FG].resource), 2898a1f3da82Smrg NonNull(TScreenOf(term)->Tcolors[TEXT_BG].resource))); 2899a1f3da82Smrg } 2900956cc18dSsnj#if OPT_MAXIMIZE 2901956cc18dSsnj if (resource.maximized) 2902956cc18dSsnj RequestMaximize(term, True); 2903956cc18dSsnj#endif 2904d522f475Smrg for (;;) { 2905d522f475Smrg#if OPT_TEK4014 2906d522f475Smrg if (TEK4014_ACTIVE(term)) 2907d522f475Smrg TekRun(); 2908d522f475Smrg else 2909d522f475Smrg#endif 2910956cc18dSsnj VTRun(term); 2911d522f475Smrg } 2912d522f475Smrg} 2913d522f475Smrg 2914956cc18dSsnj#if defined(__osf__) || (defined(__GLIBC__) && !defined(USE_USG_PTYS)) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) 2915d522f475Smrg#define USE_OPENPTY 1 2916d522f475Smrgstatic int opened_tty = -1; 2917d522f475Smrg#endif 2918d522f475Smrg 2919d522f475Smrg/* 2920d522f475Smrg * This function opens up a pty master and stuffs its value into pty. 2921d522f475Smrg * 2922d522f475Smrg * If it finds one, it returns a value of 0. If it does not find one, 2923d522f475Smrg * it returns a value of !0. This routine is designed to be re-entrant, 2924d522f475Smrg * so that if a pty master is found and later, we find that the slave 2925d522f475Smrg * has problems, we can re-enter this function and get another one. 2926d522f475Smrg */ 2927d522f475Smrgstatic int 2928d522f475Smrgget_pty(int *pty, char *from GCC_UNUSED) 2929d522f475Smrg{ 2930d522f475Smrg int result = 1; 2931d522f475Smrg 29320bd37d32Smrg#if defined(USE_OPENPTY) 29330bd37d32Smrg result = openpty(pty, &opened_tty, ttydev, NULL, NULL); 29342e4f8982Smrg if (opened_tty >= 0) { 29352e4f8982Smrg close(opened_tty); 29362e4f8982Smrg opened_tty = -1; 29372e4f8982Smrg } 29380bd37d32Smrg#elif defined(HAVE_POSIX_OPENPT) && defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT_PTY_ISATTY) 29390bd37d32Smrg if ((*pty = posix_openpt(O_RDWR)) >= 0) { 29400bd37d32Smrg char *name = ptsname(*pty); 29410bd37d32Smrg if (name != 0) { 29420bd37d32Smrg strcpy(ttydev, name); 29430bd37d32Smrg result = 0; 29440bd37d32Smrg } 29450bd37d32Smrg } 29460bd37d32Smrg#ifdef USE_PTY_SEARCH 29470bd37d32Smrg if (result) { 29480bd37d32Smrg result = pty_search(pty); 29490bd37d32Smrg } 29500bd37d32Smrg#endif 29510bd37d32Smrg#elif defined(PUCC_PTYD) 2952d522f475Smrg result = ((*pty = openrpty(ttydev, ptydev, 2953d522f475Smrg (resource.utmpInhibit ? OPTY_NOP : OPTY_LOGIN), 2954d522f475Smrg save_ruid, from)) < 0); 2955d522f475Smrg#elif defined(__QNXNTO__) 2956d522f475Smrg result = pty_search(pty); 2957d522f475Smrg#else 2958d522f475Smrg#if defined(USE_USG_PTYS) || defined(__CYGWIN__) 2959f2e35a3aSmrg#if defined(__MVS__) 2960d522f475Smrg result = pty_search(pty); 2961d522f475Smrg#else 29620bd37d32Smrg result = ((*pty = open("/dev/ptmx", O_RDWR)) < 0); 2963d522f475Smrg#endif 29640bd37d32Smrg#if defined(SVR4) || defined(__SCO__) 29650bd37d32Smrg if (!result) 29660bd37d32Smrg strcpy(ttydev, ptsname(*pty)); 2967d522f475Smrg#endif 2968d522f475Smrg 2969d522f475Smrg#elif defined(AIXV3) 2970d522f475Smrg 2971d522f475Smrg if ((*pty = open("/dev/ptc", O_RDWR)) >= 0) { 2972d522f475Smrg strcpy(ttydev, ttyname(*pty)); 2973d522f475Smrg result = 0; 2974d522f475Smrg } 2975d522f475Smrg#elif defined(__convex__) 2976d522f475Smrg 2977d522f475Smrg char *pty_name; 2978d522f475Smrg extern char *getpty(void); 2979d522f475Smrg 2980d522f475Smrg while ((pty_name = getpty()) != NULL) { 2981d522f475Smrg if ((*pty = open(pty_name, O_RDWR)) >= 0) { 2982d522f475Smrg strcpy(ptydev, pty_name); 2983d522f475Smrg strcpy(ttydev, pty_name); 2984d522f475Smrg *x_basename(ttydev) = 't'; 2985d522f475Smrg result = 0; 2986d522f475Smrg break; 2987d522f475Smrg } 2988d522f475Smrg } 2989d522f475Smrg 2990d522f475Smrg#elif defined(sequent) 2991d522f475Smrg 2992d522f475Smrg result = ((*pty = getpseudotty(&ttydev, &ptydev)) < 0); 2993d522f475Smrg 2994d522f475Smrg#elif defined(__sgi) && (OSMAJORVERSION >= 4) 2995d522f475Smrg 2996d522f475Smrg char *tty_name; 2997d522f475Smrg 2998d522f475Smrg tty_name = _getpty(pty, O_RDWR, 0622, 0); 2999d522f475Smrg if (tty_name != 0) { 3000d522f475Smrg strcpy(ttydev, tty_name); 3001d522f475Smrg result = 0; 3002d522f475Smrg } 3003d522f475Smrg#elif (defined(__sgi) && (OSMAJORVERSION < 4)) || (defined(umips) && defined (SYSTYPE_SYSV)) 3004d522f475Smrg 3005d522f475Smrg struct stat fstat_buf; 3006d522f475Smrg 3007d522f475Smrg *pty = open("/dev/ptc", O_RDWR); 3008d522f475Smrg if (*pty >= 0 && (fstat(*pty, &fstat_buf)) >= 0) { 3009d522f475Smrg result = 0; 3010d522f475Smrg sprintf(ttydev, "/dev/ttyq%d", minor(fstat_buf.st_rdev)); 3011d522f475Smrg } 3012d522f475Smrg#elif defined(__hpux) 3013d522f475Smrg 3014d522f475Smrg /* 3015d522f475Smrg * Use the clone device if it works, otherwise use pty_search logic. 3016d522f475Smrg */ 3017d522f475Smrg if ((*pty = open("/dev/ptym/clone", O_RDWR)) >= 0) { 3018d522f475Smrg char *name = ptsname(*pty); 3019d522f475Smrg if (name != 0) { 3020d522f475Smrg strcpy(ttydev, name); 3021d522f475Smrg result = 0; 3022d522f475Smrg } else { /* permissions, or other unexpected problem */ 3023d522f475Smrg close(*pty); 3024d522f475Smrg *pty = -1; 3025d522f475Smrg result = pty_search(pty); 3026d522f475Smrg } 3027d522f475Smrg } else { 3028d522f475Smrg result = pty_search(pty); 3029d522f475Smrg } 3030d522f475Smrg 3031d522f475Smrg#else 3032d522f475Smrg 3033d522f475Smrg result = pty_search(pty); 3034d522f475Smrg 3035d522f475Smrg#endif 3036d522f475Smrg#endif 3037d522f475Smrg 3038d522f475Smrg TRACE(("get_pty(ttydev=%s, ptydev=%s) %s fd=%d\n", 3039d522f475Smrg ttydev != 0 ? ttydev : "?", 3040d522f475Smrg ptydev != 0 ? ptydev : "?", 3041d522f475Smrg result ? "FAIL" : "OK", 3042d522f475Smrg pty != 0 ? *pty : -1)); 3043d522f475Smrg return result; 3044d522f475Smrg} 3045d522f475Smrg 3046d522f475Smrgstatic void 3047e0a2b6dfSmrgset_pty_permissions(uid_t uid, unsigned gid, unsigned mode) 3048d522f475Smrg{ 3049d522f475Smrg#ifdef USE_TTY_GROUP 3050d522f475Smrg struct group *ttygrp; 3051d522f475Smrg 3052d522f475Smrg if ((ttygrp = getgrnam(TTY_GROUP_NAME)) != 0) { 3053913cc679Smrg gid = (unsigned) ttygrp->gr_gid; 3054d522f475Smrg mode &= 0660U; 3055d522f475Smrg } 3056d522f475Smrg endgrent(); 3057d522f475Smrg#endif /* USE_TTY_GROUP */ 3058d522f475Smrg 3059d522f475Smrg TRACE_IDS; 3060913cc679Smrg set_owner(ttydev, (unsigned) uid, gid, mode); 3061d522f475Smrg} 3062d522f475Smrg 3063d522f475Smrg#ifdef get_pty /* USE_UTMP_SETGID */ 3064d522f475Smrg#undef get_pty 3065d522f475Smrg/* 3066d522f475Smrg * Call the real get_pty() before relinquishing root-setuid, caching the 3067d522f475Smrg * result. 3068d522f475Smrg */ 3069d522f475Smrgstatic int 3070d522f475Smrgget_pty(int *pty, char *from) 3071d522f475Smrg{ 3072d522f475Smrg static int m_pty = -1; 3073d522f475Smrg int result = -1; 3074d522f475Smrg 3075d522f475Smrg if (pty == NULL) { 3076d522f475Smrg result = really_get_pty(&m_pty, from); 3077d522f475Smrg 3078d522f475Smrg seteuid(0); 3079d522f475Smrg set_pty_permissions(save_ruid, save_rgid, 0600U); 3080d522f475Smrg seteuid(save_ruid); 3081d522f475Smrg TRACE_IDS; 3082d522f475Smrg 3083d522f475Smrg } else if (m_pty != -1) { 3084d522f475Smrg *pty = m_pty; 3085d522f475Smrg result = 0; 3086d522f475Smrg } else { 3087d522f475Smrg result = -1; 3088d522f475Smrg } 30890bd37d32Smrg TRACE(("get_pty(ttydev=%s, ptydev=%s) %s fd=%d (utmp setgid)\n", 30900bd37d32Smrg ttydev != 0 ? ttydev : "?", 30910bd37d32Smrg ptydev != 0 ? ptydev : "?", 30920bd37d32Smrg result ? "FAIL" : "OK", 30930bd37d32Smrg pty != 0 ? *pty : -1)); 30942e4f8982Smrg#ifdef USE_OPENPTY 30952e4f8982Smrg if (opened_tty >= 0) { 30962e4f8982Smrg close(opened_tty); 30972e4f8982Smrg opened_tty = -1; 30982e4f8982Smrg } 30992e4f8982Smrg#endif 3100d522f475Smrg return result; 3101d522f475Smrg} 3102d522f475Smrg#endif 3103d522f475Smrg 3104d522f475Smrg/* 3105d522f475Smrg * Called from get_pty to iterate over likely pseudo terminals 3106d522f475Smrg * we might allocate. Used on those systems that do not have 3107d522f475Smrg * a functional interface for allocating a pty. 3108d522f475Smrg * Returns 0 if found a pty, 1 if fails. 3109d522f475Smrg */ 3110d522f475Smrg#ifdef USE_PTY_SEARCH 3111d522f475Smrgstatic int 3112d522f475Smrgpty_search(int *pty) 3113d522f475Smrg{ 3114d522f475Smrg static int devindex = 0, letter = 0; 3115d522f475Smrg 3116d522f475Smrg#if defined(CRAY) || defined(__MVS__) 3117d522f475Smrg while (devindex < MAXPTTYS) { 3118d522f475Smrg sprintf(ttydev, TTYFORMAT, devindex); 3119d522f475Smrg sprintf(ptydev, PTYFORMAT, devindex); 3120d522f475Smrg devindex++; 3121d522f475Smrg 3122d522f475Smrg TRACE(("pty_search(ttydev=%s, ptydev=%s)\n", ttydev, ptydev)); 3123d522f475Smrg if ((*pty = open(ptydev, O_RDWR)) >= 0) { 3124d522f475Smrg return 0; 3125d522f475Smrg } 3126d522f475Smrg } 3127d522f475Smrg#else /* CRAY || __MVS__ */ 3128d522f475Smrg while (PTYCHAR1[letter]) { 3129d522f475Smrg ttydev[strlen(ttydev) - 2] = 3130d522f475Smrg ptydev[strlen(ptydev) - 2] = PTYCHAR1[letter]; 3131d522f475Smrg 3132d522f475Smrg while (PTYCHAR2[devindex]) { 3133d522f475Smrg ttydev[strlen(ttydev) - 1] = 3134d522f475Smrg ptydev[strlen(ptydev) - 1] = PTYCHAR2[devindex]; 3135d522f475Smrg devindex++; 3136d522f475Smrg 3137d522f475Smrg TRACE(("pty_search(ttydev=%s, ptydev=%s)\n", ttydev, ptydev)); 3138d522f475Smrg if ((*pty = open(ptydev, O_RDWR)) >= 0) { 3139d522f475Smrg#ifdef sun 3140d522f475Smrg /* Need to check the process group of the pty. 3141d522f475Smrg * If it exists, then the slave pty is in use, 3142d522f475Smrg * and we need to get another one. 3143d522f475Smrg */ 3144d522f475Smrg int pgrp_rtn; 3145d522f475Smrg if (ioctl(*pty, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) { 3146d522f475Smrg close(*pty); 3147d522f475Smrg continue; 3148d522f475Smrg } 3149d522f475Smrg#endif /* sun */ 3150d522f475Smrg return 0; 3151d522f475Smrg } 3152d522f475Smrg } 3153d522f475Smrg devindex = 0; 3154d522f475Smrg letter++; 3155d522f475Smrg } 3156d522f475Smrg#endif /* CRAY else */ 3157d522f475Smrg /* 3158d522f475Smrg * We were unable to allocate a pty master! Return an error 3159d522f475Smrg * condition and let our caller terminate cleanly. 3160d522f475Smrg */ 3161d522f475Smrg return 1; 3162d522f475Smrg} 3163d522f475Smrg#endif /* USE_PTY_SEARCH */ 3164d522f475Smrg 3165d522f475Smrg/* 3166d522f475Smrg * The only difference in /etc/termcap between 4014 and 4015 is that 3167d522f475Smrg * the latter has support for switching character sets. We support the 3168d522f475Smrg * 4015 protocol, but ignore the character switches. Therefore, we 3169d522f475Smrg * choose 4014 over 4015. 3170d522f475Smrg * 3171d522f475Smrg * Features of the 4014 over the 4012: larger (19") screen, 12-bit 3172d522f475Smrg * graphics addressing (compatible with 4012 10-bit addressing), 3173d522f475Smrg * special point plot mode, incremental plot mode (not implemented in 3174d522f475Smrg * later Tektronix terminals), and 4 character sizes. 3175d522f475Smrg * All of these are supported by xterm. 3176d522f475Smrg */ 3177d522f475Smrg 3178d522f475Smrg#if OPT_TEK4014 317901037d57Smrgstatic const char *const tekterm[] = 3180d522f475Smrg{ 3181d522f475Smrg "tek4014", 3182d522f475Smrg "tek4015", /* 4014 with APL character set support */ 3183d522f475Smrg "tek4012", /* 4010 with lower case */ 3184d522f475Smrg "tek4013", /* 4012 with APL character set support */ 3185d522f475Smrg "tek4010", /* small screen, upper-case only */ 3186d522f475Smrg "dumb", 3187d522f475Smrg 0 3188d522f475Smrg}; 3189d522f475Smrg#endif 3190d522f475Smrg 3191d522f475Smrg/* The VT102 is a VT100 with the Advanced Video Option included standard. 3192d522f475Smrg * It also adds Escape sequences for insert/delete character/line. 3193d522f475Smrg * The VT220 adds 8-bit character sets, selective erase. 3194d522f475Smrg * The VT320 adds a 25th status line, terminal state interrogation. 3195d522f475Smrg * The VT420 has up to 48 lines on the screen. 3196d522f475Smrg */ 3197d522f475Smrg 319801037d57Smrgstatic const char *const vtterm[] = 3199d522f475Smrg{ 3200d522f475Smrg#ifdef USE_X11TERM 3201d522f475Smrg "x11term", /* for people who want special term name */ 3202d522f475Smrg#endif 3203d522f475Smrg DFT_TERMTYPE, /* for people who want special term name */ 3204f2e35a3aSmrg "xterm", /* the preferred name, should be fastest */ 3205d522f475Smrg "vt102", 3206d522f475Smrg "vt100", 3207d522f475Smrg "ansi", 3208d522f475Smrg "dumb", 3209d522f475Smrg 0 3210d522f475Smrg}; 3211d522f475Smrg 3212d522f475Smrg/* ARGSUSED */ 32130bd37d32Smrgstatic void 3214d522f475Smrghungtty(int i GCC_UNUSED) 3215d522f475Smrg{ 32160bd37d32Smrg DEBUG_MSG("handle:hungtty\n"); 3217d522f475Smrg siglongjmp(env, 1); 3218d522f475Smrg} 3219d522f475Smrg 3220d522f475Smrg#if OPT_PTY_HANDSHAKE 3221d522f475Smrg#define NO_FDS {-1, -1} 3222d522f475Smrg 3223d522f475Smrgstatic int cp_pipe[2] = NO_FDS; /* this pipe is used for child to parent transfer */ 3224d522f475Smrgstatic int pc_pipe[2] = NO_FDS; /* this pipe is used for parent to child transfer */ 3225d522f475Smrg 3226d522f475Smrgtypedef enum { /* c == child, p == parent */ 3227d522f475Smrg PTY_BAD, /* c->p: can't open pty slave for some reason */ 3228d522f475Smrg PTY_FATALERROR, /* c->p: we had a fatal error with the pty */ 3229d522f475Smrg PTY_GOOD, /* c->p: we have a good pty, let's go on */ 3230d522f475Smrg PTY_NEW, /* p->c: here is a new pty slave, try this */ 3231d522f475Smrg PTY_NOMORE, /* p->c; no more pty's, terminate */ 3232d522f475Smrg UTMP_ADDED, /* c->p: utmp entry has been added */ 3233d522f475Smrg UTMP_TTYSLOT, /* c->p: here is my ttyslot */ 3234d522f475Smrg PTY_EXEC /* p->c: window has been mapped the first time */ 3235d522f475Smrg} status_t; 3236d522f475Smrg 3237f2e35a3aSmrg#define HANDSHAKE_LEN 1024 3238f2e35a3aSmrg 3239d522f475Smrgtypedef struct { 3240d522f475Smrg status_t status; 3241d522f475Smrg int error; 3242d522f475Smrg int fatal_error; 3243d522f475Smrg int tty_slot; 3244d522f475Smrg int rows; 3245d522f475Smrg int cols; 3246f2e35a3aSmrg char buffer[HANDSHAKE_LEN]; 3247d522f475Smrg} handshake_t; 3248d522f475Smrg 3249f2e35a3aSmrg/* the buffer is large enough that we can always have a trailing null */ 3250f2e35a3aSmrg#define copy_handshake(dst, src) \ 3251f2e35a3aSmrg strncpy(dst.buffer, src, (size_t)HANDSHAKE_LEN - 1)[HANDSHAKE_LEN - 1] = '\0' 3252f2e35a3aSmrg 3253d522f475Smrg#if OPT_TRACE 3254d522f475Smrgstatic void 3255d522f475Smrgtrace_handshake(const char *tag, handshake_t * data) 3256d522f475Smrg{ 3257d522f475Smrg const char *status = "?"; 3258d522f475Smrg switch (data->status) { 3259d522f475Smrg case PTY_BAD: 3260d522f475Smrg status = "PTY_BAD"; 3261d522f475Smrg break; 3262d522f475Smrg case PTY_FATALERROR: 3263d522f475Smrg status = "PTY_FATALERROR"; 3264d522f475Smrg break; 3265d522f475Smrg case PTY_GOOD: 3266d522f475Smrg status = "PTY_GOOD"; 3267d522f475Smrg break; 3268d522f475Smrg case PTY_NEW: 3269d522f475Smrg status = "PTY_NEW"; 3270d522f475Smrg break; 3271d522f475Smrg case PTY_NOMORE: 3272d522f475Smrg status = "PTY_NOMORE"; 3273d522f475Smrg break; 3274d522f475Smrg case UTMP_ADDED: 3275d522f475Smrg status = "UTMP_ADDED"; 3276d522f475Smrg break; 3277d522f475Smrg case UTMP_TTYSLOT: 3278d522f475Smrg status = "UTMP_TTYSLOT"; 3279d522f475Smrg break; 3280d522f475Smrg case PTY_EXEC: 3281d522f475Smrg status = "PTY_EXEC"; 3282d522f475Smrg break; 3283d522f475Smrg } 3284d522f475Smrg TRACE(("handshake %s %s errno=%d, error=%d device \"%s\"\n", 3285d522f475Smrg tag, 3286d522f475Smrg status, 3287d522f475Smrg data->error, 3288d522f475Smrg data->fatal_error, 3289d522f475Smrg data->buffer)); 3290d522f475Smrg} 3291d522f475Smrg#define TRACE_HANDSHAKE(tag, data) trace_handshake(tag, data) 3292d522f475Smrg#else 3293d522f475Smrg#define TRACE_HANDSHAKE(tag, data) /* nothing */ 3294d522f475Smrg#endif 3295d522f475Smrg 3296d522f475Smrg/* HsSysError() 3297d522f475Smrg * 3298d522f475Smrg * This routine does the equivalent of a SysError but it handshakes 3299d522f475Smrg * over the errno and error exit to the master process so that it can 3300d522f475Smrg * display our error message and exit with our exit code so that the 3301d522f475Smrg * user can see it. 3302d522f475Smrg */ 3303d522f475Smrg 3304d522f475Smrgstatic void 3305d522f475SmrgHsSysError(int error) 3306d522f475Smrg{ 3307d522f475Smrg handshake_t handshake; 3308d522f475Smrg 3309d522f475Smrg memset(&handshake, 0, sizeof(handshake)); 3310d522f475Smrg handshake.status = PTY_FATALERROR; 3311d522f475Smrg handshake.error = errno; 3312d522f475Smrg handshake.fatal_error = error; 3313f2e35a3aSmrg copy_handshake(handshake, ttydev); 3314d522f475Smrg 3315d522f475Smrg if (resource.ptyHandshake && (cp_pipe[1] >= 0)) { 3316d522f475Smrg TRACE(("HsSysError errno=%d, error=%d device \"%s\"\n", 3317d522f475Smrg handshake.error, 3318d522f475Smrg handshake.fatal_error, 3319d522f475Smrg handshake.buffer)); 3320d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 332120d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], 332220d2c4d2Smrg (const char *) &handshake, 332320d2c4d2Smrg sizeof(handshake))); 3324d522f475Smrg } else { 33250bd37d32Smrg xtermWarning("fatal pty error errno=%d, error=%d device \"%s\"\n", 33260bd37d32Smrg handshake.error, 33270bd37d32Smrg handshake.fatal_error, 33280bd37d32Smrg handshake.buffer); 3329d522f475Smrg fprintf(stderr, "%s\n", SysErrorMsg(handshake.error)); 3330d522f475Smrg fprintf(stderr, "Reason: %s\n", SysReasonMsg(handshake.fatal_error)); 3331d522f475Smrg } 3332d522f475Smrg exit(error); 3333d522f475Smrg} 3334d522f475Smrg 3335d522f475Smrgvoid 3336d522f475Smrgfirst_map_occurred(void) 3337d522f475Smrg{ 3338d522f475Smrg if (resource.wait_for_map) { 3339913cc679Smrg if (pc_pipe[1] >= 0) { 3340913cc679Smrg handshake_t handshake; 3341913cc679Smrg TScreen *screen = TScreenOf(term); 3342d522f475Smrg 3343913cc679Smrg memset(&handshake, 0, sizeof(handshake)); 3344913cc679Smrg handshake.status = PTY_EXEC; 3345913cc679Smrg handshake.rows = screen->max_row; 3346913cc679Smrg handshake.cols = screen->max_col; 3347d522f475Smrg 3348913cc679Smrg TRACE(("first_map_occurred: %dx%d\n", MaxRows(screen), MaxCols(screen))); 3349d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 335020d2c4d2Smrg IGNORE_RC(write(pc_pipe[1], 335120d2c4d2Smrg (const char *) &handshake, 335220d2c4d2Smrg sizeof(handshake))); 3353d522f475Smrg close(cp_pipe[0]); 3354d522f475Smrg close(pc_pipe[1]); 3355d522f475Smrg } 3356d522f475Smrg resource.wait_for_map = False; 3357d522f475Smrg } 3358d522f475Smrg} 3359d522f475Smrg#else 3360d522f475Smrg/* 3361d522f475Smrg * temporary hack to get xterm working on att ptys 3362d522f475Smrg */ 3363d522f475Smrgstatic void 3364d522f475SmrgHsSysError(int error) 3365d522f475Smrg{ 33660bd37d32Smrg xtermWarning("fatal pty error %d (errno=%d) on tty %s\n", 33670bd37d32Smrg error, errno, ttydev); 3368d522f475Smrg exit(error); 3369d522f475Smrg} 3370d522f475Smrg#endif /* OPT_PTY_HANDSHAKE else !OPT_PTY_HANDSHAKE */ 3371d522f475Smrg 3372d522f475Smrg#ifndef VMS 3373d522f475Smrgstatic void 3374e0a2b6dfSmrgset_owner(char *device, unsigned uid, unsigned gid, unsigned mode) 3375d522f475Smrg{ 3376d522f475Smrg int why; 3377d522f475Smrg 3378d522f475Smrg TRACE_IDS; 337920d2c4d2Smrg TRACE(("set_owner(%s, uid=%d, gid=%d, mode=%#o\n", 33800bd37d32Smrg device, (int) uid, (int) gid, (unsigned) mode)); 3381d522f475Smrg 3382913cc679Smrg if (chown(device, (uid_t) uid, (gid_t) gid) < 0) { 3383d522f475Smrg why = errno; 3384d522f475Smrg if (why != ENOENT 3385d522f475Smrg && save_ruid == 0) { 33860bd37d32Smrg xtermPerror("Cannot chown %s to %ld,%ld", 33870bd37d32Smrg device, (long) uid, (long) gid); 3388d522f475Smrg } 3389d522f475Smrg TRACE(("...chown failed: %s\n", strerror(why))); 3390913cc679Smrg } else if (chmod(device, (mode_t) mode) < 0) { 3391d522f475Smrg why = errno; 3392d522f475Smrg if (why != ENOENT) { 3393d522f475Smrg struct stat sb; 3394d522f475Smrg if (stat(device, &sb) < 0) { 33950bd37d32Smrg xtermPerror("Cannot chmod %s to %03o", 33960bd37d32Smrg device, (unsigned) mode); 3397d522f475Smrg } else if (mode != (sb.st_mode & 0777U)) { 33980bd37d32Smrg xtermPerror("Cannot chmod %s to %03lo currently %03lo", 33990bd37d32Smrg device, 34000bd37d32Smrg (unsigned long) mode, 34010bd37d32Smrg (unsigned long) (sb.st_mode & 0777U)); 3402d522f475Smrg TRACE(("...stat uid=%d, gid=%d, mode=%#o\n", 34030bd37d32Smrg (int) sb.st_uid, (int) sb.st_gid, (unsigned) sb.st_mode)); 3404d522f475Smrg } 3405d522f475Smrg } 3406d522f475Smrg TRACE(("...chmod failed: %s\n", strerror(why))); 3407d522f475Smrg } 3408d522f475Smrg} 3409d522f475Smrg 3410894e0ac8Smrg/* 3411894e0ac8Smrg * utmp data may not be null-terminated; even if it is, there may be garbage 3412894e0ac8Smrg * after the null. This fills the unused part of the result with nulls. 3413894e0ac8Smrg */ 3414894e0ac8Smrgstatic void 3415894e0ac8Smrgcopy_filled(char *target, const char *source, size_t len) 3416894e0ac8Smrg{ 3417894e0ac8Smrg size_t used = 0; 3418894e0ac8Smrg while (used < len) { 3419894e0ac8Smrg if ((target[used] = source[used]) == 0) 3420894e0ac8Smrg break; 3421894e0ac8Smrg ++used; 3422894e0ac8Smrg } 3423894e0ac8Smrg while (used < len) { 3424894e0ac8Smrg target[used++] = '\0'; 3425894e0ac8Smrg } 3426894e0ac8Smrg} 3427894e0ac8Smrg 3428d522f475Smrg#if defined(HAVE_UTMP) && defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 3429d522f475Smrg/* 3430d522f475Smrg * getutid() only looks at ut_type and ut_id. 3431d522f475Smrg * But we'll also check ut_line in find_utmp(). 3432d522f475Smrg */ 3433d522f475Smrgstatic void 3434d522f475Smrginit_utmp(int type, struct UTMP_STR *tofind) 3435d522f475Smrg{ 3436d522f475Smrg memset(tofind, 0, sizeof(*tofind)); 3437913cc679Smrg tofind->ut_type = (short) type; 3438894e0ac8Smrg copy_filled(tofind->ut_id, my_utmp_id(ttydev), sizeof(tofind->ut_id)); 3439894e0ac8Smrg copy_filled(tofind->ut_line, my_pty_name(ttydev), sizeof(tofind->ut_line)); 3440d522f475Smrg} 3441d522f475Smrg 3442d522f475Smrg/* 3443d522f475Smrg * We could use getutline() if we didn't support old systems. 3444d522f475Smrg */ 3445d522f475Smrgstatic struct UTMP_STR * 3446d522f475Smrgfind_utmp(struct UTMP_STR *tofind) 3447d522f475Smrg{ 3448d522f475Smrg struct UTMP_STR *result; 34490bd37d32Smrg struct UTMP_STR limited; 3450d522f475Smrg struct UTMP_STR working; 3451d522f475Smrg 3452d522f475Smrg for (;;) { 3453d522f475Smrg memset(&working, 0, sizeof(working)); 3454d522f475Smrg working.ut_type = tofind->ut_type; 3455894e0ac8Smrg copy_filled(working.ut_id, tofind->ut_id, sizeof(tofind->ut_id)); 3456d522f475Smrg#if defined(__digital__) && defined(__unix__) && (defined(OSMAJORVERSION) && OSMAJORVERSION < 5) 3457d522f475Smrg working.ut_type = 0; 3458d522f475Smrg#endif 3459d522f475Smrg if ((result = call_getutid(&working)) == 0) 3460d522f475Smrg break; 3461894e0ac8Smrg copy_filled(limited.ut_line, result->ut_line, sizeof(result->ut_line)); 34620bd37d32Smrg if (!memcmp(limited.ut_line, tofind->ut_line, sizeof(limited.ut_line))) 3463d522f475Smrg break; 3464d522f475Smrg /* 3465d522f475Smrg * Solaris, IRIX64 and HPUX manpages say to fill the static area 3466d522f475Smrg * pointed to by the return-value to zeros if searching for multiple 3467d522f475Smrg * occurrences. Otherwise it will continue to return the same value. 3468d522f475Smrg */ 3469d522f475Smrg memset(result, 0, sizeof(*result)); 3470d522f475Smrg } 3471d522f475Smrg return result; 3472d522f475Smrg} 3473d522f475Smrg#endif /* HAVE_UTMP... */ 3474d522f475Smrg 3475d522f475Smrg#define close_fd(fd) close(fd), fd = -1 3476d522f475Smrg 347720d2c4d2Smrg#if defined(TIOCNOTTY) && (!defined(__GLIBC__) || (__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))) 347820d2c4d2Smrg#define USE_NO_DEV_TTY 1 347920d2c4d2Smrg#else 348020d2c4d2Smrg#define USE_NO_DEV_TTY 0 348120d2c4d2Smrg#endif 348220d2c4d2Smrg 3483e0a2b6dfSmrgstatic int 3484e0a2b6dfSmrgsame_leaf(char *a, char *b) 3485e0a2b6dfSmrg{ 3486e0a2b6dfSmrg char *p = x_basename(a); 3487e0a2b6dfSmrg char *q = x_basename(b); 3488e0a2b6dfSmrg return !strcmp(p, q); 3489e0a2b6dfSmrg} 3490e0a2b6dfSmrg 3491e0a2b6dfSmrg/* 3492e0a2b6dfSmrg * "good enough" (inode wouldn't port to Cygwin) 3493e0a2b6dfSmrg */ 3494e0a2b6dfSmrgstatic int 3495e0a2b6dfSmrgsame_file(const char *a, const char *b) 3496e0a2b6dfSmrg{ 3497e0a2b6dfSmrg struct stat asb; 3498e0a2b6dfSmrg struct stat bsb; 3499e0a2b6dfSmrg int result = 0; 3500e0a2b6dfSmrg 3501e0a2b6dfSmrg if ((stat(a, &asb) == 0) 3502e0a2b6dfSmrg && (stat(b, &bsb) == 0) 3503e0a2b6dfSmrg && ((asb.st_mode & S_IFMT) == S_IFREG) 3504e0a2b6dfSmrg && ((bsb.st_mode & S_IFMT) == S_IFREG) 3505e0a2b6dfSmrg && (asb.st_mtime == bsb.st_mtime) 3506e0a2b6dfSmrg && (asb.st_size == bsb.st_size)) { 3507e0a2b6dfSmrg result = 1; 3508e0a2b6dfSmrg } 3509e0a2b6dfSmrg return result; 3510e0a2b6dfSmrg} 3511e0a2b6dfSmrg 3512f2e35a3aSmrgstatic int 3513f2e35a3aSmrgfindValidShell(const char *haystack, const char *needle) 3514f2e35a3aSmrg{ 3515f2e35a3aSmrg int result = -1; 3516f2e35a3aSmrg int count = -1; 3517f2e35a3aSmrg const char *s, *t; 3518f2e35a3aSmrg size_t have; 3519f2e35a3aSmrg size_t want = strlen(needle); 3520f2e35a3aSmrg 3521f2e35a3aSmrg TRACE(("findValidShell:\n%s\n", NonNull(haystack))); 3522f2e35a3aSmrg 3523f2e35a3aSmrg for (s = haystack; (s != 0) && (*s != '\0'); s = t) { 3524f2e35a3aSmrg ++count; 3525f2e35a3aSmrg if ((t = strchr(s, '\n')) == 0) { 3526f2e35a3aSmrg t = s + strlen(s); 3527f2e35a3aSmrg } 3528f2e35a3aSmrg have = (size_t) (t - s); 3529f2e35a3aSmrg 3530f2e35a3aSmrg if ((have >= want) && (*s != '#')) { 3531f2e35a3aSmrg char *p = malloc(have + 1); 3532f2e35a3aSmrg 3533f2e35a3aSmrg if (p != 0) { 3534f2e35a3aSmrg char *q; 3535f2e35a3aSmrg 3536f2e35a3aSmrg memcpy(p, s, have); 3537f2e35a3aSmrg p[have] = '\0'; 3538f2e35a3aSmrg if ((q = x_strtrim(p)) != 0) { 3539f2e35a3aSmrg TRACE(("...test %s\n", q)); 3540f2e35a3aSmrg if (!strcmp(q, needle)) { 3541f2e35a3aSmrg result = count; 3542f2e35a3aSmrg } else if (same_leaf(q, (char *) needle) && 3543f2e35a3aSmrg same_file(q, needle)) { 3544f2e35a3aSmrg result = count; 3545f2e35a3aSmrg } 3546f2e35a3aSmrg free(q); 3547f2e35a3aSmrg } 3548f2e35a3aSmrg free(p); 3549f2e35a3aSmrg } 3550f2e35a3aSmrg if (result >= 0) 3551f2e35a3aSmrg break; 3552f2e35a3aSmrg } 3553f2e35a3aSmrg while (*t == '\n') { 3554f2e35a3aSmrg ++t; 3555f2e35a3aSmrg } 3556f2e35a3aSmrg } 3557f2e35a3aSmrg return result; 3558f2e35a3aSmrg} 3559f2e35a3aSmrg 3560f2e35a3aSmrgstatic int 3561f2e35a3aSmrgourValidShell(const char *pathname) 3562f2e35a3aSmrg{ 3563f2e35a3aSmrg return findValidShell(x_strtrim(resource.valid_shells), pathname); 3564f2e35a3aSmrg} 3565f2e35a3aSmrg 3566f2e35a3aSmrg#if defined(HAVE_GETUSERSHELL) && defined(HAVE_ENDUSERSHELL) 3567f2e35a3aSmrgstatic Boolean 3568f2e35a3aSmrgvalidShell(const char *pathname) 3569f2e35a3aSmrg{ 3570f2e35a3aSmrg int result = -1; 3571f2e35a3aSmrg 3572f2e35a3aSmrg if (validProgram(pathname)) { 3573f2e35a3aSmrg char *q; 3574f2e35a3aSmrg int count = -1; 3575f2e35a3aSmrg 3576f2e35a3aSmrg TRACE(("validShell:getusershell\n")); 3577f2e35a3aSmrg while ((q = getusershell()) != 0) { 3578f2e35a3aSmrg ++count; 3579f2e35a3aSmrg TRACE(("...test \"%s\"\n", q)); 3580f2e35a3aSmrg if (!strcmp(q, pathname)) { 3581f2e35a3aSmrg result = count; 3582f2e35a3aSmrg break; 3583f2e35a3aSmrg } 3584f2e35a3aSmrg } 3585f2e35a3aSmrg endusershell(); 3586f2e35a3aSmrg 3587f2e35a3aSmrg if (result < 0) 3588f2e35a3aSmrg result = ourValidShell(pathname); 3589f2e35a3aSmrg } 3590f2e35a3aSmrg 3591f2e35a3aSmrg TRACE(("validShell %s ->%d\n", NonNull(pathname), result)); 3592f2e35a3aSmrg return (result >= 0); 3593f2e35a3aSmrg} 3594f2e35a3aSmrg#else 3595e0a2b6dfSmrg/* 3596e0a2b6dfSmrg * Only set $SHELL for paths found in the standard location. 3597e0a2b6dfSmrg */ 3598e0a2b6dfSmrgstatic Boolean 3599e0a2b6dfSmrgvalidShell(const char *pathname) 3600e0a2b6dfSmrg{ 3601f2e35a3aSmrg int result = -1; 3602e0a2b6dfSmrg const char *ok_shells = "/etc/shells"; 3603e0a2b6dfSmrg char *blob; 3604e0a2b6dfSmrg struct stat sb; 3605e0a2b6dfSmrg size_t rc; 3606e0a2b6dfSmrg FILE *fp; 3607e0a2b6dfSmrg 3608f2e35a3aSmrg if (validProgram(pathname)) { 3609f2e35a3aSmrg 3610f2e35a3aSmrg TRACE(("validShell:%s\n", ok_shells)); 3611f2e35a3aSmrg 3612f2e35a3aSmrg if (stat(ok_shells, &sb) == 0 3613f2e35a3aSmrg && (sb.st_mode & S_IFMT) == S_IFREG 3614f2e35a3aSmrg && ((size_t) sb.st_size > 0) 3615f2e35a3aSmrg && ((size_t) sb.st_size < (((size_t) ~0) - 2)) 3616f2e35a3aSmrg && (blob = calloc((size_t) sb.st_size + 2, sizeof(char))) != 0) { 3617f2e35a3aSmrg 3618f2e35a3aSmrg if ((fp = fopen(ok_shells, "r")) != 0) { 3619f2e35a3aSmrg rc = fread(blob, sizeof(char), (size_t) sb.st_size, fp); 3620f2e35a3aSmrg fclose(fp); 3621f2e35a3aSmrg 3622f2e35a3aSmrg if (rc == (size_t) sb.st_size) { 3623f2e35a3aSmrg blob[rc] = '\0'; 3624f2e35a3aSmrg result = findValidShell(blob, pathname); 3625e0a2b6dfSmrg } 3626e0a2b6dfSmrg } 3627f2e35a3aSmrg free(blob); 3628e0a2b6dfSmrg } 3629f2e35a3aSmrg if (result < 0) 3630f2e35a3aSmrg result = ourValidShell(pathname); 3631e0a2b6dfSmrg } 3632e0a2b6dfSmrg TRACE(("validShell %s ->%d\n", NonNull(pathname), result)); 3633f2e35a3aSmrg return (result > 0); 3634e0a2b6dfSmrg} 3635f2e35a3aSmrg#endif 3636e0a2b6dfSmrg 3637e0a2b6dfSmrgstatic char * 3638e0a2b6dfSmrgresetShell(char *oldPath) 3639e0a2b6dfSmrg{ 3640e0a2b6dfSmrg char *newPath = x_strdup("/bin/sh"); 3641e0a2b6dfSmrg char *envPath = getenv("SHELL"); 3642f2e35a3aSmrg free(oldPath); 3643e0a2b6dfSmrg if (!IsEmpty(envPath)) 3644e0a2b6dfSmrg xtermSetenv("SHELL", newPath); 3645e0a2b6dfSmrg return newPath; 3646e0a2b6dfSmrg} 3647e0a2b6dfSmrg 36484419d26bSmrg/* 36494419d26bSmrg * Trim unwanted environment variables: 36504419d26bSmrg * 36514419d26bSmrg * DESKTOP_STARTUP_ID 36524419d26bSmrg * standards.freedesktop.org/startup-notification-spec/ 36534419d26bSmrg * notes that this variable is used when a "reliable" mechanism is 36544419d26bSmrg * not available; in practice it must be unset to avoid confusing 36554419d26bSmrg * GTK applications. 36564419d26bSmrg * 36574419d26bSmrg * XCURSOR_PATH 36584419d26bSmrg * We set this temporarily to work around poor design of Xcursor. Unset it 36594419d26bSmrg * here to avoid confusion. 36604419d26bSmrg * 36614419d26bSmrg * Other... 36624419d26bSmrg * These are set by other terminal emulators or non-standard libraries, and are 36634419d26bSmrg * a nuisance if one starts xterm from a shell inside one of those. 36644419d26bSmrg */ 36654419d26bSmrgstatic void 36664419d26bSmrgxtermTrimEnv(void) 36674419d26bSmrg{ 36684419d26bSmrg#define DATA(wild,name) { wild, #name } 36694419d26bSmrg static struct { 36704419d26bSmrg int wild; 36714419d26bSmrg const char *name; 36724419d26bSmrg } table[] = { 36734419d26bSmrg DATA(0, DEFAULT_COLORS), 36744419d26bSmrg DATA(0, DESKTOP_STARTUP_ID), 36754419d26bSmrg DATA(0, WCWIDTH_CJK_LEGACY), 36764419d26bSmrg DATA(0, XCURSOR_PATH), 36774419d26bSmrg DATA(1, COLORFGBG), 36784419d26bSmrg DATA(1, COLORTERM), 36794419d26bSmrg DATA(1, ITERM2_), 36804419d26bSmrg DATA(1, MC_), 36814419d26bSmrg DATA(1, PUTTY), 36824419d26bSmrg DATA(1, RXVT_), 36834419d26bSmrg DATA(1, URXVT_), 36844419d26bSmrg DATA(1, VTE_), 36854419d26bSmrg }; 36864419d26bSmrg#undef DATA 36874419d26bSmrg Cardinal n; 36884419d26bSmrg 36894419d26bSmrg for (n = 0; n < XtNumber(table); ++n) { 36904419d26bSmrg int s; 36914419d26bSmrg if (table[n].wild) { 36924419d26bSmrg size_t srclen = strlen(table[n].name); 36934419d26bSmrg for (s = 0; environ[s] != NULL; ++s) { 36944419d26bSmrg size_t dstlen = strlen(environ[s]); 36954419d26bSmrg if (dstlen > srclen) { 36964419d26bSmrg char *dstend = strchr(environ[s], '='); 36974419d26bSmrg char *my_var; 36984419d26bSmrg if (dstend != NULL && 36994419d26bSmrg (dstlen = (size_t) (dstend - environ[s])) >= srclen && 37004419d26bSmrg !strncmp(table[n].name, environ[s], dstlen) && 37014419d26bSmrg (my_var = x_strdup(environ[s])) != NULL) { 37024419d26bSmrg my_var[dstlen] = '\0'; 37034419d26bSmrg xtermUnsetenv(my_var); 37044419d26bSmrg free(my_var); 37054419d26bSmrg } 37064419d26bSmrg } 37074419d26bSmrg } 37084419d26bSmrg } else if (getenv(table[n].name) != NULL) { 37094419d26bSmrg xtermUnsetenv(table[n].name); 37104419d26bSmrg } 37114419d26bSmrg } 37124419d26bSmrg} 37134419d26bSmrg 3714d522f475Smrg/* 3715d522f475Smrg * Inits pty and tty and forks a login process. 3716d522f475Smrg * Does not close fd Xsocket. 3717d522f475Smrg * If slave, the pty named in passedPty is already open for use 3718d522f475Smrg */ 3719d522f475Smrgstatic int 37202e4f8982SmrgspawnXTerm(XtermWidget xw, unsigned line_speed) 3721d522f475Smrg{ 3722d522f475Smrg TScreen *screen = TScreenOf(xw); 3723d522f475Smrg Cardinal nn; 3724d522f475Smrg#if OPT_PTY_HANDSHAKE 3725d522f475Smrg Bool got_handshake_size = False; 3726d522f475Smrg handshake_t handshake; 3727d522f475Smrg int done; 3728d522f475Smrg#endif 3729d522f475Smrg#if OPT_INITIAL_ERASE 3730d522f475Smrg int initial_erase = VAL_INITIAL_ERASE; 3731d522f475Smrg Bool setInitialErase; 3732d522f475Smrg#endif 3733d522f475Smrg int rc = 0; 3734d522f475Smrg int ttyfd = -1; 3735d522f475Smrg Bool ok_termcap; 3736d522f475Smrg char *newtc; 3737d522f475Smrg 3738d522f475Smrg#ifdef TERMIO_STRUCT 3739d522f475Smrg TERMIO_STRUCT tio; 3740d522f475Smrg#ifdef __MVS__ 3741d522f475Smrg TERMIO_STRUCT gio; 3742d522f475Smrg#endif /* __MVS__ */ 3743d522f475Smrg#ifdef TIOCLSET 3744d522f475Smrg unsigned lmode; 3745d522f475Smrg#endif /* TIOCLSET */ 3746d522f475Smrg#ifdef HAS_LTCHARS 3747d522f475Smrg struct ltchars ltc; 3748d522f475Smrg#endif /* HAS_LTCHARS */ 3749d522f475Smrg#else /* !TERMIO_STRUCT */ 3750d522f475Smrg int ldisc = 0; 3751d522f475Smrg int discipline; 3752d522f475Smrg unsigned lmode; 3753d522f475Smrg struct tchars tc; 3754d522f475Smrg struct ltchars ltc; 3755d522f475Smrg struct sgttyb sg; 3756d522f475Smrg#ifdef sony 3757d522f475Smrg int jmode; 3758d522f475Smrg struct jtchars jtc; 3759d522f475Smrg#endif /* sony */ 3760d522f475Smrg#endif /* TERMIO_STRUCT */ 3761d522f475Smrg 37620bd37d32Smrg char *shell_path = 0; 37630bd37d32Smrg char *shname, *shname_minus; 376420d2c4d2Smrg int i; 376520d2c4d2Smrg#if USE_NO_DEV_TTY 376620d2c4d2Smrg int no_dev_tty = False; 376720d2c4d2Smrg#endif 376801037d57Smrg const char *const *envnew; /* new environment */ 3769d522f475Smrg char buf[64]; 3770d522f475Smrg char *TermName = NULL; 3771d522f475Smrg#ifdef TTYSIZE_STRUCT 3772d522f475Smrg TTYSIZE_STRUCT ts; 3773d522f475Smrg#endif 37740bd37d32Smrg struct passwd pw; 3775d522f475Smrg char *login_name = NULL; 3776d522f475Smrg#ifndef USE_UTEMPTER 3777d522f475Smrg#ifdef HAVE_UTMP 3778d522f475Smrg struct UTMP_STR utmp; 3779d522f475Smrg#ifdef USE_SYSV_UTMP 3780d522f475Smrg struct UTMP_STR *utret = NULL; 3781d522f475Smrg#endif 3782d522f475Smrg#ifdef USE_LASTLOG 3783d522f475Smrg struct lastlog lastlog; 3784d522f475Smrg#endif 3785d522f475Smrg#ifdef USE_LASTLOGX 3786d522f475Smrg struct lastlogx lastlogx; 3787d522f475Smrg#endif /* USE_LASTLOG */ 3788d522f475Smrg#endif /* HAVE_UTMP */ 3789d522f475Smrg#endif /* !USE_UTEMPTER */ 3790d522f475Smrg 3791e39b573cSmrg#if OPT_TRACE 3792e39b573cSmrg unsigned long xterm_parent = (unsigned long) getpid(); 3793e39b573cSmrg#endif 3794e39b573cSmrg 3795d522f475Smrg /* Noisy compilers (suppress some unused-variable warnings) */ 3796d522f475Smrg (void) rc; 3797d522f475Smrg#if defined(HAVE_UTMP) && defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER) 3798d522f475Smrg (void) utret; 3799d522f475Smrg#endif 3800d522f475Smrg 3801d522f475Smrg screen->uid = save_ruid; 3802d522f475Smrg screen->gid = save_rgid; 3803d522f475Smrg 3804d522f475Smrg#ifdef SIGTTOU 3805d522f475Smrg /* so that TIOCSWINSZ || TIOCSIZE doesn't block */ 3806d522f475Smrg signal(SIGTTOU, SIG_IGN); 3807d522f475Smrg#endif 3808d522f475Smrg 3809d522f475Smrg#if OPT_PTY_HANDSHAKE 3810d522f475Smrg memset(&handshake, 0, sizeof(handshake)); 3811d522f475Smrg#endif 3812d522f475Smrg 3813d522f475Smrg if (am_slave >= 0) { 3814d522f475Smrg screen->respond = am_slave; 3815d522f475Smrg set_pty_id(ttydev, passedPty); 3816d522f475Smrg#ifdef USE_PTY_DEVICE 3817d522f475Smrg set_pty_id(ptydev, passedPty); 3818d522f475Smrg#endif 3819d522f475Smrg if (xtermResetIds(screen) < 0) 3820d522f475Smrg exit(1); 3821d522f475Smrg } else { 3822d522f475Smrg Bool tty_got_hung; 3823d522f475Smrg 3824d522f475Smrg /* 3825d522f475Smrg * Sometimes /dev/tty hangs on open (as in the case of a pty 3826d522f475Smrg * that has gone away). Simply make up some reasonable 3827d522f475Smrg * defaults. 3828d522f475Smrg */ 3829d522f475Smrg 3830d522f475Smrg if (!sigsetjmp(env, 1)) { 3831913cc679Smrg signal(SIGALRM, hungtty); 3832913cc679Smrg alarm(2); /* alarm(1) might return too soon */ 3833d522f475Smrg ttyfd = open("/dev/tty", O_RDWR); 3834d522f475Smrg alarm(0); 3835d522f475Smrg tty_got_hung = False; 3836d522f475Smrg } else { 3837d522f475Smrg tty_got_hung = True; 3838d522f475Smrg ttyfd = -1; 3839d522f475Smrg errno = ENXIO; 3840d522f475Smrg } 38412e4f8982Smrg shell_path = 0; 38420bd37d32Smrg memset(&pw, 0, sizeof(pw)); 3843d522f475Smrg#if OPT_PTY_HANDSHAKE 3844d522f475Smrg got_handshake_size = False; 3845d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 3846d522f475Smrg#if OPT_INITIAL_ERASE 3847d522f475Smrg initial_erase = VAL_INITIAL_ERASE; 3848d522f475Smrg#endif 3849d522f475Smrg signal(SIGALRM, SIG_DFL); 3850d522f475Smrg 3851d522f475Smrg /* 3852d522f475Smrg * Check results and ignore current control terminal if 3853d522f475Smrg * necessary. ENXIO is what is normally returned if there is 3854d522f475Smrg * no controlling terminal, but some systems (e.g. SunOS 4.0) 3855d522f475Smrg * seem to return EIO. Solaris 2.3 is said to return EINVAL. 38560bd37d32Smrg * Cygwin returns ENOENT. FreeBSD can return ENOENT, especially 38570bd37d32Smrg * if xterm is run within a jail. 3858d522f475Smrg */ 385920d2c4d2Smrg#if USE_NO_DEV_TTY 3860d522f475Smrg no_dev_tty = False; 386120d2c4d2Smrg#endif 3862d522f475Smrg if (ttyfd < 0) { 3863d522f475Smrg if (tty_got_hung || errno == ENXIO || errno == EIO || 38640bd37d32Smrg errno == ENOENT || 3865d522f475Smrg#ifdef ENODEV 3866d522f475Smrg errno == ENODEV || 3867d522f475Smrg#endif 3868d522f475Smrg errno == EINVAL || errno == ENOTTY || errno == EACCES) { 386920d2c4d2Smrg#if USE_NO_DEV_TTY 3870d522f475Smrg no_dev_tty = True; 387120d2c4d2Smrg#endif 3872d522f475Smrg#ifdef HAS_LTCHARS 3873d522f475Smrg ltc = d_ltc; 3874d522f475Smrg#endif /* HAS_LTCHARS */ 3875d522f475Smrg#ifdef TIOCLSET 3876d522f475Smrg lmode = d_lmode; 3877d522f475Smrg#endif /* TIOCLSET */ 3878d522f475Smrg#ifdef TERMIO_STRUCT 3879d522f475Smrg tio = d_tio; 3880d522f475Smrg#else /* !TERMIO_STRUCT */ 3881d522f475Smrg sg = d_sg; 3882d522f475Smrg tc = d_tc; 3883d522f475Smrg discipline = d_disipline; 3884d522f475Smrg#ifdef sony 3885d522f475Smrg jmode = d_jmode; 3886d522f475Smrg jtc = d_jtc; 3887d522f475Smrg#endif /* sony */ 3888d522f475Smrg#endif /* TERMIO_STRUCT */ 3889d522f475Smrg } else { 3890d522f475Smrg SysError(ERROR_OPDEVTTY); 3891d522f475Smrg } 3892d522f475Smrg } else { 3893d522f475Smrg 3894d522f475Smrg /* Get a copy of the current terminal's state, 3895d522f475Smrg * if we can. Some systems (e.g., SVR4 and MacII) 3896d522f475Smrg * may not have a controlling terminal at this point 3897d522f475Smrg * if started directly from xdm or xinit, 3898d522f475Smrg * in which case we just use the defaults as above. 3899d522f475Smrg */ 3900d522f475Smrg#ifdef HAS_LTCHARS 3901d522f475Smrg if (ioctl(ttyfd, TIOCGLTC, <c) == -1) 3902d522f475Smrg ltc = d_ltc; 3903d522f475Smrg#endif /* HAS_LTCHARS */ 3904d522f475Smrg#ifdef TIOCLSET 3905d522f475Smrg if (ioctl(ttyfd, TIOCLGET, &lmode) == -1) 3906d522f475Smrg lmode = d_lmode; 3907d522f475Smrg#endif /* TIOCLSET */ 3908d522f475Smrg#ifdef TERMIO_STRUCT 390920d2c4d2Smrg rc = ttyGetAttr(ttyfd, &tio); 391020d2c4d2Smrg if (rc == -1) 3911d522f475Smrg tio = d_tio; 3912d522f475Smrg#else /* !TERMIO_STRUCT */ 391320d2c4d2Smrg rc = ioctl(ttyfd, TIOCGETP, (char *) &sg); 391420d2c4d2Smrg if (rc == -1) 3915d522f475Smrg sg = d_sg; 3916d522f475Smrg if (ioctl(ttyfd, TIOCGETC, (char *) &tc) == -1) 3917d522f475Smrg tc = d_tc; 3918d522f475Smrg if (ioctl(ttyfd, TIOCGETD, (char *) &discipline) == -1) 3919d522f475Smrg discipline = d_disipline; 3920d522f475Smrg#ifdef sony 3921d522f475Smrg if (ioctl(ttyfd, TIOCKGET, (char *) &jmode) == -1) 3922d522f475Smrg jmode = d_jmode; 3923d522f475Smrg if (ioctl(ttyfd, TIOCKGETC, (char *) &jtc) == -1) 3924d522f475Smrg jtc = d_jtc; 3925d522f475Smrg#endif /* sony */ 3926d522f475Smrg#endif /* TERMIO_STRUCT */ 3927d522f475Smrg 3928d522f475Smrg /* 3929d522f475Smrg * If ptyInitialErase is set, we want to get the pty's 3930d522f475Smrg * erase value. Just in case that will fail, first get 3931d522f475Smrg * the value from /dev/tty, so we will have something 3932d522f475Smrg * at least. 3933d522f475Smrg */ 3934d522f475Smrg#if OPT_INITIAL_ERASE 3935d522f475Smrg if (resource.ptyInitialErase) { 3936d522f475Smrg#ifdef TERMIO_STRUCT 3937d522f475Smrg initial_erase = tio.c_cc[VERASE]; 3938d522f475Smrg#else /* !TERMIO_STRUCT */ 3939d522f475Smrg initial_erase = sg.sg_erase; 3940d522f475Smrg#endif /* TERMIO_STRUCT */ 3941d522f475Smrg TRACE(("%s initial_erase:%d (from /dev/tty)\n", 3942d522f475Smrg rc == 0 ? "OK" : "FAIL", 3943d522f475Smrg initial_erase)); 3944d522f475Smrg } 3945d522f475Smrg#endif 3946d522f475Smrg#ifdef __MVS__ 3947d522f475Smrg if (ttyGetAttr(ttyfd, &gio) == 0) { 3948d522f475Smrg gio.c_cflag &= ~(HUPCL | PARENB); 3949d522f475Smrg ttySetAttr(ttyfd, &gio); 3950d522f475Smrg } 3951d522f475Smrg#endif /* __MVS__ */ 3952d522f475Smrg 3953d522f475Smrg close_fd(ttyfd); 3954d522f475Smrg } 3955d522f475Smrg 3956d522f475Smrg if (get_pty(&screen->respond, XDisplayString(screen->display))) { 3957d522f475Smrg SysError(ERROR_PTYS); 3958d522f475Smrg } 3959913cc679Smrg TRACE_GET_TTYSIZE(screen->respond, "after get_pty"); 3960d522f475Smrg#if OPT_INITIAL_ERASE 3961d522f475Smrg if (resource.ptyInitialErase) { 3962d522f475Smrg#ifdef TERMIO_STRUCT 3963d522f475Smrg TERMIO_STRUCT my_tio; 396420d2c4d2Smrg rc = ttyGetAttr(screen->respond, &my_tio); 396520d2c4d2Smrg if (rc == 0) 3966d522f475Smrg initial_erase = my_tio.c_cc[VERASE]; 3967d522f475Smrg#else /* !TERMIO_STRUCT */ 3968d522f475Smrg struct sgttyb my_sg; 396920d2c4d2Smrg rc = ioctl(screen->respond, TIOCGETP, (char *) &my_sg); 397020d2c4d2Smrg if (rc == 0) 3971d522f475Smrg initial_erase = my_sg.sg_erase; 3972d522f475Smrg#endif /* TERMIO_STRUCT */ 3973d522f475Smrg TRACE(("%s initial_erase:%d (from pty)\n", 3974d522f475Smrg (rc == 0) ? "OK" : "FAIL", 3975d522f475Smrg initial_erase)); 3976d522f475Smrg } 3977d522f475Smrg#endif /* OPT_INITIAL_ERASE */ 3978d522f475Smrg } 3979d522f475Smrg 3980d522f475Smrg /* avoid double MapWindow requests */ 3981d522f475Smrg XtSetMappedWhenManaged(SHELL_OF(CURRENT_EMU()), False); 3982d522f475Smrg 3983d522f475Smrg wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", 3984d522f475Smrg False); 3985d522f475Smrg 3986d522f475Smrg if (!TEK4014_ACTIVE(xw)) 3987956cc18dSsnj VTInit(xw); /* realize now so know window size for tty driver */ 3988d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 3989d522f475Smrg if (Console) { 3990d522f475Smrg /* 3991d522f475Smrg * Inform any running xconsole program 3992d522f475Smrg * that we are going to steal the console. 3993d522f475Smrg */ 3994d522f475Smrg XmuGetHostname(mit_console_name + MIT_CONSOLE_LEN, 255); 3995d522f475Smrg mit_console = XInternAtom(screen->display, mit_console_name, False); 3996d522f475Smrg /* the user told us to be the console, so we can use CurrentTime */ 3997d522f475Smrg XtOwnSelection(SHELL_OF(CURRENT_EMU()), 3998d522f475Smrg mit_console, CurrentTime, 3999d522f475Smrg ConvertConsoleSelection, NULL, NULL); 4000d522f475Smrg } 4001d522f475Smrg#endif 4002d522f475Smrg#if OPT_TEK4014 4003d522f475Smrg if (TEK4014_ACTIVE(xw)) { 4004d522f475Smrg envnew = tekterm; 4005d522f475Smrg } else 4006d522f475Smrg#endif 4007d522f475Smrg { 4008d522f475Smrg envnew = vtterm; 4009d522f475Smrg } 4010d522f475Smrg 4011d522f475Smrg /* 4012d522f475Smrg * This used to exit if no termcap entry was found for the specified 4013d522f475Smrg * terminal name. That's a little unfriendly, so instead we'll allow 4014d522f475Smrg * the program to proceed (but not to set $TERMCAP) if the termcap 4015d522f475Smrg * entry is not found. 4016d522f475Smrg */ 4017d522f475Smrg ok_termcap = True; 401820d2c4d2Smrg if (!get_termcap(xw, TermName = resource.term_name)) { 401920d2c4d2Smrg const char *last = NULL; 402020d2c4d2Smrg char *next; 402120d2c4d2Smrg 402220d2c4d2Smrg TermName = x_strdup(*envnew); 4023d522f475Smrg ok_termcap = False; 4024d522f475Smrg while (*envnew != NULL) { 402520d2c4d2Smrg if (last == NULL || strcmp(last, *envnew)) { 402620d2c4d2Smrg next = x_strdup(*envnew); 402720d2c4d2Smrg if (get_termcap(xw, next)) { 402820d2c4d2Smrg free(TermName); 402920d2c4d2Smrg TermName = next; 40300bd37d32Smrg ok_termcap = True + 1; 403120d2c4d2Smrg break; 403220d2c4d2Smrg } else { 403320d2c4d2Smrg free(next); 403420d2c4d2Smrg } 4035d522f475Smrg } 4036d522f475Smrg last = *envnew; 4037d522f475Smrg envnew++; 4038d522f475Smrg } 4039d522f475Smrg } 4040d522f475Smrg if (ok_termcap) { 4041f2e35a3aSmrg resource.term_name = x_strdup(TermName); 404220d2c4d2Smrg resize_termcap(xw); 4043d522f475Smrg } 4044d522f475Smrg 4045d522f475Smrg /* 4046d522f475Smrg * Check if ptyInitialErase is not set. If so, we rely on the termcap 4047d522f475Smrg * (or terminfo) to tell us what the erase mode should be set to. 4048d522f475Smrg */ 4049d522f475Smrg#if OPT_INITIAL_ERASE 4050d522f475Smrg TRACE(("resource ptyInitialErase is %sset\n", 4051d522f475Smrg resource.ptyInitialErase ? "" : "not ")); 4052d522f475Smrg setInitialErase = False; 4053f2e35a3aSmrg if (override_tty_modes && ttyModes[XTTYMODE_erase].set) { 4054f2e35a3aSmrg initial_erase = ttyModes[XTTYMODE_erase].value; 4055d522f475Smrg setInitialErase = True; 4056d522f475Smrg } else if (resource.ptyInitialErase) { 4057a1f3da82Smrg /* EMPTY */ ; 4058d522f475Smrg } else if (ok_termcap) { 405920d2c4d2Smrg char *s = get_tcap_erase(xw); 4060d522f475Smrg TRACE(("...extracting initial_erase value from termcap\n")); 4061d522f475Smrg if (s != 0) { 406220d2c4d2Smrg char *save = s; 4063d522f475Smrg initial_erase = decode_keyvalue(&s, True); 4064d522f475Smrg setInitialErase = True; 406520d2c4d2Smrg free(save); 4066d522f475Smrg } 4067d522f475Smrg } 4068d522f475Smrg TRACE(("...initial_erase:%d\n", initial_erase)); 4069d522f475Smrg 4070d522f475Smrg TRACE(("resource backarrowKeyIsErase is %sset\n", 4071d522f475Smrg resource.backarrow_is_erase ? "" : "not ")); 4072d522f475Smrg if (resource.backarrow_is_erase) { /* see input.c */ 4073d522f475Smrg if (initial_erase == ANSI_DEL) { 407420d2c4d2Smrg UIntClr(xw->keyboard.flags, MODE_DECBKM); 4075d522f475Smrg } else { 4076d522f475Smrg xw->keyboard.flags |= MODE_DECBKM; 4077d522f475Smrg xw->keyboard.reset_DECBKM = 1; 4078d522f475Smrg } 4079d522f475Smrg TRACE(("...sets DECBKM %s\n", 4080d522f475Smrg (xw->keyboard.flags & MODE_DECBKM) ? "on" : "off")); 4081d522f475Smrg } else { 4082d522f475Smrg xw->keyboard.reset_DECBKM = 2; 4083d522f475Smrg } 4084d522f475Smrg#endif /* OPT_INITIAL_ERASE */ 4085d522f475Smrg 4086d522f475Smrg#ifdef TTYSIZE_STRUCT 4087d522f475Smrg /* tell tty how big window is */ 4088d522f475Smrg#if OPT_TEK4014 4089d522f475Smrg if (TEK4014_ACTIVE(xw)) { 4090913cc679Smrg setup_winsize(ts, TDefaultRows, TDefaultCols, 4091913cc679Smrg TFullHeight(TekScreenOf(tekWidget)), 4092913cc679Smrg TFullWidth(TekScreenOf(tekWidget))); 4093d522f475Smrg } else 4094d522f475Smrg#endif 4095d522f475Smrg { 4096913cc679Smrg setup_winsize(ts, MaxRows(screen), MaxCols(screen), 4097913cc679Smrg FullHeight(screen), FullWidth(screen)); 4098d522f475Smrg } 409920d2c4d2Smrg TRACE_RC(i, SET_TTYSIZE(screen->respond, ts)); 4100d522f475Smrg TRACE(("spawn SET_TTYSIZE %dx%d return %d\n", 4101d522f475Smrg TTYSIZE_ROWS(ts), 4102d522f475Smrg TTYSIZE_COLS(ts), i)); 4103d522f475Smrg#endif /* TTYSIZE_STRUCT */ 4104d522f475Smrg 41050bd37d32Smrg#if !defined(USE_OPENPTY) 41060bd37d32Smrg#if defined(USE_USG_PTYS) || defined(HAVE_POSIX_OPENPT) 41070bd37d32Smrg /* 41080bd37d32Smrg * utempter checks the ownership of the device; some implementations 41090bd37d32Smrg * set ownership in grantpt - do this first. 41100bd37d32Smrg */ 41110bd37d32Smrg grantpt(screen->respond); 41120bd37d32Smrg#endif 41130bd37d32Smrg#if !defined(USE_USG_PTYS) && defined(HAVE_POSIX_OPENPT) 41140bd37d32Smrg unlockpt(screen->respond); 4115913cc679Smrg TRACE_GET_TTYSIZE(screen->respond, "after unlockpt"); 41160bd37d32Smrg#endif 41170bd37d32Smrg#endif /* !USE_OPENPTY */ 41180bd37d32Smrg 4119d522f475Smrg added_utmp_entry = False; 4120d522f475Smrg#if defined(USE_UTEMPTER) 4121d522f475Smrg#undef UTMP 41222e4f8982Smrg if ((xw->misc.login_shell || !command_to_exec) && !resource.utmpInhibit) { 4123d522f475Smrg struct UTMP_STR dummy; 4124d522f475Smrg 4125d522f475Smrg /* Note: utempter may trim it anyway */ 4126d522f475Smrg SetUtmpHost(dummy.ut_host, screen); 41270bd37d32Smrg TRACE(("...calling addToUtmp(pty=%s, hostname=%s, master_fd=%d)\n", 41280bd37d32Smrg ttydev, dummy.ut_host, screen->respond)); 4129f2e35a3aSmrg UTEMPTER_ADD(ttydev, dummy.ut_host, screen->respond); 4130d522f475Smrg added_utmp_entry = True; 4131d522f475Smrg } 4132d522f475Smrg#endif 4133d522f475Smrg 4134d522f475Smrg if (am_slave < 0) { 4135d522f475Smrg#if OPT_PTY_HANDSHAKE 4136d522f475Smrg if (resource.ptyHandshake && (pipe(pc_pipe) || pipe(cp_pipe))) 4137d522f475Smrg SysError(ERROR_FORK); 4138d522f475Smrg#endif 4139d522f475Smrg TRACE(("Forking...\n")); 4140d522f475Smrg if ((screen->pid = fork()) == -1) 4141d522f475Smrg SysError(ERROR_FORK); 4142d522f475Smrg 4143d522f475Smrg if (screen->pid == 0) { 4144d522f475Smrg#ifdef USE_USG_PTYS 414520d2c4d2Smrg int ptyfd = -1; 4146d522f475Smrg char *pty_name; 4147d522f475Smrg#endif 4148d522f475Smrg /* 4149d522f475Smrg * now in child process 4150d522f475Smrg */ 4151d522f475Smrg#if defined(_POSIX_SOURCE) || defined(SVR4) || defined(__convex__) || defined(__SCO__) || defined(__QNX__) 4152d522f475Smrg int pgrp = setsid(); /* variable may not be used... */ 4153d522f475Smrg#else 4154d522f475Smrg int pgrp = getpid(); 4155d522f475Smrg#endif 4156d522f475Smrg TRACE_CHILD 4157d522f475Smrg 4158d522f475Smrg#ifdef USE_USG_PTYS 41590bd37d32Smrg#ifdef HAVE_SETPGID 41600bd37d32Smrg setpgid(0, 0); 41610bd37d32Smrg#else 4162d522f475Smrg setpgrp(); 41630bd37d32Smrg#endif 41640bd37d32Smrg unlockpt(screen->respond); 4165913cc679Smrg TRACE_GET_TTYSIZE(screen->respond, "after unlockpt"); 41660bd37d32Smrg if ((pty_name = ptsname(screen->respond)) == 0) { 41670bd37d32Smrg SysError(ERROR_PTSNAME); 41680bd37d32Smrg } else if ((ptyfd = open(pty_name, O_RDWR)) < 0) { 41690bd37d32Smrg SysError(ERROR_OPPTSNAME); 41700bd37d32Smrg } 4171d522f475Smrg#ifdef I_PUSH 41722e4f8982Smrg else if (PUSH_FAILS(ptyfd, "ptem")) { 41730bd37d32Smrg SysError(ERROR_PTEM); 41740bd37d32Smrg } 4175d522f475Smrg#if !defined(SVR4) && !(defined(SYSV) && defined(i386)) 41760bd37d32Smrg else if (!x_getenv("CONSEM") 41772e4f8982Smrg && PUSH_FAILS(ptyfd, "consem")) { 41780bd37d32Smrg SysError(ERROR_CONSEM); 41790bd37d32Smrg } 4180d522f475Smrg#endif /* !SVR4 */ 41812e4f8982Smrg else if (PUSH_FAILS(ptyfd, "ldterm")) { 41820bd37d32Smrg SysError(ERROR_LDTERM); 41830bd37d32Smrg } 4184d522f475Smrg#ifdef SVR4 /* from Sony */ 41852e4f8982Smrg else if (PUSH_FAILS(ptyfd, "ttcompat")) { 41860bd37d32Smrg SysError(ERROR_TTCOMPAT); 41870bd37d32Smrg } 4188d522f475Smrg#endif /* SVR4 */ 4189d522f475Smrg#endif /* I_PUSH */ 41900bd37d32Smrg ttyfd = ptyfd; 4191d522f475Smrg#ifndef __MVS__ 41920bd37d32Smrg close_fd(screen->respond); 4193d522f475Smrg#endif /* __MVS__ */ 4194d522f475Smrg 4195d522f475Smrg#ifdef TTYSIZE_STRUCT 41960bd37d32Smrg /* tell tty how big window is */ 4197d522f475Smrg#if OPT_TEK4014 41980bd37d32Smrg if (TEK4014_ACTIVE(xw)) { 4199913cc679Smrg setup_winsize(ts, TDefaultRows, TDefaultCols, 4200913cc679Smrg TFullHeight(TekScreenOf(tekWidget)), 4201913cc679Smrg TFullWidth(TekScreenOf(tekWidget))); 42020bd37d32Smrg } else 4203d522f475Smrg#endif /* OPT_TEK4014 */ 42040bd37d32Smrg { 4205913cc679Smrg setup_winsize(ts, MaxRows(screen), MaxCols(screen), 4206913cc679Smrg FullHeight(screen), FullWidth(screen)); 42070bd37d32Smrg } 4208913cc679Smrg trace_winsize(ts, "initial tty size"); 4209d522f475Smrg#endif /* TTYSIZE_STRUCT */ 4210d522f475Smrg 4211d522f475Smrg#endif /* USE_USG_PTYS */ 4212d522f475Smrg 42130bd37d32Smrg (void) pgrp; /* not all branches use this variable */ 4214d522f475Smrg 4215d522f475Smrg#if OPT_PTY_HANDSHAKE /* warning, goes for a long ways */ 42160bd37d32Smrg if (resource.ptyHandshake) { 42170bd37d32Smrg char *ptr; 4218d522f475Smrg 42190bd37d32Smrg /* close parent's sides of the pipes */ 42200bd37d32Smrg close(cp_pipe[0]); 42210bd37d32Smrg close(pc_pipe[1]); 42220bd37d32Smrg 42230bd37d32Smrg /* Make sure that our sides of the pipes are not in the 42240bd37d32Smrg * 0, 1, 2 range so that we don't fight with stdin, out 42250bd37d32Smrg * or err. 42260bd37d32Smrg */ 42270bd37d32Smrg if (cp_pipe[1] <= 2) { 42280bd37d32Smrg if ((i = fcntl(cp_pipe[1], F_DUPFD, 3)) >= 0) { 42290bd37d32Smrg IGNORE_RC(close(cp_pipe[1])); 42300bd37d32Smrg cp_pipe[1] = i; 4231d522f475Smrg } 42320bd37d32Smrg } 42330bd37d32Smrg if (pc_pipe[0] <= 2) { 42340bd37d32Smrg if ((i = fcntl(pc_pipe[0], F_DUPFD, 3)) >= 0) { 42350bd37d32Smrg IGNORE_RC(close(pc_pipe[0])); 42360bd37d32Smrg pc_pipe[0] = i; 4237d522f475Smrg } 42380bd37d32Smrg } 4239d522f475Smrg 42400bd37d32Smrg /* we don't need the socket, or the pty master anymore */ 42410bd37d32Smrg close(ConnectionNumber(screen->display)); 4242d522f475Smrg#ifndef __MVS__ 4243894e0ac8Smrg if (screen->respond >= 0) 4244894e0ac8Smrg close(screen->respond); 4245d522f475Smrg#endif /* __MVS__ */ 4246d522f475Smrg 42470bd37d32Smrg /* Now is the time to set up our process group and 42480bd37d32Smrg * open up the pty slave. 42490bd37d32Smrg */ 4250d522f475Smrg#ifdef USE_SYSV_PGRP 4251d522f475Smrg#if defined(CRAY) && (OSMAJORVERSION > 5) 42520bd37d32Smrg IGNORE_RC(setsid()); 4253d522f475Smrg#else 42540bd37d32Smrg IGNORE_RC(setpgrp()); 4255d522f475Smrg#endif 4256d522f475Smrg#endif /* USE_SYSV_PGRP */ 4257d522f475Smrg 4258d522f475Smrg#if defined(__QNX__) && !defined(__QNXNTO__) 42590bd37d32Smrg qsetlogin(getlogin(), ttydev); 4260d522f475Smrg#endif 42610bd37d32Smrg if (ttyfd >= 0) { 4262d522f475Smrg#ifdef __MVS__ 42630bd37d32Smrg if (ttyGetAttr(ttyfd, &gio) == 0) { 42640bd37d32Smrg gio.c_cflag &= ~(HUPCL | PARENB); 42650bd37d32Smrg ttySetAttr(ttyfd, &gio); 42660bd37d32Smrg } 4267d522f475Smrg#else /* !__MVS__ */ 42680bd37d32Smrg close_fd(ttyfd); 4269d522f475Smrg#endif /* __MVS__ */ 42700bd37d32Smrg } 4271d522f475Smrg 42720bd37d32Smrg for (;;) { 427320d2c4d2Smrg#if USE_NO_DEV_TTY 42740bd37d32Smrg if (!no_dev_tty 42750bd37d32Smrg && (ttyfd = open("/dev/tty", O_RDWR)) >= 0) { 42760bd37d32Smrg ioctl(ttyfd, TIOCNOTTY, (char *) NULL); 42770bd37d32Smrg close_fd(ttyfd); 42780bd37d32Smrg } 427920d2c4d2Smrg#endif /* USE_NO_DEV_TTY */ 4280d522f475Smrg#ifdef CSRG_BASED 42810bd37d32Smrg IGNORE_RC(revoke(ttydev)); 4282d522f475Smrg#endif 42830bd37d32Smrg if ((ttyfd = open(ttydev, O_RDWR)) >= 0) { 4284913cc679Smrg TRACE_GET_TTYSIZE(ttyfd, "after open"); 42850bd37d32Smrg TRACE_RC(i, SET_TTYSIZE(ttyfd, ts)); 4286913cc679Smrg TRACE_GET_TTYSIZE(ttyfd, "after SET_TTYSIZE fixup"); 4287d522f475Smrg#if defined(CRAY) && defined(TCSETCTTY) 42880bd37d32Smrg /* make /dev/tty work */ 42890bd37d32Smrg ioctl(ttyfd, TCSETCTTY, 0); 4290d522f475Smrg#endif 4291d522f475Smrg#if ((defined(__GLIBC__) && defined(__FreeBSD_kernel__)) || defined(__GNU__)) && defined(TIOCSCTTY) 42920bd37d32Smrg /* make /dev/tty work */ 42930bd37d32Smrg ioctl(ttyfd, TIOCSCTTY, 0); 4294d522f475Smrg#endif 4295d522f475Smrg#ifdef USE_SYSV_PGRP 42960bd37d32Smrg /* We need to make sure that we are actually 42970bd37d32Smrg * the process group leader for the pty. If 42980bd37d32Smrg * we are, then we should now be able to open 42990bd37d32Smrg * /dev/tty. 43000bd37d32Smrg */ 43010bd37d32Smrg if ((i = open("/dev/tty", O_RDWR)) >= 0) { 43020bd37d32Smrg /* success! */ 43030bd37d32Smrg close(i); 4304d522f475Smrg break; 4305d522f475Smrg } 43060bd37d32Smrg#else /* USE_SYSV_PGRP */ 43070bd37d32Smrg break; 43080bd37d32Smrg#endif /* USE_SYSV_PGRP */ 43090bd37d32Smrg } 43100bd37d32Smrg perror("open ttydev"); 4311d522f475Smrg#ifdef TIOCSCTTY 43120bd37d32Smrg ioctl(ttyfd, TIOCSCTTY, 0); 4313d522f475Smrg#endif 43140bd37d32Smrg /* let our master know that the open failed */ 43150bd37d32Smrg handshake.status = PTY_BAD; 43160bd37d32Smrg handshake.error = errno; 4317f2e35a3aSmrg copy_handshake(handshake, ttydev); 43180bd37d32Smrg TRACE_HANDSHAKE("writing", &handshake); 43190bd37d32Smrg IGNORE_RC(write(cp_pipe[1], 43200bd37d32Smrg (const char *) &handshake, 43210bd37d32Smrg sizeof(handshake))); 4322d522f475Smrg 43230bd37d32Smrg /* get reply from parent */ 43240bd37d32Smrg i = (int) read(pc_pipe[0], (char *) &handshake, 43250bd37d32Smrg sizeof(handshake)); 43260bd37d32Smrg if (i <= 0) { 43270bd37d32Smrg /* parent terminated */ 43280bd37d32Smrg exit(1); 4329d522f475Smrg } 4330d522f475Smrg 43310bd37d32Smrg if (handshake.status == PTY_NOMORE) { 43320bd37d32Smrg /* No more ptys, let's shutdown. */ 43330bd37d32Smrg exit(1); 4334d522f475Smrg } 43350bd37d32Smrg 43360bd37d32Smrg /* We have a new pty to try */ 43370bd37d32Smrg if (ttyfd >= 0) 43380bd37d32Smrg close(ttyfd); 43390bd37d32Smrg free(ttydev); 4340f2e35a3aSmrg handshake.buffer[HANDSHAKE_LEN - 1] = '\0'; 43410bd37d32Smrg ttydev = x_strdup(handshake.buffer); 4342d522f475Smrg } 4343d522f475Smrg 43440bd37d32Smrg /* use the same tty name that everyone else will use 43450bd37d32Smrg * (from ttyname) 43460bd37d32Smrg */ 43470bd37d32Smrg if ((ptr = ttyname(ttyfd)) != 0) { 43480bd37d32Smrg free(ttydev); 43490bd37d32Smrg ttydev = x_strdup(ptr); 43500bd37d32Smrg } 43510bd37d32Smrg } 43520bd37d32Smrg#endif /* OPT_PTY_HANDSHAKE -- from near fork */ 4353d522f475Smrg 4354d522f475Smrg set_pty_permissions(screen->uid, 4355913cc679Smrg (unsigned) screen->gid, 4356d522f475Smrg (resource.messages 4357d522f475Smrg ? 0622U 4358d522f475Smrg : 0600U)); 4359d522f475Smrg 4360d522f475Smrg /* 4361d522f475Smrg * set up the tty modes 4362d522f475Smrg */ 4363d522f475Smrg { 4364d522f475Smrg#ifdef TERMIO_STRUCT 4365d522f475Smrg#if defined(umips) || defined(CRAY) || defined(linux) 4366d522f475Smrg /* If the control tty had its modes screwed around with, 4367d522f475Smrg eg. by lineedit in the shell, or emacs, etc. then tio 4368d522f475Smrg will have bad values. Let's just get termio from the 4369d522f475Smrg new tty and tailor it. */ 4370d522f475Smrg if (ttyGetAttr(ttyfd, &tio) == -1) 4371d522f475Smrg SysError(ERROR_TIOCGETP); 4372d522f475Smrg tio.c_lflag |= ECHOE; 4373d522f475Smrg#endif /* umips */ 4374d522f475Smrg /* Now is also the time to change the modes of the 4375d522f475Smrg * child pty. 4376d522f475Smrg */ 4377d522f475Smrg /* input: nl->nl, don't ignore cr, cr->nl */ 437820d2c4d2Smrg UIntClr(tio.c_iflag, (INLCR | IGNCR)); 4379d522f475Smrg tio.c_iflag |= ICRNL; 43800bd37d32Smrg#if OPT_WIDE_CHARS && defined(IUTF8) 4381d522f475Smrg#if OPT_LUIT_PROG 4382d522f475Smrg if (command_to_exec_with_luit == 0) 4383d522f475Smrg#endif 4384d522f475Smrg if (screen->utf8_mode) 4385d522f475Smrg tio.c_iflag |= IUTF8; 4386d522f475Smrg#endif 4387f2e35a3aSmrg /* output: cr->cr, nl is not return, no delays, ln->cr/nl */ 4388d522f475Smrg#ifndef USE_POSIX_TERMIOS 438920d2c4d2Smrg UIntClr(tio.c_oflag, 439020d2c4d2Smrg (OCRNL 439120d2c4d2Smrg | ONLRET 439220d2c4d2Smrg | NLDLY 439320d2c4d2Smrg | CRDLY 439420d2c4d2Smrg | TABDLY 439520d2c4d2Smrg | BSDLY 439620d2c4d2Smrg | VTDLY 439720d2c4d2Smrg | FFDLY)); 4398d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 4399f2e35a3aSmrg tio.c_oflag |= D_TIO_FLAGS; 4400d522f475Smrg#ifndef USE_POSIX_TERMIOS 4401d522f475Smrg# if defined(Lynx) && !defined(CBAUD) 4402d522f475Smrg# define CBAUD V_CBAUD 4403d522f475Smrg# endif 440420d2c4d2Smrg UIntClr(tio.c_cflag, CBAUD); 4405d522f475Smrg#ifdef BAUD_0 4406d522f475Smrg /* baud rate is 0 (don't care) */ 4407d522f475Smrg#elif defined(HAVE_TERMIO_C_ISPEED) 44082e4f8982Smrg tio.c_ispeed = tio.c_ospeed = line_speed; 4409d522f475Smrg#else /* !BAUD_0 */ 44102e4f8982Smrg tio.c_cflag |= line_speed; 4411d522f475Smrg#endif /* !BAUD_0 */ 4412d522f475Smrg#else /* USE_POSIX_TERMIOS */ 44132e4f8982Smrg cfsetispeed(&tio, line_speed); 44142e4f8982Smrg cfsetospeed(&tio, line_speed); 4415d522f475Smrg#ifdef __MVS__ 4416d522f475Smrg /* turn off bits that can't be set from the slave side */ 4417d522f475Smrg tio.c_cflag &= ~(PACKET | PKT3270 | PTU3270 | PKTXTND); 4418d522f475Smrg#endif /* __MVS__ */ 4419d522f475Smrg /* Clear CLOCAL so that SIGHUP is sent to us 4420d522f475Smrg when the xterm ends */ 44212e4f8982Smrg tio.c_cflag &= (unsigned) ~CLOCAL; 4422d522f475Smrg#endif /* USE_POSIX_TERMIOS */ 4423d522f475Smrg /* enable signals, canonical processing (erase, kill, etc), 4424d522f475Smrg * echo 4425d522f475Smrg */ 4426d522f475Smrg tio.c_lflag |= ISIG | ICANON | ECHO | ECHOE | ECHOK; 4427d522f475Smrg#ifdef ECHOKE 4428d522f475Smrg tio.c_lflag |= ECHOKE | IEXTEN; 4429d522f475Smrg#endif 4430d522f475Smrg#ifdef ECHOCTL 4431d522f475Smrg tio.c_lflag |= ECHOCTL | IEXTEN; 4432d522f475Smrg#endif 4433f2e35a3aSmrg for (nn = 0; nn < XtNumber(ttyChars); ++nn) { 4434d522f475Smrg if (validTtyChar(tio, nn)) { 4435f2e35a3aSmrg int sysMode = ttyChars[nn].sysMode; 4436d522f475Smrg#ifdef __MVS__ 4437d522f475Smrg if (tio.c_cc[sysMode] != 0) { 4438d522f475Smrg switch (sysMode) { 4439d522f475Smrg case VEOL: 4440d522f475Smrg case VEOF: 4441d522f475Smrg continue; 4442d522f475Smrg } 4443d522f475Smrg } 4444d522f475Smrg#endif 4445f2e35a3aSmrg tio.c_cc[sysMode] = (cc_t) ttyChars[nn].myDefault; 4446d522f475Smrg } 4447d522f475Smrg } 4448d522f475Smrg 4449d522f475Smrg if (override_tty_modes) { 4450f2e35a3aSmrg TRACE(("applying termios ttyModes\n")); 4451f2e35a3aSmrg for (nn = 0; nn < XtNumber(ttyChars); ++nn) { 4452d522f475Smrg if (validTtyChar(tio, nn)) { 4453f2e35a3aSmrg TMODE(ttyChars[nn].myMode, 4454f2e35a3aSmrg tio.c_cc[ttyChars[nn].sysMode]); 4455f2e35a3aSmrg } else if (isTabMode(nn)) { 4456f2e35a3aSmrg unsigned tmp = (unsigned) tio.c_oflag; 4457f2e35a3aSmrg tmp = tmp & (unsigned) ~TABDLY; 4458f2e35a3aSmrg tmp |= (unsigned) ttyModes[ttyChars[nn].myMode].value; 4459f2e35a3aSmrg tio.c_oflag = tmp; 4460d522f475Smrg } 4461d522f475Smrg } 4462d522f475Smrg#ifdef HAS_LTCHARS 4463d522f475Smrg /* both SYSV and BSD have ltchars */ 4464d522f475Smrg TMODE(XTTYMODE_susp, ltc.t_suspc); 4465d522f475Smrg TMODE(XTTYMODE_dsusp, ltc.t_dsuspc); 4466d522f475Smrg TMODE(XTTYMODE_rprnt, ltc.t_rprntc); 4467d522f475Smrg TMODE(XTTYMODE_flush, ltc.t_flushc); 4468d522f475Smrg TMODE(XTTYMODE_weras, ltc.t_werasc); 4469d522f475Smrg TMODE(XTTYMODE_lnext, ltc.t_lnextc); 4470d522f475Smrg#endif 4471d522f475Smrg } 4472d522f475Smrg#ifdef HAS_LTCHARS 4473d522f475Smrg#ifdef __hpux 4474d522f475Smrg /* ioctl chokes when the "reserved" process group controls 4475d522f475Smrg * are not set to _POSIX_VDISABLE */ 4476913cc679Smrg ltc.t_rprntc = _POSIX_VDISABLE; 4477913cc679Smrg ltc.t_rprntc = _POSIX_VDISABLE; 4478913cc679Smrg ltc.t_flushc = _POSIX_VDISABLE; 4479913cc679Smrg ltc.t_werasc = _POSIX_VDISABLE; 4480913cc679Smrg ltc.t_lnextc = _POSIX_VDISABLE; 4481d522f475Smrg#endif /* __hpux */ 4482d522f475Smrg if (ioctl(ttyfd, TIOCSLTC, <c) == -1) 4483d522f475Smrg HsSysError(ERROR_TIOCSETC); 4484d522f475Smrg#endif /* HAS_LTCHARS */ 4485d522f475Smrg#ifdef TIOCLSET 4486d522f475Smrg if (ioctl(ttyfd, TIOCLSET, (char *) &lmode) == -1) 4487d522f475Smrg HsSysError(ERROR_TIOCLSET); 4488d522f475Smrg#endif /* TIOCLSET */ 4489d522f475Smrg if (ttySetAttr(ttyfd, &tio) == -1) 4490d522f475Smrg HsSysError(ERROR_TIOCSETP); 4491d522f475Smrg 4492d522f475Smrg /* ignore errors here - some platforms don't work */ 449320d2c4d2Smrg UIntClr(tio.c_cflag, CSIZE); 4494d522f475Smrg if (screen->input_eight_bits) 4495d522f475Smrg tio.c_cflag |= CS8; 4496d522f475Smrg else 4497d522f475Smrg tio.c_cflag |= CS7; 4498d522f475Smrg (void) ttySetAttr(ttyfd, &tio); 4499d522f475Smrg 4500d522f475Smrg#else /* !TERMIO_STRUCT */ 4501d522f475Smrg sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW); 4502d522f475Smrg sg.sg_flags |= ECHO | CRMOD; 4503d522f475Smrg /* make sure speed is set on pty so that editors work right */ 45042e4f8982Smrg sg.sg_ispeed = line_speed; 45052e4f8982Smrg sg.sg_ospeed = line_speed; 4506d522f475Smrg /* reset t_brkc to default value */ 4507d522f475Smrg tc.t_brkc = -1; 4508d522f475Smrg#ifdef LPASS8 4509d522f475Smrg if (screen->input_eight_bits) 4510d522f475Smrg lmode |= LPASS8; 4511d522f475Smrg else 4512d522f475Smrg lmode &= ~(LPASS8); 4513d522f475Smrg#endif 4514d522f475Smrg#ifdef sony 4515d522f475Smrg jmode &= ~KM_KANJI; 4516d522f475Smrg#endif /* sony */ 4517d522f475Smrg 4518d522f475Smrg ltc = d_ltc; 4519d522f475Smrg 4520d522f475Smrg if (override_tty_modes) { 4521f2e35a3aSmrg TRACE(("applying sgtty ttyModes\n")); 4522d522f475Smrg TMODE(XTTYMODE_intr, tc.t_intrc); 4523d522f475Smrg TMODE(XTTYMODE_quit, tc.t_quitc); 4524d522f475Smrg TMODE(XTTYMODE_erase, sg.sg_erase); 4525d522f475Smrg TMODE(XTTYMODE_kill, sg.sg_kill); 4526d522f475Smrg TMODE(XTTYMODE_eof, tc.t_eofc); 4527d522f475Smrg TMODE(XTTYMODE_start, tc.t_startc); 4528d522f475Smrg TMODE(XTTYMODE_stop, tc.t_stopc); 4529d522f475Smrg TMODE(XTTYMODE_brk, tc.t_brkc); 4530d522f475Smrg /* both SYSV and BSD have ltchars */ 4531d522f475Smrg TMODE(XTTYMODE_susp, ltc.t_suspc); 4532d522f475Smrg TMODE(XTTYMODE_dsusp, ltc.t_dsuspc); 4533d522f475Smrg TMODE(XTTYMODE_rprnt, ltc.t_rprntc); 4534d522f475Smrg TMODE(XTTYMODE_flush, ltc.t_flushc); 4535d522f475Smrg TMODE(XTTYMODE_weras, ltc.t_werasc); 4536d522f475Smrg TMODE(XTTYMODE_lnext, ltc.t_lnextc); 4537f2e35a3aSmrg if (ttyModes[XTTYMODE_tabs].set 4538f2e35a3aSmrg || ttyModes[XTTYMODE__tabs].set) { 4539f2e35a3aSmrg sg.sg_flags &= ~XTABS; 4540f2e35a3aSmrg if (ttyModes[XTTYMODE__tabs].set.set) 4541f2e35a3aSmrg sg.sg_flags |= XTABS; 4542f2e35a3aSmrg } 4543d522f475Smrg } 4544d522f475Smrg 4545d522f475Smrg if (ioctl(ttyfd, TIOCSETP, (char *) &sg) == -1) 4546d522f475Smrg HsSysError(ERROR_TIOCSETP); 4547d522f475Smrg if (ioctl(ttyfd, TIOCSETC, (char *) &tc) == -1) 4548d522f475Smrg HsSysError(ERROR_TIOCSETC); 4549d522f475Smrg if (ioctl(ttyfd, TIOCSETD, (char *) &discipline) == -1) 4550d522f475Smrg HsSysError(ERROR_TIOCSETD); 4551d522f475Smrg if (ioctl(ttyfd, TIOCSLTC, (char *) <c) == -1) 4552d522f475Smrg HsSysError(ERROR_TIOCSLTC); 4553d522f475Smrg if (ioctl(ttyfd, TIOCLSET, (char *) &lmode) == -1) 4554d522f475Smrg HsSysError(ERROR_TIOCLSET); 4555d522f475Smrg#ifdef sony 4556d522f475Smrg if (ioctl(ttyfd, TIOCKSET, (char *) &jmode) == -1) 4557d522f475Smrg HsSysError(ERROR_TIOCKSET); 4558d522f475Smrg if (ioctl(ttyfd, TIOCKSETC, (char *) &jtc) == -1) 4559d522f475Smrg HsSysError(ERROR_TIOCKSETC); 4560d522f475Smrg#endif /* sony */ 4561d522f475Smrg#endif /* TERMIO_STRUCT */ 4562d522f475Smrg#if defined(TIOCCONS) || defined(SRIOCSREDIR) 4563d522f475Smrg if (Console) { 4564d522f475Smrg#ifdef TIOCCONS 4565d522f475Smrg int on = 1; 4566d522f475Smrg if (ioctl(ttyfd, TIOCCONS, (char *) &on) == -1) 45670bd37d32Smrg xtermPerror("cannot open console"); 4568d522f475Smrg#endif 4569d522f475Smrg#ifdef SRIOCSREDIR 4570d522f475Smrg int fd = open("/dev/console", O_RDWR); 4571d522f475Smrg if (fd == -1 || ioctl(fd, SRIOCSREDIR, ttyfd) == -1) 45720bd37d32Smrg xtermPerror("cannot open console"); 457320d2c4d2Smrg IGNORE_RC(close(fd)); 4574d522f475Smrg#endif 4575d522f475Smrg } 4576d522f475Smrg#endif /* TIOCCONS */ 4577d522f475Smrg } 4578d522f475Smrg 4579d522f475Smrg signal(SIGCHLD, SIG_DFL); 4580d522f475Smrg#ifdef USE_SYSV_SIGHUP 4581d522f475Smrg /* watch out for extra shells (I don't understand either) */ 4582d522f475Smrg signal(SIGHUP, SIG_DFL); 4583d522f475Smrg#else 4584d522f475Smrg signal(SIGHUP, SIG_IGN); 4585d522f475Smrg#endif 4586d522f475Smrg /* restore various signals to their defaults */ 4587d522f475Smrg signal(SIGINT, SIG_DFL); 4588d522f475Smrg signal(SIGQUIT, SIG_DFL); 4589d522f475Smrg signal(SIGTERM, SIG_DFL); 4590d522f475Smrg 4591d522f475Smrg /* 4592d522f475Smrg * If we're not asked to let the parent process set the terminal's 4593d522f475Smrg * erase mode, or if we had the ttyModes erase resource, then set 4594d522f475Smrg * the terminal's erase mode from our best guess. 4595d522f475Smrg */ 4596d522f475Smrg#if OPT_INITIAL_ERASE 4597d522f475Smrg TRACE(("check if we should set erase to %d:%s\n\tptyInitialErase:%d,\n\toveride_tty_modes:%d,\n\tXTTYMODE_erase:%d\n", 4598d522f475Smrg initial_erase, 4599d522f475Smrg setInitialErase ? "YES" : "NO", 4600d522f475Smrg resource.ptyInitialErase, 4601d522f475Smrg override_tty_modes, 4602f2e35a3aSmrg ttyModes[XTTYMODE_erase].set)); 4603d522f475Smrg if (setInitialErase) { 4604d522f475Smrg#if OPT_TRACE 4605d522f475Smrg int old_erase; 4606d522f475Smrg#endif 4607d522f475Smrg#ifdef TERMIO_STRUCT 4608d522f475Smrg if (ttyGetAttr(ttyfd, &tio) == -1) 4609d522f475Smrg tio = d_tio; 4610d522f475Smrg#if OPT_TRACE 4611d522f475Smrg old_erase = tio.c_cc[VERASE]; 4612d522f475Smrg#endif 46130bd37d32Smrg tio.c_cc[VERASE] = (cc_t) initial_erase; 461420d2c4d2Smrg TRACE_RC(rc, ttySetAttr(ttyfd, &tio)); 4615d522f475Smrg#else /* !TERMIO_STRUCT */ 4616d522f475Smrg if (ioctl(ttyfd, TIOCGETP, (char *) &sg) == -1) 4617d522f475Smrg sg = d_sg; 4618d522f475Smrg#if OPT_TRACE 4619d522f475Smrg old_erase = sg.sg_erase; 4620d522f475Smrg#endif 4621d522f475Smrg sg.sg_erase = initial_erase; 4622d522f475Smrg rc = ioctl(ttyfd, TIOCSETP, (char *) &sg); 4623d522f475Smrg#endif /* TERMIO_STRUCT */ 4624d522f475Smrg TRACE(("%s setting erase to %d (was %d)\n", 4625d522f475Smrg rc ? "FAIL" : "OK", initial_erase, old_erase)); 4626d522f475Smrg } 4627d522f475Smrg#endif 4628d522f475Smrg 4629d522f475Smrg xtermCopyEnv(environ); 46304419d26bSmrg xtermTrimEnv(); 46310bd37d32Smrg 4632a1f3da82Smrg xtermSetenv("TERM", resource.term_name); 4633a1f3da82Smrg if (!resource.term_name) 463420d2c4d2Smrg *get_tcap_buffer(xw) = 0; 4635d522f475Smrg 4636d522f475Smrg sprintf(buf, "%lu", 4637d522f475Smrg ((unsigned long) XtWindow(SHELL_OF(CURRENT_EMU())))); 4638d522f475Smrg xtermSetenv("WINDOWID", buf); 4639d522f475Smrg 4640d522f475Smrg /* put the display into the environment of the shell */ 4641d522f475Smrg xtermSetenv("DISPLAY", XDisplayString(screen->display)); 4642d522f475Smrg 4643d522f475Smrg xtermSetenv("XTERM_VERSION", xtermVersion()); 4644d522f475Smrg xtermSetenv("XTERM_LOCALE", xtermEnvLocale()); 4645d522f475Smrg 4646e39b573cSmrg /* 4647e39b573cSmrg * For debugging only, add environment variables that can be used 4648e39b573cSmrg * in scripts to selectively kill xterm's parent or child 4649e39b573cSmrg * processes. 4650e39b573cSmrg */ 4651e39b573cSmrg#if OPT_TRACE 4652e39b573cSmrg sprintf(buf, "%lu", (unsigned long) xterm_parent); 4653e39b573cSmrg xtermSetenv("XTERM_PARENT", buf); 4654e39b573cSmrg sprintf(buf, "%lu", (unsigned long) getpid()); 4655e39b573cSmrg xtermSetenv("XTERM_CHILD", buf); 4656e39b573cSmrg#endif 4657e39b573cSmrg 4658d522f475Smrg signal(SIGTERM, SIG_DFL); 4659d522f475Smrg 4660d522f475Smrg /* this is the time to go and set up stdin, out, and err 4661d522f475Smrg */ 4662d522f475Smrg { 4663d522f475Smrg#if defined(CRAY) && (OSMAJORVERSION >= 6) 4664d522f475Smrg close_fd(ttyfd); 4665d522f475Smrg 466620d2c4d2Smrg IGNORE_RC(close(0)); 4667d522f475Smrg 4668d522f475Smrg if (open("/dev/tty", O_RDWR)) { 4669d522f475Smrg SysError(ERROR_OPDEVTTY); 4670d522f475Smrg } 467120d2c4d2Smrg IGNORE_RC(close(1)); 467220d2c4d2Smrg IGNORE_RC(close(2)); 4673d522f475Smrg dup(0); 4674d522f475Smrg dup(0); 4675d522f475Smrg#else 4676d522f475Smrg /* dup the tty */ 4677d522f475Smrg for (i = 0; i <= 2; i++) 4678d522f475Smrg if (i != ttyfd) { 467920d2c4d2Smrg IGNORE_RC(close(i)); 468020d2c4d2Smrg IGNORE_RC(dup(ttyfd)); 4681d522f475Smrg } 4682d522f475Smrg#ifndef ATT 4683d522f475Smrg /* and close the tty */ 4684d522f475Smrg if (ttyfd > 2) 4685d522f475Smrg close_fd(ttyfd); 4686d522f475Smrg#endif 4687d522f475Smrg#endif /* CRAY */ 4688d522f475Smrg } 4689d522f475Smrg 4690d522f475Smrg#if !defined(USE_SYSV_PGRP) 4691d522f475Smrg#ifdef TIOCSCTTY 4692d522f475Smrg setsid(); 4693d522f475Smrg ioctl(0, TIOCSCTTY, 0); 4694d522f475Smrg#endif 4695d522f475Smrg ioctl(0, TIOCSPGRP, (char *) &pgrp); 4696d522f475Smrg setpgrp(0, 0); 4697d522f475Smrg close(open(ttydev, O_WRONLY)); 4698d522f475Smrg setpgrp(0, pgrp); 4699d522f475Smrg#if defined(__QNX__) 4700d522f475Smrg tcsetpgrp(0, pgrp /*setsid() */ ); 4701d522f475Smrg#endif 4702d522f475Smrg#endif /* !USE_SYSV_PGRP */ 4703d522f475Smrg 4704d522f475Smrg#ifdef Lynx 4705d522f475Smrg { 4706d522f475Smrg TERMIO_STRUCT t; 4707d522f475Smrg if (ttyGetAttr(0, &t) >= 0) { 4708d522f475Smrg /* this gets lost somewhere on our way... */ 4709d522f475Smrg t.c_oflag |= OPOST; 4710d522f475Smrg ttySetAttr(0, &t); 4711d522f475Smrg } 4712d522f475Smrg } 4713d522f475Smrg#endif 4714d522f475Smrg 4715d522f475Smrg#ifdef HAVE_UTMP 4716d522f475Smrg login_name = NULL; 47170bd37d32Smrg if (x_getpwuid(screen->uid, &pw)) { 47180bd37d32Smrg login_name = x_getlogin(screen->uid, &pw); 4719d522f475Smrg } 4720d522f475Smrg if (login_name != NULL) { 4721d522f475Smrg xtermSetenv("LOGNAME", login_name); /* for POSIX */ 4722d522f475Smrg } 4723d522f475Smrg#ifndef USE_UTEMPTER 4724d522f475Smrg#ifdef USE_UTMP_SETGID 4725d522f475Smrg setEffectiveGroup(save_egid); 4726d522f475Smrg TRACE_IDS; 4727d522f475Smrg#endif 4728d522f475Smrg#ifdef USE_SYSV_UTMP 4729d522f475Smrg /* Set up our utmp entry now. We need to do it here 4730d522f475Smrg * for the following reasons: 4731d522f475Smrg * - It needs to have our correct process id (for 4732d522f475Smrg * login). 4733d522f475Smrg * - If our parent was to set it after the fork(), 4734d522f475Smrg * it might make it out before we need it. 4735d522f475Smrg * - We need to do it before we go and change our 4736d522f475Smrg * user and group id's. 4737d522f475Smrg */ 4738d522f475Smrg (void) call_setutent(); 4739d522f475Smrg init_utmp(DEAD_PROCESS, &utmp); 4740d522f475Smrg 4741d522f475Smrg /* position to entry in utmp file */ 4742d522f475Smrg /* Test return value: beware of entries left behind: PSz 9 Mar 00 */ 474320d2c4d2Smrg utret = find_utmp(&utmp); 474420d2c4d2Smrg if (utret == 0) { 4745d522f475Smrg (void) call_setutent(); 4746d522f475Smrg init_utmp(USER_PROCESS, &utmp); 474720d2c4d2Smrg utret = find_utmp(&utmp); 474820d2c4d2Smrg if (utret == 0) { 4749d522f475Smrg (void) call_setutent(); 4750d522f475Smrg } 4751d522f475Smrg } 4752d522f475Smrg#if OPT_TRACE 4753d522f475Smrg if (!utret) 4754d522f475Smrg TRACE(("getutid: NULL\n")); 4755d522f475Smrg else 47560bd37d32Smrg TRACE(("getutid: pid=%d type=%d user=%s line=%.*s id=%.*s\n", 475720d2c4d2Smrg (int) utret->ut_pid, utret->ut_type, utret->ut_user, 47580bd37d32Smrg (int) sizeof(utret->ut_line), utret->ut_line, 47590bd37d32Smrg (int) sizeof(utret->ut_id), utret->ut_id)); 4760d522f475Smrg#endif 4761d522f475Smrg 4762d522f475Smrg /* set up the new entry */ 4763d522f475Smrg utmp.ut_type = USER_PROCESS; 4764d522f475Smrg#ifdef HAVE_UTMP_UT_XSTATUS 4765d522f475Smrg utmp.ut_xstatus = 2; 4766d522f475Smrg#endif 4767894e0ac8Smrg copy_filled(utmp.ut_user, 4768894e0ac8Smrg (login_name != NULL) ? login_name : "????", 4769894e0ac8Smrg sizeof(utmp.ut_user)); 4770d522f475Smrg /* why are we copying this string again? (see above) */ 4771894e0ac8Smrg copy_filled(utmp.ut_id, my_utmp_id(ttydev), sizeof(utmp.ut_id)); 4772894e0ac8Smrg copy_filled(utmp.ut_line, 4773894e0ac8Smrg my_pty_name(ttydev), sizeof(utmp.ut_line)); 4774d522f475Smrg 4775d522f475Smrg#ifdef HAVE_UTMP_UT_HOST 4776d522f475Smrg SetUtmpHost(utmp.ut_host, screen); 4777d522f475Smrg#endif 4778d522f475Smrg#ifdef HAVE_UTMP_UT_SYSLEN 4779d522f475Smrg SetUtmpSysLen(utmp); 4780d522f475Smrg#endif 4781d522f475Smrg 4782894e0ac8Smrg copy_filled(utmp.ut_name, 4783894e0ac8Smrg (login_name) ? login_name : "????", 4784894e0ac8Smrg sizeof(utmp.ut_name)); 4785d522f475Smrg 4786d522f475Smrg utmp.ut_pid = getpid(); 4787d522f475Smrg#if defined(HAVE_UTMP_UT_XTIME) 4788d522f475Smrg#if defined(HAVE_UTMP_UT_SESSION) 4789d522f475Smrg utmp.ut_session = getsid(0); 4790d522f475Smrg#endif 4791d522f475Smrg utmp.ut_xtime = time((time_t *) 0); 4792d522f475Smrg utmp.ut_tv.tv_usec = 0; 4793d522f475Smrg#else 4794d522f475Smrg utmp.ut_time = time((time_t *) 0); 4795d522f475Smrg#endif 4796d522f475Smrg 4797d522f475Smrg /* write out the entry */ 4798d522f475Smrg if (!resource.utmpInhibit) { 4799d522f475Smrg errno = 0; 4800d522f475Smrg call_pututline(&utmp); 48010bd37d32Smrg TRACE(("pututline: id %.*s, line %.*s, pid %ld, errno %d %s\n", 48020bd37d32Smrg (int) sizeof(utmp.ut_id), utmp.ut_id, 48030bd37d32Smrg (int) sizeof(utmp.ut_line), utmp.ut_line, 4804d522f475Smrg (long) utmp.ut_pid, 4805d522f475Smrg errno, (errno != 0) ? strerror(errno) : "")); 4806d522f475Smrg } 4807d522f475Smrg#ifdef WTMP 4808d522f475Smrg#if defined(WTMPX_FILE) && (defined(SVR4) || defined(__SCO__)) 4809d522f475Smrg if (xw->misc.login_shell) 4810d522f475Smrg updwtmpx(WTMPX_FILE, &utmp); 4811d522f475Smrg#elif defined(linux) && defined(__GLIBC__) && (__GLIBC__ >= 2) && !(defined(__powerpc__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)) 4812d522f475Smrg if (xw->misc.login_shell) 4813d522f475Smrg call_updwtmp(etc_wtmp, &utmp); 4814d522f475Smrg#else 4815d522f475Smrg if (xw->misc.login_shell && 4816d522f475Smrg (i = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 48170bd37d32Smrg IGNORE_RC(write(i, (char *) &utmp, sizeof(utmp))); 4818d522f475Smrg close(i); 4819d522f475Smrg } 4820d522f475Smrg#endif 4821d522f475Smrg#endif 4822d522f475Smrg /* close the file */ 4823d522f475Smrg (void) call_endutent(); 4824d522f475Smrg 4825d522f475Smrg#else /* USE_SYSV_UTMP */ 4826d522f475Smrg /* We can now get our ttyslot! We can also set the initial 4827d522f475Smrg * utmp entry. 4828d522f475Smrg */ 4829d522f475Smrg tslot = ttyslot(); 4830d522f475Smrg added_utmp_entry = False; 4831d522f475Smrg { 48320bd37d32Smrg if (tslot > 0 && OkPasswd(&pw) && !resource.utmpInhibit && 4833d522f475Smrg (i = open(etc_utmp, O_WRONLY)) >= 0) { 4834956cc18dSsnj memset(&utmp, 0, sizeof(utmp)); 4835894e0ac8Smrg copy_filled(utmp.ut_line, 4836894e0ac8Smrg my_pty_name(ttydev), 4837894e0ac8Smrg sizeof(utmp.ut_line)); 4838894e0ac8Smrg copy_filled(utmp.ut_name, login_name, 4839894e0ac8Smrg sizeof(utmp.ut_name)); 4840d522f475Smrg#ifdef HAVE_UTMP_UT_HOST 4841d522f475Smrg SetUtmpHost(utmp.ut_host, screen); 4842d522f475Smrg#endif 4843d522f475Smrg#ifdef HAVE_UTMP_UT_SYSLEN 4844d522f475Smrg SetUtmpSysLen(utmp); 4845d522f475Smrg#endif 4846d522f475Smrg 4847d522f475Smrg utmp.ut_time = time((time_t *) 0); 4848d522f475Smrg lseek(i, (long) (tslot * sizeof(utmp)), 0); 48490bd37d32Smrg IGNORE_RC(write(i, (char *) &utmp, sizeof(utmp))); 4850d522f475Smrg close(i); 4851d522f475Smrg added_utmp_entry = True; 4852d522f475Smrg#if defined(WTMP) 4853d522f475Smrg if (xw->misc.login_shell && 4854d522f475Smrg (i = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 4855d522f475Smrg int status; 4856d522f475Smrg status = write(i, (char *) &utmp, sizeof(utmp)); 4857d522f475Smrg status = close(i); 4858d522f475Smrg } 4859d522f475Smrg#elif defined(MNX_LASTLOG) 4860d522f475Smrg if (xw->misc.login_shell && 4861d522f475Smrg (i = open(_U_LASTLOG, O_WRONLY)) >= 0) { 4862d522f475Smrg lseek(i, (long) (screen->uid * 4863d522f475Smrg sizeof(utmp)), 0); 48640bd37d32Smrg IGNORE_RC(write(i, (char *) &utmp, sizeof(utmp))); 4865d522f475Smrg close(i); 4866d522f475Smrg } 4867d522f475Smrg#endif /* WTMP or MNX_LASTLOG */ 4868d522f475Smrg } else 4869d522f475Smrg tslot = -tslot; 4870d522f475Smrg } 4871d522f475Smrg 4872d522f475Smrg /* Let's pass our ttyslot to our parent so that it can 4873d522f475Smrg * clean up after us. 4874d522f475Smrg */ 4875d522f475Smrg#if OPT_PTY_HANDSHAKE 4876d522f475Smrg if (resource.ptyHandshake) { 4877d522f475Smrg handshake.tty_slot = tslot; 4878d522f475Smrg } 4879d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4880d522f475Smrg#endif /* USE_SYSV_UTMP */ 4881d522f475Smrg 4882d522f475Smrg#ifdef USE_LASTLOGX 4883d522f475Smrg if (xw->misc.login_shell) { 4884956cc18dSsnj memset(&lastlogx, 0, sizeof(lastlogx)); 4885f2e35a3aSmrg copy_filled(lastlogx.ll_line, 4886f2e35a3aSmrg my_pty_name(ttydev), 4887f2e35a3aSmrg sizeof(lastlogx.ll_line)); 4888d522f475Smrg X_GETTIMEOFDAY(&lastlogx.ll_tv); 4889d522f475Smrg SetUtmpHost(lastlogx.ll_host, screen); 4890d522f475Smrg updlastlogx(_PATH_LASTLOGX, screen->uid, &lastlogx); 4891d522f475Smrg } 4892d522f475Smrg#endif 4893d522f475Smrg 4894d522f475Smrg#ifdef USE_LASTLOG 4895d522f475Smrg if (xw->misc.login_shell && 4896d522f475Smrg (i = open(etc_lastlog, O_WRONLY)) >= 0) { 4897d522f475Smrg size_t size = sizeof(struct lastlog); 4898913cc679Smrg off_t offset = (off_t) ((size_t) screen->uid * size); 4899d522f475Smrg 4900956cc18dSsnj memset(&lastlog, 0, size); 4901f2e35a3aSmrg copy_filled(lastlog.ll_line, 4902f2e35a3aSmrg my_pty_name(ttydev), 4903f2e35a3aSmrg sizeof(lastlog.ll_line)); 4904d522f475Smrg SetUtmpHost(lastlog.ll_host, screen); 4905d522f475Smrg lastlog.ll_time = time((time_t *) 0); 4906d522f475Smrg if (lseek(i, offset, 0) != (off_t) (-1)) { 49070bd37d32Smrg IGNORE_RC(write(i, (char *) &lastlog, size)); 4908d522f475Smrg } 4909d522f475Smrg close(i); 4910d522f475Smrg } 4911d522f475Smrg#endif /* USE_LASTLOG */ 4912d522f475Smrg 4913d522f475Smrg#if defined(USE_UTMP_SETGID) 4914d522f475Smrg disableSetGid(); 4915d522f475Smrg TRACE_IDS; 4916d522f475Smrg#endif 4917d522f475Smrg 4918d522f475Smrg#if OPT_PTY_HANDSHAKE 4919d522f475Smrg /* Let our parent know that we set up our utmp entry 4920d522f475Smrg * so that it can clean up after us. 4921d522f475Smrg */ 4922d522f475Smrg if (resource.ptyHandshake) { 4923d522f475Smrg handshake.status = UTMP_ADDED; 4924d522f475Smrg handshake.error = 0; 4925f2e35a3aSmrg copy_handshake(handshake, ttydev); 4926d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 492720d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], (char *) &handshake, sizeof(handshake))); 4928d522f475Smrg } 4929d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4930d522f475Smrg#endif /* USE_UTEMPTER */ 4931d522f475Smrg#endif /* HAVE_UTMP */ 4932d522f475Smrg 493320d2c4d2Smrg IGNORE_RC(setgid(screen->gid)); 4934d522f475Smrg TRACE_IDS; 4935e0a2b6dfSmrg#ifdef HAVE_INITGROUPS 49360bd37d32Smrg if (geteuid() == 0 && OkPasswd(&pw)) { 49370bd37d32Smrg if (initgroups(login_name, pw.pw_gid)) { 4938d522f475Smrg perror("initgroups failed"); 4939d522f475Smrg SysError(ERROR_INIGROUPS); 4940d522f475Smrg } 4941d522f475Smrg } 4942d522f475Smrg#endif 4943d522f475Smrg if (setuid(screen->uid)) { 4944d522f475Smrg SysError(ERROR_SETUID); 4945d522f475Smrg } 4946d522f475Smrg TRACE_IDS; 4947d522f475Smrg#if OPT_PTY_HANDSHAKE 4948d522f475Smrg if (resource.ptyHandshake) { 4949d522f475Smrg /* mark the pipes as close on exec */ 49500bd37d32Smrg (void) fcntl(cp_pipe[1], F_SETFD, 1); 49510bd37d32Smrg (void) fcntl(pc_pipe[0], F_SETFD, 1); 4952d522f475Smrg 4953d522f475Smrg /* We are at the point where we are going to 4954d522f475Smrg * exec our shell (or whatever). Let our parent 4955d522f475Smrg * know we arrived safely. 4956d522f475Smrg */ 4957d522f475Smrg handshake.status = PTY_GOOD; 4958d522f475Smrg handshake.error = 0; 4959f2e35a3aSmrg copy_handshake(handshake, ttydev); 4960d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 496120d2c4d2Smrg IGNORE_RC(write(cp_pipe[1], 496220d2c4d2Smrg (const char *) &handshake, 496320d2c4d2Smrg sizeof(handshake))); 4964d522f475Smrg 4965d522f475Smrg if (resource.wait_for_map) { 496620d2c4d2Smrg i = (int) read(pc_pipe[0], (char *) &handshake, 496720d2c4d2Smrg sizeof(handshake)); 4968d522f475Smrg if (i != sizeof(handshake) || 4969d522f475Smrg handshake.status != PTY_EXEC) { 4970d522f475Smrg /* some very bad problem occurred */ 4971d522f475Smrg exit(ERROR_PTY_EXEC); 4972d522f475Smrg } 4973d522f475Smrg if (handshake.rows > 0 && handshake.cols > 0) { 4974913cc679Smrg TRACE(("handshake read ttysize: %dx%d\n", 4975d522f475Smrg handshake.rows, handshake.cols)); 4976d522f475Smrg set_max_row(screen, handshake.rows); 4977d522f475Smrg set_max_col(screen, handshake.cols); 4978d522f475Smrg#ifdef TTYSIZE_STRUCT 4979d522f475Smrg got_handshake_size = True; 4980913cc679Smrg setup_winsize(ts, MaxRows(screen), MaxCols(screen), 4981913cc679Smrg FullHeight(screen), FullWidth(screen)); 4982913cc679Smrg trace_winsize(ts, "got handshake"); 4983d522f475Smrg#endif /* TTYSIZE_STRUCT */ 4984d522f475Smrg } 4985d522f475Smrg } 4986d522f475Smrg } 4987d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 4988d522f475Smrg 4989d522f475Smrg#ifdef USE_SYSV_ENVVARS 4990d522f475Smrg { 4991d522f475Smrg char numbuf[12]; 4992d522f475Smrg sprintf(numbuf, "%d", MaxCols(screen)); 4993d522f475Smrg xtermSetenv("COLUMNS", numbuf); 4994d522f475Smrg sprintf(numbuf, "%d", MaxRows(screen)); 4995d522f475Smrg xtermSetenv("LINES", numbuf); 4996d522f475Smrg } 4997d522f475Smrg#ifdef HAVE_UTMP 49980bd37d32Smrg if (OkPasswd(&pw)) { /* SVR4 doesn't provide these */ 4999d522f475Smrg if (!x_getenv("HOME")) 50000bd37d32Smrg xtermSetenv("HOME", pw.pw_dir); 5001d522f475Smrg if (!x_getenv("SHELL")) 50020bd37d32Smrg xtermSetenv("SHELL", pw.pw_shell); 5003d522f475Smrg } 5004d522f475Smrg#endif /* HAVE_UTMP */ 5005d522f475Smrg#else /* USE_SYSV_ENVVARS */ 500620d2c4d2Smrg if (*(newtc = get_tcap_buffer(xw)) != '\0') { 500720d2c4d2Smrg resize_termcap(xw); 500820d2c4d2Smrg if (xw->misc.titeInhibit && !xw->misc.tiXtraScroll) { 500920d2c4d2Smrg remove_termcap_entry(newtc, "ti="); 501020d2c4d2Smrg remove_termcap_entry(newtc, "te="); 501120d2c4d2Smrg } 501220d2c4d2Smrg /* 501320d2c4d2Smrg * work around broken termcap entries */ 501420d2c4d2Smrg if (resource.useInsertMode) { 501520d2c4d2Smrg remove_termcap_entry(newtc, "ic="); 501620d2c4d2Smrg /* don't get duplicates */ 501720d2c4d2Smrg remove_termcap_entry(newtc, "im="); 501820d2c4d2Smrg remove_termcap_entry(newtc, "ei="); 501920d2c4d2Smrg remove_termcap_entry(newtc, "mi"); 502020d2c4d2Smrg if (*newtc) 502120d2c4d2Smrg strcat(newtc, ":im=\\E[4h:ei=\\E[4l:mi:"); 502220d2c4d2Smrg } 502320d2c4d2Smrg if (*newtc) { 5024d522f475Smrg#if OPT_INITIAL_ERASE 502520d2c4d2Smrg unsigned len; 502620d2c4d2Smrg remove_termcap_entry(newtc, TERMCAP_ERASE "="); 502720d2c4d2Smrg len = (unsigned) strlen(newtc); 502820d2c4d2Smrg if (len != 0 && newtc[len - 1] == ':') 502920d2c4d2Smrg len--; 503020d2c4d2Smrg sprintf(newtc + len, ":%s=\\%03o:", 503120d2c4d2Smrg TERMCAP_ERASE, 503220d2c4d2Smrg CharOf(initial_erase)); 503320d2c4d2Smrg#endif 503420d2c4d2Smrg xtermSetenv("TERMCAP", newtc); 503520d2c4d2Smrg } 5036d522f475Smrg } 5037d522f475Smrg#endif /* USE_SYSV_ENVVARS */ 5038913cc679Smrg#ifdef OWN_TERMINFO_ENV 5039913cc679Smrg xtermSetenv("TERMINFO", OWN_TERMINFO_DIR); 5040913cc679Smrg#endif 5041d522f475Smrg 5042d522f475Smrg#if OPT_PTY_HANDSHAKE 5043d522f475Smrg /* 5044d522f475Smrg * Need to reset after all the ioctl bashing we did above. 5045d522f475Smrg * 5046d522f475Smrg * If we expect the waitForMap logic to set the handshake-size, 5047d522f475Smrg * use that to prevent races. 5048d522f475Smrg */ 5049913cc679Smrg TRACE(("should we reset screensize after pty-handshake?\n")); 5050913cc679Smrg TRACE(("... ptyHandshake :%d\n", resource.ptyHandshake)); 5051913cc679Smrg TRACE(("... ptySttySize :%d\n", resource.ptySttySize)); 5052913cc679Smrg TRACE(("... got_handshake_size:%d\n", got_handshake_size)); 5053913cc679Smrg TRACE(("... wait_for_map0 :%d\n", resource.wait_for_map0)); 5054d522f475Smrg if (resource.ptyHandshake 5055d522f475Smrg && resource.ptySttySize 5056d522f475Smrg && (got_handshake_size || !resource.wait_for_map0)) { 5057d522f475Smrg#ifdef TTYSIZE_STRUCT 505820d2c4d2Smrg TRACE_RC(i, SET_TTYSIZE(0, ts)); 5059913cc679Smrg trace_winsize(ts, "ptyHandshake SET_TTYSIZE"); 5060d522f475Smrg#endif /* TTYSIZE_STRUCT */ 5061d522f475Smrg } 5062d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 5063d522f475Smrg signal(SIGHUP, SIG_DFL); 5064d522f475Smrg 50650bd37d32Smrg /* 5066e0a2b6dfSmrg * If we have an explicit shell to run, make that set $SHELL. 5067e0a2b6dfSmrg * Next, allow an existing setting of $SHELL, for absolute paths. 50680bd37d32Smrg * Otherwise, if $SHELL is not set, determine it from the user's 50690bd37d32Smrg * password information, if possible. 50700bd37d32Smrg * 50710bd37d32Smrg * Incidentally, our setting of $SHELL tells luit to use that 50720bd37d32Smrg * program rather than choosing between $SHELL and "/bin/sh". 50730bd37d32Smrg */ 5074e0a2b6dfSmrg if (validShell(explicit_shname)) { 5075e0a2b6dfSmrg xtermSetenv("SHELL", explicit_shname); 5076e0a2b6dfSmrg } else if (validProgram(shell_path = x_getenv("SHELL"))) { 5077e0a2b6dfSmrg if (!validShell(shell_path)) { 5078e0a2b6dfSmrg xtermUnsetenv("SHELL"); 5079d522f475Smrg } 5080e0a2b6dfSmrg } else if ((!OkPasswd(&pw) && !x_getpwuid(screen->uid, &pw)) 5081e0a2b6dfSmrg || *(shell_path = x_strdup(pw.pw_shell)) == 0) { 5082e0a2b6dfSmrg shell_path = resetShell(shell_path); 5083e0a2b6dfSmrg } else if (validShell(shell_path)) { 5084e0a2b6dfSmrg xtermSetenv("SHELL", shell_path); 5085d522f475Smrg } else { 5086e0a2b6dfSmrg shell_path = resetShell(shell_path); 5087d522f475Smrg } 5088e0a2b6dfSmrg 5089e0a2b6dfSmrg /* 5090e0a2b6dfSmrg * Set $XTERM_SHELL, which is not necessarily a valid shell, but 5091e0a2b6dfSmrg * is executable. 5092e0a2b6dfSmrg */ 5093e0a2b6dfSmrg if (validProgram(explicit_shname)) { 5094e0a2b6dfSmrg shell_path = explicit_shname; 5095e0a2b6dfSmrg } else if (shell_path == 0) { 5096e0a2b6dfSmrg /* this could happen if the explicit shname lost a race */ 5097e0a2b6dfSmrg shell_path = resetShell(shell_path); 50980bd37d32Smrg } 50990bd37d32Smrg xtermSetenv("XTERM_SHELL", shell_path); 5100d522f475Smrg 51010bd37d32Smrg shname = x_basename(shell_path); 51020bd37d32Smrg TRACE(("shell path '%s' leaf '%s'\n", shell_path, shname)); 5103d522f475Smrg 5104d522f475Smrg#if OPT_LUIT_PROG 5105d522f475Smrg /* 5106d522f475Smrg * Use two copies of command_to_exec, in case luit is not actually 5107d522f475Smrg * there, or refuses to run. In that case we will fall-through to 5108d522f475Smrg * to command that the user gave anyway. 5109d522f475Smrg */ 51102eaa94a1Schristos if (command_to_exec_with_luit && command_to_exec) { 51110bd37d32Smrg char *myShell = xtermFindShell(*command_to_exec_with_luit, False); 51120bd37d32Smrg xtermSetenv("XTERM_SHELL", myShell); 51130bd37d32Smrg free(myShell); 51140bd37d32Smrg TRACE_ARGV("spawning luit command", command_to_exec_with_luit); 5115d522f475Smrg execvp(*command_to_exec_with_luit, command_to_exec_with_luit); 51160bd37d32Smrg xtermPerror("Can't execvp %s", *command_to_exec_with_luit); 51170bd37d32Smrg xtermWarning("cannot support your locale.\n"); 5118d522f475Smrg } 5119d522f475Smrg#endif 5120d522f475Smrg if (command_to_exec) { 51210bd37d32Smrg char *myShell = xtermFindShell(*command_to_exec, False); 51220bd37d32Smrg xtermSetenv("XTERM_SHELL", myShell); 51230bd37d32Smrg free(myShell); 51240bd37d32Smrg TRACE_ARGV("spawning command", command_to_exec); 5125d522f475Smrg execvp(*command_to_exec, command_to_exec); 5126d522f475Smrg if (command_to_exec[1] == 0) 51270bd37d32Smrg execlp(shell_path, shname, "-c", command_to_exec[0], 51280bd37d32Smrg (void *) 0); 51290bd37d32Smrg xtermPerror("Can't execvp %s", *command_to_exec); 5130d522f475Smrg } 5131d522f475Smrg#ifdef USE_SYSV_SIGHUP 5132d522f475Smrg /* fix pts sh hanging around */ 5133d522f475Smrg signal(SIGHUP, SIG_DFL); 5134d522f475Smrg#endif 5135d522f475Smrg 5136f2e35a3aSmrg if ((shname_minus = malloc(strlen(shname) + 2)) != 0) { 513701037d57Smrg (void) strcpy(shname_minus, "-"); 513801037d57Smrg (void) strcat(shname_minus, shname); 513901037d57Smrg } else { 514001037d57Smrg static char default_minus[] = "-sh"; 514101037d57Smrg shname_minus = default_minus; 514201037d57Smrg } 5143d522f475Smrg#ifndef TERMIO_STRUCT 51440bd37d32Smrg ldisc = (!XStrCmp("csh", shname + strlen(shname) - 3) 51450bd37d32Smrg ? NTTYDISC 51460bd37d32Smrg : 0); 5147d522f475Smrg ioctl(0, TIOCSETD, (char *) &ldisc); 5148d522f475Smrg#endif /* !TERMIO_STRUCT */ 5149d522f475Smrg 5150d522f475Smrg#ifdef USE_LOGIN_DASH_P 51510bd37d32Smrg if (xw->misc.login_shell && OkPasswd(&pw) && added_utmp_entry) 5152d522f475Smrg execl(bin_login, "login", "-p", "-f", login_name, (void *) 0); 5153d522f475Smrg#endif 51542eaa94a1Schristos 51552eaa94a1Schristos#if OPT_LUIT_PROG 51562eaa94a1Schristos if (command_to_exec_with_luit) { 51572eaa94a1Schristos if (xw->misc.login_shell) { 51580bd37d32Smrg char *params[4]; 51590bd37d32Smrg params[0] = x_strdup("-argv0"); 51600bd37d32Smrg params[1] = shname_minus; 51610bd37d32Smrg params[2] = NULL; 51620bd37d32Smrg x_appendargv(command_to_exec_with_luit 51630bd37d32Smrg + command_length_with_luit, 51640bd37d32Smrg params); 51652eaa94a1Schristos } 51660bd37d32Smrg TRACE_ARGV("final luit command", command_to_exec_with_luit); 51672eaa94a1Schristos execvp(*command_to_exec_with_luit, command_to_exec_with_luit); 51682eaa94a1Schristos /* Exec failed. */ 51690bd37d32Smrg xtermPerror("Can't execvp %s", *command_to_exec_with_luit); 51702eaa94a1Schristos } 51712eaa94a1Schristos#endif 51720bd37d32Smrg execlp(shell_path, 5173d522f475Smrg (xw->misc.login_shell ? shname_minus : shname), 5174d522f475Smrg (void *) 0); 5175d522f475Smrg 5176d522f475Smrg /* Exec failed. */ 51770bd37d32Smrg xtermPerror("Could not exec %s", shell_path); 517820d2c4d2Smrg IGNORE_RC(sleep(5)); 51790bd37d32Smrg free(shell_path); 5180d522f475Smrg exit(ERROR_EXEC); 5181d522f475Smrg } 5182d522f475Smrg /* end if in child after fork */ 5183d522f475Smrg#if OPT_PTY_HANDSHAKE 5184d522f475Smrg if (resource.ptyHandshake) { 5185d522f475Smrg /* Parent process. Let's handle handshaked requests to our 5186d522f475Smrg * child process. 5187d522f475Smrg */ 5188d522f475Smrg 5189d522f475Smrg /* close childs's sides of the pipes */ 5190d522f475Smrg close(cp_pipe[1]); 5191d522f475Smrg close(pc_pipe[0]); 5192d522f475Smrg 5193d522f475Smrg for (done = 0; !done;) { 5194d522f475Smrg if (read(cp_pipe[0], 5195d522f475Smrg (char *) &handshake, 5196d522f475Smrg sizeof(handshake)) <= 0) { 5197d522f475Smrg /* Our child is done talking to us. If it terminated 5198d522f475Smrg * due to an error, we will catch the death of child 5199d522f475Smrg * and clean up. 5200d522f475Smrg */ 5201d522f475Smrg break; 5202d522f475Smrg } 5203d522f475Smrg 5204d522f475Smrg TRACE_HANDSHAKE("read", &handshake); 5205d522f475Smrg switch (handshake.status) { 5206d522f475Smrg case PTY_GOOD: 5207d522f475Smrg /* Success! Let's free up resources and 5208d522f475Smrg * continue. 5209d522f475Smrg */ 5210d522f475Smrg done = 1; 5211d522f475Smrg break; 5212d522f475Smrg 5213d522f475Smrg case PTY_BAD: 5214d522f475Smrg /* The open of the pty failed! Let's get 5215d522f475Smrg * another one. 5216d522f475Smrg */ 521720d2c4d2Smrg IGNORE_RC(close(screen->respond)); 5218d522f475Smrg if (get_pty(&screen->respond, XDisplayString(screen->display))) { 5219d522f475Smrg /* no more ptys! */ 52200bd37d32Smrg xtermPerror("child process can find no available ptys"); 5221d522f475Smrg handshake.status = PTY_NOMORE; 5222d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 522320d2c4d2Smrg IGNORE_RC(write(pc_pipe[1], 522420d2c4d2Smrg (const char *) &handshake, 522520d2c4d2Smrg sizeof(handshake))); 5226d522f475Smrg exit(ERROR_PTYS); 5227d522f475Smrg } 5228d522f475Smrg handshake.status = PTY_NEW; 5229f2e35a3aSmrg copy_handshake(handshake, ttydev); 5230d522f475Smrg TRACE_HANDSHAKE("writing", &handshake); 523120d2c4d2Smrg IGNORE_RC(write(pc_pipe[1], 523220d2c4d2Smrg (const char *) &handshake, 523320d2c4d2Smrg sizeof(handshake))); 5234d522f475Smrg break; 5235d522f475Smrg 5236d522f475Smrg case PTY_FATALERROR: 5237d522f475Smrg errno = handshake.error; 5238d522f475Smrg close(cp_pipe[0]); 5239d522f475Smrg close(pc_pipe[1]); 5240d522f475Smrg SysError(handshake.fatal_error); 5241d522f475Smrg /*NOTREACHED */ 5242d522f475Smrg 5243d522f475Smrg case UTMP_ADDED: 5244d522f475Smrg /* The utmp entry was set by our slave. Remember 5245d522f475Smrg * this so that we can reset it later. 5246d522f475Smrg */ 5247d522f475Smrg added_utmp_entry = True; 5248d522f475Smrg#ifndef USE_SYSV_UTMP 5249d522f475Smrg tslot = handshake.tty_slot; 5250d522f475Smrg#endif /* USE_SYSV_UTMP */ 5251d522f475Smrg free(ttydev); 5252f2e35a3aSmrg handshake.buffer[HANDSHAKE_LEN - 1] = '\0'; 5253d522f475Smrg ttydev = x_strdup(handshake.buffer); 5254d522f475Smrg break; 5255d522f475Smrg case PTY_NEW: 5256d522f475Smrg case PTY_NOMORE: 5257d522f475Smrg case UTMP_TTYSLOT: 5258d522f475Smrg case PTY_EXEC: 5259d522f475Smrg default: 52600bd37d32Smrg xtermWarning("unexpected handshake status %d\n", 52610bd37d32Smrg (int) handshake.status); 5262d522f475Smrg } 5263d522f475Smrg } 5264d522f475Smrg /* close our sides of the pipes */ 5265d522f475Smrg if (!resource.wait_for_map) { 5266d522f475Smrg close(cp_pipe[0]); 5267d522f475Smrg close(pc_pipe[1]); 5268d522f475Smrg } 5269d522f475Smrg } 5270d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 5271d522f475Smrg } 5272d522f475Smrg 5273d522f475Smrg /* end if no slave */ 5274d522f475Smrg /* 5275d522f475Smrg * still in parent (xterm process) 5276d522f475Smrg */ 5277d522f475Smrg#ifdef USE_SYSV_SIGHUP 5278d522f475Smrg /* hung sh problem? */ 5279d522f475Smrg signal(SIGHUP, SIG_DFL); 5280d522f475Smrg#else 5281d522f475Smrg signal(SIGHUP, SIG_IGN); 5282d522f475Smrg#endif 5283d522f475Smrg 5284d522f475Smrg/* 5285d522f475Smrg * Unfortunately, System V seems to have trouble divorcing the child process 5286d522f475Smrg * from the process group of xterm. This is a problem because hitting the 5287d522f475Smrg * INTR or QUIT characters on the keyboard will cause xterm to go away if we 5288d522f475Smrg * don't ignore the signals. This is annoying. 5289d522f475Smrg */ 5290d522f475Smrg 5291d522f475Smrg#if defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP) 5292d522f475Smrg signal(SIGINT, SIG_IGN); 5293d522f475Smrg 5294d522f475Smrg#ifndef SYSV 5295d522f475Smrg /* hung shell problem */ 5296d522f475Smrg signal(SIGQUIT, SIG_IGN); 5297d522f475Smrg#endif 5298d522f475Smrg signal(SIGTERM, SIG_IGN); 5299d522f475Smrg#elif defined(SYSV) || defined(__osf__) 5300d522f475Smrg /* if we were spawned by a jobcontrol smart shell (like ksh or csh), 5301d522f475Smrg * then our pgrp and pid will be the same. If we were spawned by 5302d522f475Smrg * a jobcontrol dumb shell (like /bin/sh), then we will be in our 5303d522f475Smrg * parent's pgrp, and we must ignore keyboard signals, or we will 5304d522f475Smrg * tank on everything. 5305d522f475Smrg */ 5306d522f475Smrg if (getpid() == getpgrp()) { 5307d522f475Smrg (void) signal(SIGINT, Exit); 5308d522f475Smrg (void) signal(SIGQUIT, Exit); 5309d522f475Smrg (void) signal(SIGTERM, Exit); 5310d522f475Smrg } else { 5311d522f475Smrg (void) signal(SIGINT, SIG_IGN); 5312d522f475Smrg (void) signal(SIGQUIT, SIG_IGN); 5313d522f475Smrg (void) signal(SIGTERM, SIG_IGN); 5314d522f475Smrg } 5315d522f475Smrg (void) signal(SIGPIPE, Exit); 5316d522f475Smrg#else /* SYSV */ 5317d522f475Smrg signal(SIGINT, Exit); 5318d522f475Smrg signal(SIGQUIT, Exit); 5319d522f475Smrg signal(SIGTERM, Exit); 5320d522f475Smrg signal(SIGPIPE, Exit); 5321d522f475Smrg#endif /* USE_SYSV_SIGNALS and not SIGTSTP */ 53220bd37d32Smrg#ifdef NO_LEAKS 53230bd37d32Smrg if (ok_termcap != True) 53240bd37d32Smrg free(TermName); 53250bd37d32Smrg#endif 5326d522f475Smrg 5327d522f475Smrg return 0; 5328d522f475Smrg} /* end spawnXTerm */ 5329d522f475Smrg 53300bd37d32Smrgvoid 5331d522f475SmrgExit(int n) 5332d522f475Smrg{ 533320d2c4d2Smrg XtermWidget xw = term; 533420d2c4d2Smrg TScreen *screen = TScreenOf(xw); 5335d522f475Smrg 5336d522f475Smrg#ifdef USE_UTEMPTER 53370bd37d32Smrg DEBUG_MSG("handle:Exit USE_UTEMPTER\n"); 53380bd37d32Smrg if (!resource.utmpInhibit && added_utmp_entry) { 53390bd37d32Smrg TRACE(("...calling removeFromUtmp\n")); 5340f2e35a3aSmrg UTEMPTER_DEL(); 53410bd37d32Smrg } 5342d522f475Smrg#elif defined(HAVE_UTMP) 5343d522f475Smrg#ifdef USE_SYSV_UTMP 5344d522f475Smrg struct UTMP_STR utmp; 5345d522f475Smrg struct UTMP_STR *utptr; 5346d522f475Smrg 53470bd37d32Smrg DEBUG_MSG("handle:Exit USE_SYSV_UTMP\n"); 5348d522f475Smrg /* don't do this more than once */ 53490bd37d32Smrg if (xterm_exiting) { 53500bd37d32Smrg exit(n); 53510bd37d32Smrg } 5352d522f475Smrg xterm_exiting = True; 5353d522f475Smrg 5354d522f475Smrg#ifdef PUCC_PTYD 5355d522f475Smrg closepty(ttydev, ptydev, (resource.utmpInhibit ? OPTY_NOP : OPTY_LOGIN), screen->respond); 5356d522f475Smrg#endif /* PUCC_PTYD */ 5357d522f475Smrg 5358d522f475Smrg /* cleanup the utmp entry we forged earlier */ 5359d522f475Smrg if (!resource.utmpInhibit 5360d522f475Smrg#if OPT_PTY_HANDSHAKE /* without handshake, no way to know */ 5361d522f475Smrg && (resource.ptyHandshake && added_utmp_entry) 5362d522f475Smrg#endif /* OPT_PTY_HANDSHAKE */ 5363d522f475Smrg ) { 5364d522f475Smrg#if defined(USE_UTMP_SETGID) 5365d522f475Smrg setEffectiveGroup(save_egid); 5366d522f475Smrg TRACE_IDS; 5367d522f475Smrg#endif 5368d522f475Smrg init_utmp(USER_PROCESS, &utmp); 5369d522f475Smrg (void) call_setutent(); 5370d522f475Smrg 5371d522f475Smrg /* 5372d522f475Smrg * We could use getutline() if we didn't support old systems. 5373d522f475Smrg */ 5374d522f475Smrg while ((utptr = find_utmp(&utmp)) != 0) { 5375d522f475Smrg if (utptr->ut_pid == screen->pid) { 5376d522f475Smrg utptr->ut_type = DEAD_PROCESS; 5377d522f475Smrg#if defined(HAVE_UTMP_UT_XTIME) 5378d522f475Smrg#if defined(HAVE_UTMP_UT_SESSION) 5379d522f475Smrg utptr->ut_session = getsid(0); 5380d522f475Smrg#endif 5381d522f475Smrg utptr->ut_xtime = time((time_t *) 0); 5382d522f475Smrg utptr->ut_tv.tv_usec = 0; 5383d522f475Smrg#else 5384d522f475Smrg *utptr->ut_user = 0; 5385d522f475Smrg utptr->ut_time = time((time_t *) 0); 5386d522f475Smrg#endif 5387d522f475Smrg (void) call_pututline(utptr); 5388d522f475Smrg#ifdef WTMP 5389d522f475Smrg#if defined(WTMPX_FILE) && (defined(SVR4) || defined(__SCO__)) 539020d2c4d2Smrg if (xw->misc.login_shell) 5391d522f475Smrg updwtmpx(WTMPX_FILE, utptr); 5392d522f475Smrg#elif defined(linux) && defined(__GLIBC__) && (__GLIBC__ >= 2) && !(defined(__powerpc__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)) 5393894e0ac8Smrg copy_filled(utmp.ut_line, utptr->ut_line, sizeof(utmp.ut_line)); 539420d2c4d2Smrg if (xw->misc.login_shell) 5395d522f475Smrg call_updwtmp(etc_wtmp, utptr); 5396d522f475Smrg#else 5397d522f475Smrg /* set wtmp entry if wtmp file exists */ 539820d2c4d2Smrg if (xw->misc.login_shell) { 5399d522f475Smrg int fd; 5400d522f475Smrg if ((fd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 54010bd37d32Smrg IGNORE_RC(write(fd, utptr, sizeof(*utptr))); 5402d522f475Smrg close(fd); 5403d522f475Smrg } 5404d522f475Smrg } 5405d522f475Smrg#endif 5406d522f475Smrg#endif 5407d522f475Smrg break; 5408d522f475Smrg } 5409d522f475Smrg memset(utptr, 0, sizeof(*utptr)); /* keep searching */ 5410d522f475Smrg } 5411d522f475Smrg (void) call_endutent(); 5412d522f475Smrg#ifdef USE_UTMP_SETGID 5413d522f475Smrg disableSetGid(); 5414d522f475Smrg TRACE_IDS; 5415d522f475Smrg#endif 5416d522f475Smrg } 5417d522f475Smrg#else /* not USE_SYSV_UTMP */ 5418d522f475Smrg int wfd; 5419d522f475Smrg struct utmp utmp; 5420d522f475Smrg 54210bd37d32Smrg DEBUG_MSG("handle:Exit !USE_SYSV_UTMP\n"); 5422d522f475Smrg if (!resource.utmpInhibit && added_utmp_entry && 5423d522f475Smrg (am_slave < 0 && tslot > 0)) { 5424d522f475Smrg#if defined(USE_UTMP_SETGID) 5425d522f475Smrg setEffectiveGroup(save_egid); 5426d522f475Smrg TRACE_IDS; 5427d522f475Smrg#endif 5428d522f475Smrg if ((wfd = open(etc_utmp, O_WRONLY)) >= 0) { 5429956cc18dSsnj memset(&utmp, 0, sizeof(utmp)); 5430d522f475Smrg lseek(wfd, (long) (tslot * sizeof(utmp)), 0); 54310bd37d32Smrg IGNORE_RC(write(wfd, (char *) &utmp, sizeof(utmp))); 5432d522f475Smrg close(wfd); 5433d522f475Smrg } 5434d522f475Smrg#ifdef WTMP 543520d2c4d2Smrg if (xw->misc.login_shell && 5436d522f475Smrg (wfd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) { 5437894e0ac8Smrg copy_filled(utmp.ut_line, 5438894e0ac8Smrg my_pty_name(ttydev), 5439894e0ac8Smrg sizeof(utmp.ut_line)); 5440d522f475Smrg utmp.ut_time = time((time_t *) 0); 54410bd37d32Smrg IGNORE_RC(write(wfd, (char *) &utmp, sizeof(utmp))); 5442d522f475Smrg close(wfd); 5443d522f475Smrg } 5444d522f475Smrg#endif /* WTMP */ 5445d522f475Smrg#ifdef USE_UTMP_SETGID 5446d522f475Smrg disableSetGid(); 5447d522f475Smrg TRACE_IDS; 5448d522f475Smrg#endif 5449d522f475Smrg } 5450d522f475Smrg#endif /* USE_SYSV_UTMP */ 5451d522f475Smrg#endif /* HAVE_UTMP */ 5452d522f475Smrg 5453e0a2b6dfSmrg cleanup_colored_cursor(); 5454e0a2b6dfSmrg 5455d522f475Smrg /* 5456d522f475Smrg * Flush pending data before releasing ownership, so nobody else can write 5457d522f475Smrg * in the middle of the data. 5458d522f475Smrg */ 5459d522f475Smrg ttyFlush(screen->respond); 5460d522f475Smrg 5461e39b573cSmrg#ifdef USE_PTY_SEARCH 5462d522f475Smrg if (am_slave < 0) { 5463d522f475Smrg TRACE_IDS; 5464d522f475Smrg /* restore ownership of tty and pty */ 5465d522f475Smrg set_owner(ttydev, 0, 0, 0666U); 5466d522f475Smrg#if (defined(USE_PTY_DEVICE) && !defined(__sgi) && !defined(__hpux)) 5467d522f475Smrg set_owner(ptydev, 0, 0, 0666U); 5468d522f475Smrg#endif 5469d522f475Smrg } 5470e39b573cSmrg#endif 5471d522f475Smrg 5472d522f475Smrg /* 54730bd37d32Smrg * Close after releasing ownership to avoid race condition: other programs 5474d522f475Smrg * grabbing it, and *then* having us release ownership.... 5475d522f475Smrg */ 5476d522f475Smrg close(screen->respond); /* close explicitly to avoid race with slave side */ 5477d522f475Smrg#ifdef ALLOWLOGGING 5478d522f475Smrg if (screen->logging) 547920d2c4d2Smrg CloseLog(xw); 5480d522f475Smrg#endif 5481d522f475Smrg 5482e39b573cSmrg xtermPrintOnXError(xw, n); 5483e39b573cSmrg 5484d522f475Smrg#ifdef NO_LEAKS 5485d522f475Smrg if (n == 0) { 54860bd37d32Smrg Display *dpy = TScreenOf(xw)->display; 54870bd37d32Smrg 5488d522f475Smrg TRACE(("Freeing memory leaks\n")); 5489d522f475Smrg 54900bd37d32Smrg if (toplevel) { 54910bd37d32Smrg XtDestroyWidget(toplevel); 54920bd37d32Smrg TRACE(("destroyed top-level widget\n")); 54930bd37d32Smrg } 54940bd37d32Smrg sortedOpts(0, 0, 0); 54950bd37d32Smrg noleaks_charproc(); 54960bd37d32Smrg noleaks_ptydata(); 5497894e0ac8Smrg#if OPT_GRAPHICS 54984419d26bSmrg noleaks_graphics(dpy); 5499894e0ac8Smrg#endif 5500d522f475Smrg#if OPT_WIDE_CHARS 55010bd37d32Smrg noleaks_CharacterClass(); 5502d522f475Smrg#endif 55030bd37d32Smrg /* XrmSetDatabase(dpy, 0); increases leaks ;-) */ 55040bd37d32Smrg XtCloseDisplay(dpy); 55050bd37d32Smrg XtDestroyApplicationContext(app_con); 55060bd37d32Smrg xtermCloseSession(); 55070bd37d32Smrg TRACE(("closed display\n")); 55080bd37d32Smrg 550920d2c4d2Smrg TRACE_CLOSE(); 5510d522f475Smrg } 5511d522f475Smrg#endif 5512d522f475Smrg 5513d522f475Smrg exit(n); 5514d522f475Smrg} 5515d522f475Smrg 5516d522f475Smrg/* ARGSUSED */ 5517d522f475Smrgstatic void 551820d2c4d2Smrgresize_termcap(XtermWidget xw) 5519d522f475Smrg{ 552020d2c4d2Smrg char *newtc = get_tcap_buffer(xw); 552120d2c4d2Smrg 5522d522f475Smrg#ifndef USE_SYSV_ENVVARS 5523d522f475Smrg if (!TEK4014_ACTIVE(xw) && *newtc) { 5524d522f475Smrg TScreen *screen = TScreenOf(xw); 5525d522f475Smrg char *ptr1, *ptr2; 5526d522f475Smrg size_t i; 5527d522f475Smrg int li_first = 0; 5528d522f475Smrg char *temp; 5529d522f475Smrg char oldtc[TERMCAP_SIZE]; 5530d522f475Smrg 5531d522f475Smrg strcpy(oldtc, newtc); 5532d522f475Smrg TRACE(("resize %s\n", oldtc)); 5533d522f475Smrg if ((ptr1 = x_strindex(oldtc, "co#")) == NULL) { 5534d522f475Smrg strcat(oldtc, "co#80:"); 5535d522f475Smrg ptr1 = x_strindex(oldtc, "co#"); 5536d522f475Smrg } 5537d522f475Smrg if ((ptr2 = x_strindex(oldtc, "li#")) == NULL) { 5538d522f475Smrg strcat(oldtc, "li#24:"); 5539d522f475Smrg ptr2 = x_strindex(oldtc, "li#"); 5540d522f475Smrg } 5541d522f475Smrg if (ptr1 > ptr2) { 5542d522f475Smrg li_first++; 5543d522f475Smrg temp = ptr1; 5544d522f475Smrg ptr1 = ptr2; 5545d522f475Smrg ptr2 = temp; 5546d522f475Smrg } 5547d522f475Smrg ptr1 += 3; 5548d522f475Smrg ptr2 += 3; 5549956cc18dSsnj strncpy(newtc, oldtc, i = (size_t) (ptr1 - oldtc)); 5550d522f475Smrg temp = newtc + i; 5551d522f475Smrg sprintf(temp, "%d", (li_first 5552d522f475Smrg ? MaxRows(screen) 5553d522f475Smrg : MaxCols(screen))); 5554d522f475Smrg temp += strlen(temp); 55550bd37d32Smrg if ((ptr1 = strchr(ptr1, ':')) != 0 && (ptr1 < ptr2)) { 55560bd37d32Smrg strncpy(temp, ptr1, i = (size_t) (ptr2 - ptr1)); 55570bd37d32Smrg temp += i; 55580bd37d32Smrg sprintf(temp, "%d", (li_first 55590bd37d32Smrg ? MaxCols(screen) 55600bd37d32Smrg : MaxRows(screen))); 55610bd37d32Smrg if ((ptr2 = strchr(ptr2, ':')) != 0) { 55620bd37d32Smrg strcat(temp, ptr2); 55630bd37d32Smrg } 55640bd37d32Smrg } 5565d522f475Smrg TRACE((" ==> %s\n", newtc)); 5566d522f475Smrg TRACE((" new size %dx%d\n", MaxRows(screen), MaxCols(screen))); 5567d522f475Smrg } 5568d522f475Smrg#endif /* USE_SYSV_ENVVARS */ 5569d522f475Smrg} 5570d522f475Smrg 5571d522f475Smrg#endif /* ! VMS */ 5572d522f475Smrg 5573d522f475Smrg/* 5574d522f475Smrg * Does a non-blocking wait for a child process. If the system 5575d522f475Smrg * doesn't support non-blocking wait, do nothing. 5576d522f475Smrg * Returns the pid of the child, or 0 or -1 if none or error. 5577d522f475Smrg */ 5578d522f475Smrgint 5579d522f475Smrgnonblocking_wait(void) 5580d522f475Smrg{ 5581d522f475Smrg#ifdef USE_POSIX_WAIT 5582d522f475Smrg pid_t pid; 5583d522f475Smrg 5584d522f475Smrg pid = waitpid(-1, NULL, WNOHANG); 5585d522f475Smrg#elif defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP)) 5586d522f475Smrg /* cannot do non-blocking wait */ 5587d522f475Smrg int pid = 0; 5588d522f475Smrg#else /* defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP)) */ 5589d522f475Smrg#if defined(Lynx) 5590d522f475Smrg int status; 5591d522f475Smrg#else 5592d522f475Smrg union wait status; 5593d522f475Smrg#endif 5594d522f475Smrg int pid; 5595d522f475Smrg 5596d522f475Smrg pid = wait3(&status, WNOHANG, (struct rusage *) NULL); 5597d522f475Smrg#endif /* USE_POSIX_WAIT else */ 5598d522f475Smrg return pid; 5599d522f475Smrg} 5600d522f475Smrg 5601d522f475Smrg#ifndef VMS 5602d522f475Smrg 5603d522f475Smrg/* ARGSUSED */ 56040bd37d32Smrgstatic void 5605d522f475Smrgreapchild(int n GCC_UNUSED) 5606d522f475Smrg{ 5607d522f475Smrg int olderrno = errno; 5608d522f475Smrg int pid; 5609d522f475Smrg 56100bd37d32Smrg DEBUG_MSG("handle:reapchild\n"); 56110bd37d32Smrg 5612d522f475Smrg pid = wait(NULL); 5613d522f475Smrg 5614d522f475Smrg#ifdef USE_SYSV_SIGNALS 5615d522f475Smrg /* cannot re-enable signal before waiting for child 5616d522f475Smrg * because then SVR4 loops. Sigh. HP-UX 9.01 too. 5617d522f475Smrg */ 5618d522f475Smrg (void) signal(SIGCHLD, reapchild); 5619d522f475Smrg#endif 5620d522f475Smrg 5621d522f475Smrg do { 562220d2c4d2Smrg if (pid == TScreenOf(term)->pid) { 56230bd37d32Smrg DEBUG_MSG("Exiting\n"); 56242e4f8982Smrg if (hold_screen) 56252e4f8982Smrg caught_intr = True; 56262e4f8982Smrg else 5627d522f475Smrg need_cleanup = True; 5628d522f475Smrg } 5629d522f475Smrg } while ((pid = nonblocking_wait()) > 0); 5630d522f475Smrg 5631d522f475Smrg errno = olderrno; 5632d522f475Smrg} 5633d522f475Smrg#endif /* !VMS */ 5634d522f475Smrg 5635d522f475Smrgstatic void 563620d2c4d2Smrgremove_termcap_entry(char *buf, const char *str) 5637d522f475Smrg{ 5638d522f475Smrg char *base = buf; 5639d522f475Smrg char *first = base; 5640d522f475Smrg int count = 0; 5641d522f475Smrg size_t len = strlen(str); 5642d522f475Smrg 5643d522f475Smrg TRACE(("*** remove_termcap_entry('%s', '%s')\n", str, buf)); 5644d522f475Smrg 5645d522f475Smrg while (*buf != 0) { 5646d522f475Smrg if (!count && !strncmp(buf, str, len)) { 5647d522f475Smrg while (*buf != 0) { 5648d522f475Smrg if (*buf == '\\') 5649d522f475Smrg buf++; 5650d522f475Smrg else if (*buf == ':') 5651d522f475Smrg break; 5652d522f475Smrg if (*buf != 0) 5653d522f475Smrg buf++; 5654d522f475Smrg } 56550bd37d32Smrg while ((*first++ = *buf++) != 0) { 56560bd37d32Smrg ; 56570bd37d32Smrg } 5658d522f475Smrg TRACE(("...removed_termcap_entry('%s', '%s')\n", str, base)); 5659d522f475Smrg return; 5660d522f475Smrg } else if (*buf == '\\') { 5661d522f475Smrg buf++; 5662d522f475Smrg } else if (*buf == ':') { 5663d522f475Smrg first = buf; 5664d522f475Smrg count = 0; 5665d522f475Smrg } else if (!isspace(CharOf(*buf))) { 5666d522f475Smrg count++; 5667d522f475Smrg } 5668d522f475Smrg if (*buf != 0) 5669d522f475Smrg buf++; 5670d522f475Smrg } 5671d522f475Smrg TRACE(("...cannot remove\n")); 5672d522f475Smrg} 5673d522f475Smrg 5674d522f475Smrg/* 5675d522f475Smrg * parse_tty_modes accepts lines of the following form: 5676d522f475Smrg * 5677d522f475Smrg * [SETTING] ... 5678d522f475Smrg * 5679f2e35a3aSmrg * where setting consists of the words in the ttyModes[] array followed by a 5680f2e35a3aSmrg * character or ^char. 5681d522f475Smrg */ 5682d522f475Smrgstatic int 5683f2e35a3aSmrgparse_tty_modes(char *s) 5684d522f475Smrg{ 5685d522f475Smrg int c; 5686f2e35a3aSmrg Cardinal j, k; 5687d522f475Smrg int count = 0; 5688f2e35a3aSmrg Boolean found; 5689d522f475Smrg 5690d522f475Smrg TRACE(("parse_tty_modes\n")); 5691a1f3da82Smrg for (;;) { 5692d522f475Smrg size_t len; 5693d522f475Smrg 5694f2e35a3aSmrg while (*s && isspace(CharOf(*s))) { 5695d522f475Smrg s++; 5696f2e35a3aSmrg } 5697f2e35a3aSmrg if (!*s) { 5698d522f475Smrg return count; 5699f2e35a3aSmrg } 5700d522f475Smrg 5701f2e35a3aSmrg for (len = 0; s[len] && !isspace(CharOf(s[len])); ++len) { 5702f2e35a3aSmrg ; 5703f2e35a3aSmrg } 5704f2e35a3aSmrg found = False; 5705f2e35a3aSmrg for (j = 0; j < XtNumber(ttyModes); ++j) { 5706f2e35a3aSmrg if (len == ttyModes[j].len 5707f2e35a3aSmrg && strncmp(s, 5708f2e35a3aSmrg ttyModes[j].name, 5709f2e35a3aSmrg ttyModes[j].len) == 0) { 5710f2e35a3aSmrg found = True; 5711d522f475Smrg break; 5712f2e35a3aSmrg } 5713d522f475Smrg } 5714f2e35a3aSmrg if (!found) { 5715d522f475Smrg return -1; 5716f2e35a3aSmrg } 5717d522f475Smrg 5718f2e35a3aSmrg s += ttyModes[j].len; 5719f2e35a3aSmrg while (*s && isspace(CharOf(*s))) { 5720d522f475Smrg s++; 5721f2e35a3aSmrg } 5722d522f475Smrg 5723f2e35a3aSmrg /* check if this needs a parameter */ 5724f2e35a3aSmrg found = False; 5725f2e35a3aSmrg for (k = 0, c = 0; k < XtNumber(ttyChars); ++k) { 5726f2e35a3aSmrg if ((int) j == ttyChars[k].myMode) { 5727f2e35a3aSmrg if (ttyChars[k].sysMode < 0) { 5728f2e35a3aSmrg found = True; 5729f2e35a3aSmrg c = ttyChars[k].myDefault; 5730f2e35a3aSmrg } 5731f2e35a3aSmrg break; 5732f2e35a3aSmrg } 5733f2e35a3aSmrg } 5734f2e35a3aSmrg 5735f2e35a3aSmrg if (!found) { 5736f2e35a3aSmrg if (!*s 5737f2e35a3aSmrg || (c = decode_keyvalue(&s, False)) == -1) { 5738f2e35a3aSmrg return -1; 5739f2e35a3aSmrg } 5740d522f475Smrg } 5741f2e35a3aSmrg ttyModes[j].value = c; 5742f2e35a3aSmrg ttyModes[j].set = 1; 5743f2e35a3aSmrg count++; 5744f2e35a3aSmrg TRACE(("...parsed #%d: %s=%#x\n", count, ttyModes[j].name, c)); 5745d522f475Smrg } 5746d522f475Smrg} 5747d522f475Smrg 5748d522f475Smrg#ifndef VMS /* don't use pipes on OpenVMS */ 5749d522f475Smrgint 5750d522f475SmrgGetBytesAvailable(int fd) 5751d522f475Smrg{ 5752d522f475Smrg#if defined(FIONREAD) 5753d522f475Smrg int arg; 5754d522f475Smrg ioctl(fd, FIONREAD, (char *) &arg); 5755d522f475Smrg return (int) arg; 5756d522f475Smrg#elif defined(__CYGWIN__) 5757d522f475Smrg fd_set set; 575820d2c4d2Smrg struct timeval select_timeout = 5759d522f475Smrg {0, 0}; 5760d522f475Smrg 5761d522f475Smrg FD_ZERO(&set); 5762d522f475Smrg FD_SET(fd, &set); 576320d2c4d2Smrg if (Select(fd + 1, &set, NULL, NULL, &select_timeout) > 0) 5764d522f475Smrg return 1; 5765d522f475Smrg else 5766d522f475Smrg return 0; 5767d522f475Smrg#elif defined(FIORDCK) 5768d522f475Smrg return (ioctl(fd, FIORDCHK, NULL)); 5769d522f475Smrg#else /* !FIORDCK */ 5770d522f475Smrg struct pollfd pollfds[1]; 5771d522f475Smrg 5772d522f475Smrg pollfds[0].fd = fd; 5773d522f475Smrg pollfds[0].events = POLLIN; 5774d522f475Smrg return poll(pollfds, 1, 0); 5775d522f475Smrg#endif 5776d522f475Smrg} 5777d522f475Smrg#endif /* !VMS */ 5778d522f475Smrg 5779d522f475Smrg/* Utility function to try to hide system differences from 5780d522f475Smrg everybody who used to call killpg() */ 5781d522f475Smrg 5782d522f475Smrgint 5783d522f475Smrgkill_process_group(int pid, int sig) 5784d522f475Smrg{ 5785d522f475Smrg TRACE(("kill_process_group(pid=%d, sig=%d)\n", pid, sig)); 5786d522f475Smrg#if defined(SVR4) || defined(SYSV) || !defined(X_NOT_POSIX) 5787d522f475Smrg return kill(-pid, sig); 5788d522f475Smrg#else 5789d522f475Smrg return killpg(pid, sig); 5790d522f475Smrg#endif 5791d522f475Smrg} 5792d522f475Smrg 5793d522f475Smrg#if OPT_EBCDIC 5794d522f475Smrgint 5795d522f475SmrgA2E(int x) 5796d522f475Smrg{ 5797d522f475Smrg char c; 5798d522f475Smrg c = x; 5799d522f475Smrg __atoe_l(&c, 1); 5800d522f475Smrg return c; 5801d522f475Smrg} 5802d522f475Smrg 5803d522f475Smrgint 5804d522f475SmrgE2A(int x) 5805d522f475Smrg{ 5806d522f475Smrg char c; 5807d522f475Smrg c = x; 5808d522f475Smrg __etoa_l(&c, 1); 5809d522f475Smrg return c; 5810d522f475Smrg} 5811d522f475Smrg#endif 5812d522f475Smrg 5813d522f475Smrg#if defined(__QNX__) && !defined(__QNXNTO__) 5814d522f475Smrg#include <sys/types.h> 5815d522f475Smrg#include <sys/proc_msg.h> 5816d522f475Smrg#include <sys/kernel.h> 5817d522f475Smrg#include <string.h> 5818d522f475Smrg#include <errno.h> 5819d522f475Smrg 5820d522f475Smrgstruct _proc_session ps; 5821d522f475Smrgstruct _proc_session_reply rps; 5822d522f475Smrg 5823d522f475Smrgint 5824d522f475Smrgqsetlogin(char *login, char *ttyname) 5825d522f475Smrg{ 5826d522f475Smrg int v = getsid(getpid()); 5827d522f475Smrg 5828d522f475Smrg memset(&ps, 0, sizeof(ps)); 5829d522f475Smrg memset(&rps, 0, sizeof(rps)); 5830d522f475Smrg 5831d522f475Smrg ps.type = _PROC_SESSION; 5832d522f475Smrg ps.subtype = _PROC_SUB_ACTION1; 5833d522f475Smrg ps.sid = v; 5834d522f475Smrg strcpy(ps.name, login); 5835d522f475Smrg 5836d522f475Smrg Send(1, &ps, &rps, sizeof(ps), sizeof(rps)); 5837d522f475Smrg 5838d522f475Smrg if (rps.status < 0) 5839d522f475Smrg return (rps.status); 5840d522f475Smrg 5841d522f475Smrg ps.type = _PROC_SESSION; 5842d522f475Smrg ps.subtype = _PROC_SUB_ACTION2; 5843d522f475Smrg ps.sid = v; 5844d522f475Smrg sprintf(ps.name, "//%d%s", getnid(), ttyname); 5845d522f475Smrg Send(1, &ps, &rps, sizeof(ps), sizeof(rps)); 5846d522f475Smrg 5847d522f475Smrg return (rps.status); 5848d522f475Smrg} 5849d522f475Smrg#endif 585001037d57Smrg 585101037d57Smrg#ifdef __minix 585201037d57Smrgint 585301037d57Smrgsetpgrp(void) 585401037d57Smrg{ 585501037d57Smrg return 0; 585601037d57Smrg} 585701037d57Smrg 585801037d57Smrgvoid 585901037d57Smrg_longjmp(jmp_buf _env, int _val) 586001037d57Smrg{ 586101037d57Smrg longjmp(_env, _val); 586201037d57Smrg} 586301037d57Smrg#endif 5864