xconsole.c revision eaad2c89
1c7484f1fSmrg/* 2c7484f1fSmrg * 3c7484f1fSmrgCopyright 1990, 1998 The Open Group 4c7484f1fSmrg 5c7484f1fSmrgPermission to use, copy, modify, distribute, and sell this software and its 6c7484f1fSmrgdocumentation for any purpose is hereby granted without fee, provided that 7c7484f1fSmrgthe above copyright notice appear in all copies and that both that 8c7484f1fSmrgcopyright notice and this permission notice appear in supporting 9c7484f1fSmrgdocumentation. 10c7484f1fSmrg 11c7484f1fSmrgThe above copyright notice and this permission notice shall be included in 12c7484f1fSmrgall copies or substantial portions of the Software. 13c7484f1fSmrg 14c7484f1fSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15c7484f1fSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16c7484f1fSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17c7484f1fSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18c7484f1fSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19c7484f1fSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20c7484f1fSmrg 21c7484f1fSmrgExcept as contained in this notice, the name of The Open Group shall not be 22c7484f1fSmrgused in advertising or otherwise to promote the sale, use or other dealings 23c7484f1fSmrgin this Software without prior written authorization from The Open Group. 24c7484f1fSmrg * 25c7484f1fSmrg * Author: Keith Packard, MIT X Consortium 26c7484f1fSmrg */ 27c7484f1fSmrg 28c7484f1fSmrg 29c7484f1fSmrg#ifdef HAVE_CONFIG_H 30c7484f1fSmrg#include "config.h" 31c7484f1fSmrg#endif 32c7484f1fSmrg 33eaad2c89Smrg#include <X11/Xfuncproto.h> 34eaad2c89Smrg 35c7484f1fSmrg#include <X11/Intrinsic.h> 36c7484f1fSmrg#include <X11/StringDefs.h> 37c7484f1fSmrg#include <X11/Xatom.h> 38c7484f1fSmrg 39c7484f1fSmrg#include <X11/Xmu/Atoms.h> 40c7484f1fSmrg#include <X11/Xmu/StdSel.h> 41c7484f1fSmrg#include <X11/Xmu/SysUtil.h> 42c7484f1fSmrg 43c7484f1fSmrg#include <X11/Xaw/Form.h> 44c7484f1fSmrg#include <X11/Xaw/Label.h> 45c7484f1fSmrg#include <X11/Xaw/Command.h> 46c7484f1fSmrg#include <X11/Xaw/AsciiText.h> 47c7484f1fSmrg#include <X11/Xaw/Dialog.h> 48c7484f1fSmrg#include <X11/Xaw/Cardinals.h> 49c7484f1fSmrg#include <X11/Xaw/Paned.h> 50c7484f1fSmrg#include <X11/Xaw/Box.h> 51c7484f1fSmrg 52c7484f1fSmrgextern char *_XawTextGetSTRING(TextWidget ctx, XawTextPosition left, 53c7484f1fSmrg XawTextPosition right); 54c7484f1fSmrg 55c7484f1fSmrg#include <X11/Xos.h> 56c7484f1fSmrg#include <X11/Xfuncs.h> 57c7484f1fSmrg#include <sys/stat.h> 58c7484f1fSmrg#ifndef _POSIX_SOURCE 59c7484f1fSmrg#define _POSIX_SOURCE 60c7484f1fSmrg#include <stdio.h> 61c7484f1fSmrg#undef _POSIX_SOURCE 62c7484f1fSmrg#else 63c7484f1fSmrg#include <stdio.h> 64c7484f1fSmrg#endif 65c7484f1fSmrg#include <X11/Shell.h> 66c7484f1fSmrg#include <ctype.h> 67c7484f1fSmrg#include <stdlib.h> 68c7484f1fSmrg#ifdef HAS_OPENPTY 69f91b368dSmrg# ifdef HAVE_UTIL_H 70c7484f1fSmrg# include <util.h> 71c7484f1fSmrg# endif 72eaad2c89Smrg# ifdef HAVE_LIBUTIL_H 73eaad2c89Smrg# include <libutil.h> 74eaad2c89Smrg# endif 75f91b368dSmrg# ifdef HAVE_PTY_H 76c7484f1fSmrg# include <pty.h> 77c7484f1fSmrg# endif 78c7484f1fSmrg#endif 79c7484f1fSmrg 80c7484f1fSmrgstatic void inputReady(XtPointer w, int *source, XtInputId *id); 81c7484f1fSmrgstatic long TextLength(Widget w); 82c7484f1fSmrgstatic void TextReplace(Widget w, int start, int end, XawTextBlock *block); 83c7484f1fSmrgstatic void TextAppend(Widget w, char *s, int len); 84c7484f1fSmrgstatic void TextInsert(Widget w, char *s, int len); 85c7484f1fSmrgstatic Bool ExceededMaxLines(Widget w); 86c7484f1fSmrgstatic void ScrollLine(Widget w); 87c7484f1fSmrg 88c7484f1fSmrgstatic Widget top, text; 89c7484f1fSmrg 90c7484f1fSmrgstatic XtInputId input_id; 91c7484f1fSmrg 92c7484f1fSmrgstatic FILE *input; 93c7484f1fSmrgstatic Boolean regularFile = FALSE; 94c7484f1fSmrg 95c7484f1fSmrgstatic Boolean notified; 96c7484f1fSmrgstatic Boolean iconified; 97c7484f1fSmrg 98c7484f1fSmrgstatic Atom wm_delete_window; 99c7484f1fSmrgstatic Atom mit_console; 100c7484f1fSmrg 101c7484f1fSmrg#define MIT_CONSOLE_LEN 12 102c7484f1fSmrg#define MIT_CONSOLE "MIT_CONSOLE_" 103c7484f1fSmrgstatic char mit_console_name[255 + MIT_CONSOLE_LEN + 1] = MIT_CONSOLE; 104c7484f1fSmrg 105c7484f1fSmrgstatic struct _app_resources { 106c7484f1fSmrg char *file; 107c7484f1fSmrg Boolean stripNonprint; 108c7484f1fSmrg Boolean notify; 109c7484f1fSmrg Boolean daemon; 110c7484f1fSmrg Boolean verbose; 111c7484f1fSmrg Boolean exitOnFail; 112c7484f1fSmrg int saveLines; 113c7484f1fSmrg} app_resources; 114c7484f1fSmrg 115c7484f1fSmrg#define Offset(field) XtOffsetOf(struct _app_resources, field) 116c7484f1fSmrg 117c7484f1fSmrgstatic XtResource resources[] = { 118c7484f1fSmrg {"file", "File", XtRString, sizeof (char *), 119c7484f1fSmrg Offset (file), XtRString, "console" }, 120c7484f1fSmrg {"notify", "Notify", XtRBoolean, sizeof (Boolean), 121c7484f1fSmrg Offset (notify), XtRImmediate, (XtPointer)True }, 122c7484f1fSmrg {"stripNonprint", "StripNonprint", XtRBoolean, sizeof (Boolean), 123c7484f1fSmrg Offset (stripNonprint), XtRImmediate, (XtPointer)True }, 124c7484f1fSmrg {"daemon", "Daemon", XtRBoolean, sizeof (Boolean), 125c7484f1fSmrg Offset (daemon), XtRImmediate, (XtPointer)False}, 126c7484f1fSmrg {"verbose", "Verbose", XtRBoolean, sizeof (Boolean), 127c7484f1fSmrg Offset (verbose),XtRImmediate, (XtPointer)False}, 128c7484f1fSmrg {"exitOnFail", "ExitOnFail", XtRBoolean, sizeof (Boolean), 129c7484f1fSmrg Offset (exitOnFail),XtRImmediate, (XtPointer)False}, 130c7484f1fSmrg {"saveLines", "SaveLines", XtRInt, sizeof (int), 131c7484f1fSmrg Offset (saveLines), XtRImmediate, (XtPointer) 0 }, 132c7484f1fSmrg}; 133c7484f1fSmrg 134c7484f1fSmrg#undef Offset 135c7484f1fSmrg 136c7484f1fSmrgstatic XrmOptionDescRec options[] = { 137c7484f1fSmrg {"-file", "*file", XrmoptionSepArg, NULL}, 138c7484f1fSmrg {"-notify", "*notify", XrmoptionNoArg, "TRUE"}, 139c7484f1fSmrg {"-nonotify", "*notify", XrmoptionNoArg, "FALSE"}, 140c7484f1fSmrg {"-daemon", "*daemon", XrmoptionNoArg, "TRUE"}, 141c7484f1fSmrg {"-verbose", "*verbose", XrmoptionNoArg, "TRUE"}, 142c7484f1fSmrg {"-exitOnFail", "*exitOnFail", XrmoptionNoArg, "TRUE"}, 143c7484f1fSmrg {"-saveLines", "*saveLines", XrmoptionSepArg, NULL}, 144c7484f1fSmrg}; 145c7484f1fSmrg 146c7484f1fSmrg 147c7484f1fSmrg#ifdef linux 148c7484f1fSmrg#define USE_FILE 149c7484f1fSmrg#define FILE_NAME "/dev/xconsole" 150c7484f1fSmrg# if defined (__GLIBC__) && ((__GLIBC__ > 2) || (__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)) 151c7484f1fSmrg/* 152c7484f1fSmrg * Linux distribution based on glibc 2.1 and higher should use 153c7484f1fSmrg * devpts. This is the fallback if open file FILE_NAME fails. 154c7484f1fSmrg * <werner@suse.de> 155c7484f1fSmrg */ 156eaad2c89Smrg# define USE_PTS 157c7484f1fSmrg# endif 158c7484f1fSmrg#endif 159c7484f1fSmrg 160c7484f1fSmrg#if defined(_AIX) 161c7484f1fSmrg# define USE_PTS 162c7484f1fSmrg#endif 163c7484f1fSmrg 164c7484f1fSmrg#if !defined (USE_FILE) || defined (linux) 165c7484f1fSmrg# include <sys/ioctl.h> 166c7484f1fSmrg# ifdef hpux 167c7484f1fSmrg# include <termios.h> 168c7484f1fSmrg# endif 169c7484f1fSmrg# if defined (SVR4) || defined (USE_PTS) 170c7484f1fSmrg# include <termios.h> 171f91b368dSmrg# ifndef HAS_OPENPTY 172c7484f1fSmrg# include <sys/stropts.h> /* for I_PUSH */ 173f91b368dSmrg# endif 174c7484f1fSmrg# ifdef sun 175c7484f1fSmrg# include <sys/strredir.h> 176c7484f1fSmrg# endif 177c7484f1fSmrg# endif 178eaad2c89Smrg# if defined(TIOCCONS) || defined(SRIOCSREDIR) 179c7484f1fSmrg# define USE_PTY 180c7484f1fSmrgstatic int tty_fd, pty_fd; 181c7484f1fSmrgstatic char ttydev[64], ptydev[64]; 182c7484f1fSmrg# endif 183c7484f1fSmrg#endif 184c7484f1fSmrg 185c7484f1fSmrg#if (defined(SVR4) && !defined(sun)) || (defined(SYSV) && defined(i386)) 186c7484f1fSmrg#define USE_OSM 187c7484f1fSmrg#include <signal.h> 188c7484f1fSmrg#endif 189c7484f1fSmrg 190c7484f1fSmrg#ifdef USE_PTY 191c7484f1fSmrgstatic int get_pty(int *pty, int *tty, char *ttydev, char *ptydev); 192c7484f1fSmrg#endif 193c7484f1fSmrg 194c7484f1fSmrg#ifdef USE_OSM 195c7484f1fSmrgstatic FILE *osm_pipe(void); 196c7484f1fSmrgstatic int child_pid; 197c7484f1fSmrg#endif 198c7484f1fSmrg 199c7484f1fSmrg/* Copied from xterm/ptyx.h */ 200c7484f1fSmrg#ifndef PTYCHAR1 201c7484f1fSmrg#ifdef __hpux 202c7484f1fSmrg#define PTYCHAR1 "zyxwvutsrqp" 203c7484f1fSmrg#else /* !__hpux */ 204c7484f1fSmrg#define PTYCHAR1 "pqrstuvwxyzPQRSTUVWXYZ" 205c7484f1fSmrg#endif /* !__hpux */ 206c7484f1fSmrg#endif /* !PTYCHAR1 */ 207c7484f1fSmrg 208c7484f1fSmrg#ifndef PTYCHAR2 209c7484f1fSmrg#ifdef __hpux 210c7484f1fSmrg#define PTYCHAR2 "fedcba9876543210" 211c7484f1fSmrg#else /* !__hpux */ 212c7484f1fSmrg#ifdef __FreeBSD__ 213c7484f1fSmrg#define PTYCHAR2 "0123456789abcdefghijklmnopqrstuv" 214c7484f1fSmrg#else /* !__FreeBSD__ */ 215c7484f1fSmrg#define PTYCHAR2 "0123456789abcdef" 216c7484f1fSmrg#endif /* !__FreeBSD__ */ 217c7484f1fSmrg#endif /* !__hpux */ 218c7484f1fSmrg#endif /* !PTYCHAR2 */ 219c7484f1fSmrg 220c7484f1fSmrgstatic void 221c7484f1fSmrgOpenConsole(void) 222c7484f1fSmrg{ 223c7484f1fSmrg input = 0; 224c7484f1fSmrg if (app_resources.file) 225c7484f1fSmrg { 226c7484f1fSmrg if (!strcmp (app_resources.file, "console")) 227c7484f1fSmrg { 228c7484f1fSmrg /* must be owner and have read/write permission */ 229eaad2c89Smrg#if !defined(__NetBSD__) && !defined(__OpenBSD__) 230c7484f1fSmrg struct stat sbuf; 231c7484f1fSmrg# if !defined (linux) 232c7484f1fSmrg if (!stat("/dev/console", &sbuf) && 233c7484f1fSmrg (sbuf.st_uid == getuid()) && 234c7484f1fSmrg !access("/dev/console", R_OK|W_OK)) 235c7484f1fSmrg# endif 236c7484f1fSmrg#endif 237c7484f1fSmrg { 238c7484f1fSmrg#ifdef USE_FILE 239c7484f1fSmrg# ifdef linux 240c7484f1fSmrg if (!stat(FILE_NAME, &sbuf)) 241c7484f1fSmrg# endif 242eaad2c89Smrg input = fopen (FILE_NAME, "r"); 243c7484f1fSmrg#endif 244eaad2c89Smrg 245c7484f1fSmrg#ifdef USE_PTY 246c7484f1fSmrg if (!input && get_pty (&pty_fd, &tty_fd, ttydev, ptydev) == 0) 247c7484f1fSmrg { 248c7484f1fSmrg# ifdef TIOCCONS 249c7484f1fSmrg int on = 1; 250c7484f1fSmrg if (ioctl (tty_fd, TIOCCONS, (char *) &on) != -1) 251c7484f1fSmrg input = fdopen (pty_fd, "r"); 252c7484f1fSmrg# else 253c7484f1fSmrg int consfd = open("/dev/console", O_RDONLY); 254c7484f1fSmrg if (consfd >= 0) 255c7484f1fSmrg { 256c7484f1fSmrg if (ioctl(consfd, SRIOCSREDIR, tty_fd) != -1) 257c7484f1fSmrg input = fdopen (pty_fd, "r"); 258c7484f1fSmrg close(consfd); 259c7484f1fSmrg } 260c7484f1fSmrg# endif 261c7484f1fSmrg } 262c7484f1fSmrg#endif /* USE_PTY */ 263c7484f1fSmrg } 264c7484f1fSmrg#ifdef USE_OSM 265c7484f1fSmrg /* Don't have to be owner of /dev/console when using /dev/osm. */ 266c7484f1fSmrg if (!input) 267c7484f1fSmrg input = osm_pipe(); 268c7484f1fSmrg#endif 269c7484f1fSmrg if (input && app_resources.verbose) 270c7484f1fSmrg { 271c7484f1fSmrg char *hostname; 272c7484f1fSmrg TextAppend (text, "Console log for ", 16); 273c7484f1fSmrg hostname = mit_console_name + MIT_CONSOLE_LEN; 274c7484f1fSmrg TextAppend (text, hostname, strlen (hostname)); 275c7484f1fSmrg TextAppend (text, "\n", 1); 276c7484f1fSmrg } 277c7484f1fSmrg } 278c7484f1fSmrg else 279c7484f1fSmrg { 280c7484f1fSmrg regularFile = FALSE; 281c7484f1fSmrg if (access(app_resources.file, R_OK) == 0) 282c7484f1fSmrg { 283eaad2c89Smrg int fd = open (app_resources.file, 284eaad2c89Smrg O_RDONLY | O_NONBLOCK | O_NOCTTY); 285eaad2c89Smrg if (fd != -1) { 286eaad2c89Smrg input = fdopen (fd, "r"); 287eaad2c89Smrg 288eaad2c89Smrg if (input) { 289eaad2c89Smrg struct stat sbuf; 290eaad2c89Smrg 291eaad2c89Smrg if ((fstat(fd, &sbuf) == 0) && S_ISREG(sbuf.st_mode)) 292eaad2c89Smrg regularFile = TRUE; 293eaad2c89Smrg } 294eaad2c89Smrg else 295eaad2c89Smrg close(fd); 296eaad2c89Smrg } 297c7484f1fSmrg } 298c7484f1fSmrg } 299c7484f1fSmrg if (!input) 300c7484f1fSmrg { 301c7484f1fSmrg if (app_resources.exitOnFail) 302c7484f1fSmrg exit(0); 303c7484f1fSmrg TextAppend (text, "Couldn't open ", 14); 304c7484f1fSmrg TextAppend (text, app_resources.file, strlen (app_resources.file)); 305c7484f1fSmrg TextAppend (text, "\n", 1); 306c7484f1fSmrg } 307c7484f1fSmrg } 308c7484f1fSmrg else 309c7484f1fSmrg input = stdin; 310c7484f1fSmrg 311c7484f1fSmrg if (input) 312c7484f1fSmrg { 313c7484f1fSmrg input_id = XtAddInput (fileno (input), (XtPointer) XtInputReadMask, 314c7484f1fSmrg inputReady, (XtPointer) text); 315c7484f1fSmrg } 316c7484f1fSmrg} 317c7484f1fSmrg 318c7484f1fSmrgstatic void 319c7484f1fSmrgCloseConsole (void) 320c7484f1fSmrg{ 321c7484f1fSmrg if (input) 322c7484f1fSmrg { 323c7484f1fSmrg XtRemoveInput (input_id); 324c7484f1fSmrg fclose (input); 325c7484f1fSmrg } 326c7484f1fSmrg#ifdef USE_PTY 327c7484f1fSmrg close (tty_fd); 328c7484f1fSmrg#endif 329c7484f1fSmrg} 330c7484f1fSmrg 331c7484f1fSmrg#ifdef USE_OSM 332c7484f1fSmrgstatic void 333c7484f1fSmrgKillChild(int sig) 334c7484f1fSmrg{ 335c7484f1fSmrg if (child_pid > 0) 336c7484f1fSmrg kill(child_pid, SIGTERM); 337c7484f1fSmrg _exit(0); 338c7484f1fSmrg} 339c7484f1fSmrg#endif 340c7484f1fSmrg 341c7484f1fSmrg/*ARGSUSED*/ 342eaad2c89Smrgstatic void _X_NORETURN 343c7484f1fSmrgQuit(Widget widget, XEvent *event, String *params, Cardinal *num_params) 344c7484f1fSmrg{ 345c7484f1fSmrg#ifdef USE_OSM 346c7484f1fSmrg if (child_pid > 0) 347c7484f1fSmrg kill(child_pid, SIGTERM); 348c7484f1fSmrg#endif 349c7484f1fSmrg exit (0); 350c7484f1fSmrg} 351c7484f1fSmrg 352c7484f1fSmrg#ifdef USE_OSM 353c7484f1fSmrgstatic int (*ioerror)(Display *); 354c7484f1fSmrg 355c7484f1fSmrgstatic int 356c7484f1fSmrgIOError(Display *dpy) 357c7484f1fSmrg{ 358c7484f1fSmrg if (child_pid > 0) 359c7484f1fSmrg kill(child_pid, SIGTERM); 360c7484f1fSmrg return (*ioerror)(dpy); 361c7484f1fSmrg} 362c7484f1fSmrg#endif 363c7484f1fSmrg 364c7484f1fSmrgstatic void 365c7484f1fSmrgNotify(void) 366c7484f1fSmrg{ 367c7484f1fSmrg Arg arglist[1]; 368c7484f1fSmrg char *oldName; 369c7484f1fSmrg char *newName; 370c7484f1fSmrg 371c7484f1fSmrg if (!iconified || !app_resources.notify || notified) 372c7484f1fSmrg return; 373c7484f1fSmrg XtSetArg (arglist[0], XtNiconName, &oldName); 374c7484f1fSmrg XtGetValues (top, arglist, 1); 375c7484f1fSmrg newName = malloc (strlen (oldName) + 3); 376c7484f1fSmrg if (!newName) 377c7484f1fSmrg return; 378c7484f1fSmrg sprintf (newName, "%s *", oldName); 379c7484f1fSmrg XtSetArg (arglist[0], XtNiconName, newName); 380c7484f1fSmrg XtSetValues (top, arglist, 1); 381c7484f1fSmrg free (newName); 382c7484f1fSmrg notified = True; 383c7484f1fSmrg} 384c7484f1fSmrg 385c7484f1fSmrg/*ARGSUSED*/ 386c7484f1fSmrgstatic void 387c7484f1fSmrgDeiconified(Widget widget, XEvent *event, String *params, Cardinal *num_params) 388c7484f1fSmrg{ 389c7484f1fSmrg Arg arglist[1]; 390c7484f1fSmrg char *oldName; 391c7484f1fSmrg char *newName; 392eaad2c89Smrg size_t oldlen; 393c7484f1fSmrg 394c7484f1fSmrg iconified = False; 395c7484f1fSmrg if (!app_resources.notify || !notified) 396c7484f1fSmrg return; 397c7484f1fSmrg XtSetArg (arglist[0], XtNiconName, &oldName); 398c7484f1fSmrg XtGetValues (top, arglist, 1); 399c7484f1fSmrg oldlen = strlen (oldName); 400c7484f1fSmrg if (oldlen >= 2) 401c7484f1fSmrg { 402c7484f1fSmrg newName = malloc (oldlen - 1); 403c7484f1fSmrg if (!newName) 404c7484f1fSmrg return; 405c7484f1fSmrg strncpy (newName, oldName, oldlen - 2); 406c7484f1fSmrg newName[oldlen - 2] = '\0'; 407c7484f1fSmrg XtSetArg (arglist[0], XtNiconName, newName); 408c7484f1fSmrg XtSetValues (top, arglist, 1); 409c7484f1fSmrg free (newName); 410c7484f1fSmrg } 411c7484f1fSmrg notified = False; 412c7484f1fSmrg} 413c7484f1fSmrg 414c7484f1fSmrg/*ARGSUSED*/ 415c7484f1fSmrgstatic void 416c7484f1fSmrgIconified(Widget widget, XEvent *event, String *params, Cardinal *num_params) 417c7484f1fSmrg{ 418c7484f1fSmrg iconified = True; 419c7484f1fSmrg} 420c7484f1fSmrg 421c7484f1fSmrg/*ARGSUSED*/ 422c7484f1fSmrgstatic void 423c7484f1fSmrgClear(Widget widget, XEvent *event, String *params, Cardinal *num_params) 424c7484f1fSmrg{ 425c7484f1fSmrg long last; 426c7484f1fSmrg XawTextBlock block; 427c7484f1fSmrg 428c7484f1fSmrg last = TextLength (text); 429c7484f1fSmrg block.ptr = ""; 430c7484f1fSmrg block.firstPos = 0; 431c7484f1fSmrg block.length = 0; 432c7484f1fSmrg block.format = FMT8BIT; 433c7484f1fSmrg TextReplace (text, 0, last, &block); 434c7484f1fSmrg} 435c7484f1fSmrg 436c7484f1fSmrgstatic XtActionsRec actions[] = { 437c7484f1fSmrg { "Quit", Quit }, 438c7484f1fSmrg { "Iconified", Iconified }, 439c7484f1fSmrg { "Deiconified", Deiconified }, 440c7484f1fSmrg { "Clear", Clear }, 441c7484f1fSmrg}; 442c7484f1fSmrg 443c7484f1fSmrgstatic void 444c7484f1fSmrgstripNonprint(char *b) 445c7484f1fSmrg{ 446c7484f1fSmrg char *c; 447c7484f1fSmrg 448c7484f1fSmrg c = b; 449c7484f1fSmrg while (*b) 450c7484f1fSmrg { 451c7484f1fSmrg if (isprint (*b) || (isspace (*b) && *b != '\r')) 452c7484f1fSmrg { 453c7484f1fSmrg if (c != b) 454c7484f1fSmrg *c = *b; 455c7484f1fSmrg ++c; 456c7484f1fSmrg } 457c7484f1fSmrg ++b; 458c7484f1fSmrg } 459c7484f1fSmrg *c = '\0'; 460c7484f1fSmrg} 461c7484f1fSmrg 462c7484f1fSmrgstatic void 463c7484f1fSmrginputReady(XtPointer w, int *source, XtInputId *id) 464c7484f1fSmrg{ 465c7484f1fSmrg char buffer[1025]; 466c7484f1fSmrg int n; 467c7484f1fSmrg 468c7484f1fSmrg n = read (*source, buffer, sizeof (buffer) - 1); 469c7484f1fSmrg if (n <= 0) 470c7484f1fSmrg { 471c7484f1fSmrg if (app_resources.file && regularFile && n == 0) 472c7484f1fSmrg { 473c7484f1fSmrg if (XPending(XtDisplay(w))) 474c7484f1fSmrg return; 475c7484f1fSmrg 476c7484f1fSmrg sleep(1); 477c7484f1fSmrg return; 478c7484f1fSmrg } 479c7484f1fSmrg 480c7484f1fSmrg fclose (input); 481c7484f1fSmrg XtRemoveInput (*id); 482c7484f1fSmrg 483c7484f1fSmrg /* try to reopen if pipe; this can be caused by syslog restart */ 484c7484f1fSmrg if (app_resources.file && !regularFile && n == 0) 485c7484f1fSmrg { 486c7484f1fSmrg OpenConsole(); 487c7484f1fSmrg } 488c7484f1fSmrg } else { 489c7484f1fSmrg Notify(); 490c7484f1fSmrg buffer[n] = '\0'; 491c7484f1fSmrg if (app_resources.stripNonprint) 492c7484f1fSmrg { 493c7484f1fSmrg stripNonprint (buffer); 494c7484f1fSmrg n = strlen (buffer); 495c7484f1fSmrg } 496eaad2c89Smrg 497c7484f1fSmrg TextAppend ((Widget) text, buffer, n); 498c7484f1fSmrg } 499c7484f1fSmrg} 500c7484f1fSmrg 501c7484f1fSmrgstatic Boolean 502c7484f1fSmrgConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type, 503c7484f1fSmrg XtPointer *value, unsigned long *length, int *format) 504c7484f1fSmrg{ 505c7484f1fSmrg Display* d = XtDisplay(w); 506c7484f1fSmrg XSelectionRequestEvent* req = 507c7484f1fSmrg XtGetSelectionRequest(w, *selection, (XtRequestId)NULL); 508c7484f1fSmrg 509c7484f1fSmrg if (*target == XA_TARGETS(d)) 510c7484f1fSmrg { 511c7484f1fSmrg Atom* targetP; 512c7484f1fSmrg Atom* std_targets; 513c7484f1fSmrg unsigned long std_length; 514c7484f1fSmrg XmuConvertStandardSelection(w, req->time, selection, target, type, 515c7484f1fSmrg (XPointer *)&std_targets, &std_length, 516c7484f1fSmrg format); 517c7484f1fSmrg *value = (XtPointer)XtMalloc(sizeof(Atom)*(std_length + 5)); 518c7484f1fSmrg targetP = *(Atom**)value; 519c7484f1fSmrg *targetP++ = XA_STRING; 520c7484f1fSmrg *targetP++ = XA_TEXT(d); 521c7484f1fSmrg *targetP++ = XA_LENGTH(d); 522c7484f1fSmrg *targetP++ = XA_LIST_LENGTH(d); 523c7484f1fSmrg *targetP++ = XA_CHARACTER_POSITION(d); 524c7484f1fSmrg *length = std_length + (targetP - (*(Atom **) value)); 525c7484f1fSmrg memmove( (char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); 526c7484f1fSmrg XtFree((char*)std_targets); 527c7484f1fSmrg *type = XA_ATOM; 528c7484f1fSmrg *format = 32; 529c7484f1fSmrg return True; 530c7484f1fSmrg } 531c7484f1fSmrg 532c7484f1fSmrg if (*target == XA_LIST_LENGTH(d) || 533c7484f1fSmrg *target == XA_LENGTH(d)) 534c7484f1fSmrg { 535c7484f1fSmrg long * temp; 536c7484f1fSmrg 537c7484f1fSmrg temp = (long *) XtMalloc(sizeof(long)); 538c7484f1fSmrg if (*target == XA_LIST_LENGTH(d)) 539c7484f1fSmrg *temp = 1L; 540c7484f1fSmrg else /* *target == XA_LENGTH(d) */ 541c7484f1fSmrg *temp = (long) TextLength (text); 542c7484f1fSmrg 543c7484f1fSmrg *value = (XtPointer) temp; 544c7484f1fSmrg *type = XA_INTEGER; 545c7484f1fSmrg *length = 1L; 546c7484f1fSmrg *format = 32; 547c7484f1fSmrg return True; 548c7484f1fSmrg } 549c7484f1fSmrg 550c7484f1fSmrg if (*target == XA_CHARACTER_POSITION(d)) 551c7484f1fSmrg { 552c7484f1fSmrg long * temp; 553c7484f1fSmrg 554c7484f1fSmrg temp = (long *) XtMalloc(2 * sizeof(long)); 555c7484f1fSmrg temp[0] = (long) 0; 556c7484f1fSmrg temp[1] = TextLength (text); 557c7484f1fSmrg *value = (XtPointer) temp; 558c7484f1fSmrg *type = XA_SPAN(d); 559c7484f1fSmrg *length = 2L; 560c7484f1fSmrg *format = 32; 561c7484f1fSmrg return True; 562c7484f1fSmrg } 563c7484f1fSmrg 564c7484f1fSmrg if (*target == XA_STRING || 565c7484f1fSmrg *target == XA_TEXT(d) || 566c7484f1fSmrg *target == XA_COMPOUND_TEXT(d)) 567c7484f1fSmrg { 568c7484f1fSmrg if (*target == XA_COMPOUND_TEXT(d)) 569c7484f1fSmrg *type = *target; 570c7484f1fSmrg else 571c7484f1fSmrg *type = XA_STRING; 572c7484f1fSmrg *length = TextLength (text); 573c7484f1fSmrg *value = (XtPointer)_XawTextGetSTRING((TextWidget) text, 0, *length); 574c7484f1fSmrg *format = 8; 575c7484f1fSmrg /* 576c7484f1fSmrg * Drop our connection to the file; the new console program 577c7484f1fSmrg * will open as soon as it receives the selection contents; there 578c7484f1fSmrg * is a small window where console output will not be redirected, 579c7484f1fSmrg * but I see no way of avoiding that without having two programs 580c7484f1fSmrg * attempt to redirect console output at the same time, which seems 581c7484f1fSmrg * worse 582c7484f1fSmrg */ 583c7484f1fSmrg CloseConsole (); 584c7484f1fSmrg return True; 585c7484f1fSmrg } 586c7484f1fSmrg 587c7484f1fSmrg if (XmuConvertStandardSelection(w, req->time, selection, target, type, 588c7484f1fSmrg (XPointer *)value, length, format)) 589c7484f1fSmrg return True; 590c7484f1fSmrg 591c7484f1fSmrg return False; 592c7484f1fSmrg} 593c7484f1fSmrg 594eaad2c89Smrgstatic void _X_NORETURN 595c7484f1fSmrgLoseSelection(Widget w, Atom *selection) 596c7484f1fSmrg{ 597c7484f1fSmrg Quit (w, (XEvent*)NULL, (String*)NULL, (Cardinal*)NULL); 598c7484f1fSmrg} 599c7484f1fSmrg 600c7484f1fSmrg/*ARGSUSED*/ 601c7484f1fSmrgstatic void 602c7484f1fSmrgInsertSelection(Widget w, XtPointer client_data, Atom *selection, Atom *type, 603c7484f1fSmrg XtPointer value, unsigned long *length, int *format) 604c7484f1fSmrg{ 605c7484f1fSmrg if (*type != XT_CONVERT_FAIL) 606c7484f1fSmrg TextInsert (text, (char *) value, *length); 607c7484f1fSmrg XtOwnSelection(top, mit_console, CurrentTime, 608c7484f1fSmrg ConvertSelection, LoseSelection, NULL); 609c7484f1fSmrg OpenConsole (); 610c7484f1fSmrg} 611c7484f1fSmrg 612c7484f1fSmrgint 613c7484f1fSmrgmain(int argc, char *argv[]) 614c7484f1fSmrg{ 615c7484f1fSmrg Arg arglist[10]; 616c7484f1fSmrg Cardinal num_args; 617c7484f1fSmrg 618c7484f1fSmrg XtSetLanguageProc(NULL,NULL,NULL); 619c7484f1fSmrg top = XtInitialize ("xconsole", "XConsole", options, XtNumber (options), 620c7484f1fSmrg &argc, argv); 621c7484f1fSmrg XtGetApplicationResources (top, (XtPointer)&app_resources, resources, 622c7484f1fSmrg XtNumber (resources), NULL, 0); 623c7484f1fSmrg 624c7484f1fSmrg if (app_resources.daemon) 625c7484f1fSmrg if (fork ()) exit (0); 626c7484f1fSmrg XtAddActions (actions, XtNumber (actions)); 627c7484f1fSmrg 628c7484f1fSmrg text = XtCreateManagedWidget ("text", asciiTextWidgetClass, 629c7484f1fSmrg top, NULL, 0); 630c7484f1fSmrg 631c7484f1fSmrg XtRealizeWidget (top); 632c7484f1fSmrg num_args = 0; 633c7484f1fSmrg XtSetArg(arglist[num_args], XtNiconic, &iconified); num_args++; 634c7484f1fSmrg XtGetValues(top, arglist, num_args); 635c7484f1fSmrg if (iconified) 636c7484f1fSmrg Iconified((Widget)NULL, (XEvent*)NULL, (String*)NULL, (Cardinal*)NULL); 637c7484f1fSmrg else 638c7484f1fSmrg Deiconified((Widget)NULL,(XEvent*)NULL,(String*)NULL,(Cardinal*)NULL); 639c7484f1fSmrg wm_delete_window = XInternAtom(XtDisplay(top), "WM_DELETE_WINDOW", 640c7484f1fSmrg False); 641c7484f1fSmrg (void) XSetWMProtocols (XtDisplay(top), XtWindow(top), 642c7484f1fSmrg &wm_delete_window, 1); 643c7484f1fSmrg 644c7484f1fSmrg XmuGetHostname (mit_console_name + MIT_CONSOLE_LEN, 255); 645c7484f1fSmrg 646c7484f1fSmrg mit_console = XInternAtom(XtDisplay(top), mit_console_name, False); 647c7484f1fSmrg 648c7484f1fSmrg if (XGetSelectionOwner (XtDisplay (top), mit_console)) 649c7484f1fSmrg { 650c7484f1fSmrg XtGetSelectionValue(top, mit_console, XA_STRING, InsertSelection, 651c7484f1fSmrg NULL, CurrentTime); 652c7484f1fSmrg } 653c7484f1fSmrg else 654c7484f1fSmrg { 655c7484f1fSmrg XtOwnSelection(top, mit_console, CurrentTime, 656c7484f1fSmrg ConvertSelection, LoseSelection, NULL); 657c7484f1fSmrg OpenConsole (); 658c7484f1fSmrg } 659c7484f1fSmrg#ifdef USE_OSM 660c7484f1fSmrg ioerror = XSetIOErrorHandler(IOError); 661c7484f1fSmrg#endif 662c7484f1fSmrg XtMainLoop (); 663c7484f1fSmrg return 0; 664c7484f1fSmrg} 665c7484f1fSmrg 666c7484f1fSmrgstatic long 667c7484f1fSmrgTextLength(Widget w) 668c7484f1fSmrg{ 669c7484f1fSmrg return XawTextSourceScan (XawTextGetSource (w), 670c7484f1fSmrg (XawTextPosition) 0, 671c7484f1fSmrg XawstAll, XawsdRight, 1, TRUE); 672c7484f1fSmrg} 673c7484f1fSmrg 674c7484f1fSmrgstatic void 675c7484f1fSmrgTextReplace(Widget w, int start, int end, XawTextBlock *block) 676c7484f1fSmrg{ 677c7484f1fSmrg Arg arg; 678c7484f1fSmrg Widget source; 679c7484f1fSmrg XawTextEditType edit_mode; 680c7484f1fSmrg 681c7484f1fSmrg source = XawTextGetSource (w); 682c7484f1fSmrg XtSetArg (arg, XtNeditType, &edit_mode); 683c7484f1fSmrg XtGetValues (source, &arg, ONE); 684c7484f1fSmrg XtSetArg (arg, XtNeditType, XawtextEdit); 685c7484f1fSmrg XtSetValues (source, &arg, ONE); 686c7484f1fSmrg XawTextReplace (w, start, end, block); 687c7484f1fSmrg XtSetArg (arg, XtNeditType, edit_mode); 688c7484f1fSmrg XtSetValues (source, &arg, ONE); 689c7484f1fSmrg} 690c7484f1fSmrg 691c7484f1fSmrgstatic void 692c7484f1fSmrgTextAppend(Widget w, char *s, int len) 693c7484f1fSmrg{ 694c7484f1fSmrg long last, current; 695c7484f1fSmrg XawTextBlock block; 696c7484f1fSmrg 697c7484f1fSmrg current = XawTextGetInsertionPoint (w); 698c7484f1fSmrg last = TextLength (w); 699c7484f1fSmrg block.ptr = s; 700c7484f1fSmrg block.firstPos = 0; 701c7484f1fSmrg block.length = len; 702c7484f1fSmrg block.format = FMT8BIT; 703c7484f1fSmrg /* 704c7484f1fSmrg * If saveLines is 1, just replace the entire contents of the widget 705c7484f1fSmrg * each time, so the test in ExceededMaxLines() isn't fooled. 706c7484f1fSmrg */ 707c7484f1fSmrg if (app_resources.saveLines == 1) 708c7484f1fSmrg TextReplace (w, 0, last, &block); 709c7484f1fSmrg else 710c7484f1fSmrg TextReplace (w, last, last, &block); 711c7484f1fSmrg if (current == last) 712c7484f1fSmrg XawTextSetInsertionPoint (w, last + block.length); 713c7484f1fSmrg if (ExceededMaxLines(w)) 714c7484f1fSmrg ScrollLine(w); 715c7484f1fSmrg} 716c7484f1fSmrg 717c7484f1fSmrgstatic void 718c7484f1fSmrgTextInsert(Widget w, char *s, int len) 719c7484f1fSmrg{ 720c7484f1fSmrg XawTextBlock block; 721c7484f1fSmrg long current; 722c7484f1fSmrg 723c7484f1fSmrg current = XawTextGetInsertionPoint (w); 724c7484f1fSmrg block.ptr = s; 725c7484f1fSmrg block.firstPos = 0; 726c7484f1fSmrg block.length = len; 727c7484f1fSmrg block.format = FMT8BIT; 728c7484f1fSmrg TextReplace (w, 0, 0, &block); 729c7484f1fSmrg if (current == 0) 730c7484f1fSmrg XawTextSetInsertionPoint (w, len); 731c7484f1fSmrg if (ExceededMaxLines(w)) 732c7484f1fSmrg ScrollLine(w); 733c7484f1fSmrg} 734c7484f1fSmrg 735c7484f1fSmrgstatic Bool 736c7484f1fSmrgExceededMaxLines(Widget w) 737c7484f1fSmrg{ 738c7484f1fSmrg XawTextPosition end_of_last_line; 739c7484f1fSmrg Bool retval = False; 740c7484f1fSmrg 741c7484f1fSmrg if (app_resources.saveLines > 0) 742c7484f1fSmrg { 743c7484f1fSmrg /* 744c7484f1fSmrg * XawTextSourceScan() will return the end of the widget if it cannot 745c7484f1fSmrg * find what it is searching for. 746c7484f1fSmrg */ 747c7484f1fSmrg end_of_last_line = XawTextSourceScan (XawTextGetSource (w), 748c7484f1fSmrg (XawTextPosition) 0, 749c7484f1fSmrg XawstEOL, XawsdRight, 750c7484f1fSmrg app_resources.saveLines, TRUE); 751c7484f1fSmrg if (TextLength(w) > end_of_last_line) 752c7484f1fSmrg retval = True; 753c7484f1fSmrg else 754c7484f1fSmrg retval = False; 755c7484f1fSmrg } 756c7484f1fSmrg else 757c7484f1fSmrg retval = False; 758c7484f1fSmrg return retval; 759c7484f1fSmrg} 760c7484f1fSmrg 761c7484f1fSmrgstatic void 762c7484f1fSmrgScrollLine(Widget w) 763c7484f1fSmrg{ 764c7484f1fSmrg XawTextPosition firstnewline; 765c7484f1fSmrg XawTextBlock block; 766c7484f1fSmrg 767c7484f1fSmrg /* 768c7484f1fSmrg * This is pretty inefficient but should work well enough unless the 769c7484f1fSmrg * console device is getting totally spammed. Generally, new lines 770c7484f1fSmrg * only come in one at a time anyway. 771c7484f1fSmrg */ 772c7484f1fSmrg firstnewline = XawTextSourceScan (XawTextGetSource (w), 773c7484f1fSmrg (XawTextPosition) 0, 774c7484f1fSmrg XawstEOL, XawsdRight, 1, TRUE); 775c7484f1fSmrg block.ptr = ""; 776c7484f1fSmrg block.firstPos = 0; 777c7484f1fSmrg block.length = 0; 778c7484f1fSmrg block.format = FMT8BIT; 779c7484f1fSmrg TextReplace (w, 0, firstnewline, &block); 780c7484f1fSmrg} 781c7484f1fSmrg 782c7484f1fSmrg#ifdef USE_PTY 783c7484f1fSmrg/* 784c7484f1fSmrg * This function opens up a pty master and stuffs its value into pty. 785c7484f1fSmrg * If it finds one, it returns a value of 0. If it does not find one, 786c7484f1fSmrg * it returns a value of !0. This routine is designed to be re-entrant, 787c7484f1fSmrg * so that if a pty master is found and later, we find that the slave 788c7484f1fSmrg * has problems, we can re-enter this function and get another one. 789c7484f1fSmrg */ 790c7484f1fSmrg 791c7484f1fSmrgstatic int 792c7484f1fSmrgget_pty(int *pty, int *tty, char *ttydev, char *ptydev) 793c7484f1fSmrg{ 794c7484f1fSmrg#ifdef HAS_OPENPTY 795c7484f1fSmrg if (openpty(pty, tty, NULL, NULL, NULL) == -1) { 796c7484f1fSmrg return 1; 797c7484f1fSmrg } 798c7484f1fSmrg return 0; 799c7484f1fSmrg#elif defined (SVR4) || defined (USE_PTS) 800c7484f1fSmrg#if defined (_AIX) 801c7484f1fSmrg if ((*pty = open ("/dev/ptc", O_RDWR)) < 0) 802c7484f1fSmrg#else 803c7484f1fSmrg if ((*pty = open ("/dev/ptmx", O_RDWR)) < 0) 804c7484f1fSmrg#endif 805c7484f1fSmrg return 1; 806c7484f1fSmrg grantpt(*pty); 807c7484f1fSmrg unlockpt(*pty); 808c7484f1fSmrg strcpy(ttydev, (char *)ptsname(*pty)); 809c7484f1fSmrg if ((*tty = open(ttydev, O_RDWR)) >= 0) 810c7484f1fSmrg { 811c7484f1fSmrg (void)ioctl(*tty, I_PUSH, "ttcompat"); 812c7484f1fSmrg return 0; 813c7484f1fSmrg } 814c7484f1fSmrg if (*pty >= 0) 815c7484f1fSmrg close (*pty); 816c7484f1fSmrg#else /* !SVR4, need lots of code */ 817c7484f1fSmrg#ifdef USE_GET_PSEUDOTTY 818c7484f1fSmrg if ((*pty = getpseudotty (&ttydev, &ptydev)) >= 0 && 819c7484f1fSmrg (*tty = open (ttydev, O_RDWR)) >= 0) 820c7484f1fSmrg return 0; 821c7484f1fSmrg if (*pty >= 0) 822c7484f1fSmrg close (*pty); 823c7484f1fSmrg#else 824c7484f1fSmrg static int devindex, letter = 0; 825c7484f1fSmrg 826c7484f1fSmrg#ifdef sgi 827c7484f1fSmrg { 828c7484f1fSmrg char *slave; 829c7484f1fSmrg slave = _getpty (pty, O_RDWR, 0622, 0); 830c7484f1fSmrg if ((*tty = open (slave, O_RDWR)) != -1) 831c7484f1fSmrg return 0; 832c7484f1fSmrg } 833c7484f1fSmrg#else 834c7484f1fSmrg strcpy (ttydev, "/dev/ttyxx"); 835c7484f1fSmrg strcpy (ptydev, "/dev/ptyxx"); 836c7484f1fSmrg while (PTYCHAR1[letter]) { 837c7484f1fSmrg ttydev [strlen(ttydev) - 2] = ptydev [strlen(ptydev) - 2] = 838c7484f1fSmrg PTYCHAR1 [letter]; 839c7484f1fSmrg 840c7484f1fSmrg while (PTYCHAR2[devindex]) { 841c7484f1fSmrg ttydev [strlen(ttydev) - 1] = ptydev [strlen(ptydev) - 1] = 842c7484f1fSmrg PTYCHAR2 [devindex]; 843c7484f1fSmrg if ((*pty = open (ptydev, O_RDWR)) >= 0 && 844c7484f1fSmrg (*tty = open (ttydev, O_RDWR)) >= 0) 845c7484f1fSmrg { 846c7484f1fSmrg /* 847c7484f1fSmrg * We need to set things up for our next entry 848c7484f1fSmrg * into this function! 849c7484f1fSmrg */ 850c7484f1fSmrg (void) devindex++; 851c7484f1fSmrg return(0); 852c7484f1fSmrg } 853c7484f1fSmrg if (*pty >= 0) 854c7484f1fSmrg close (*pty); 855c7484f1fSmrg devindex++; 856c7484f1fSmrg } 857c7484f1fSmrg devindex = 0; 858c7484f1fSmrg (void) letter++; 859c7484f1fSmrg } 860c7484f1fSmrg#endif /* sgi else not sgi */ 861c7484f1fSmrg#endif /* USE_GET_PSEUDOTTY */ 862c7484f1fSmrg#endif /* SVR4 */ 863c7484f1fSmrg /* 864c7484f1fSmrg * We were unable to allocate a pty master! Return an error 865c7484f1fSmrg * condition and let our caller terminate cleanly. 866c7484f1fSmrg */ 867c7484f1fSmrg return(1); 868c7484f1fSmrg} 869c7484f1fSmrg#endif 870c7484f1fSmrg 871c7484f1fSmrg#ifdef USE_OSM 872c7484f1fSmrg/* 873c7484f1fSmrg * On SYSV386 there is a special device, /dev/osm, where system messages 874c7484f1fSmrg * are sent. Problem is that we can't perform a select(2) on this device. 875c7484f1fSmrg * So this routine creates a streams-pty where one end reads the device and 876c7484f1fSmrg * sends the output to xconsole. 877c7484f1fSmrg */ 878c7484f1fSmrg 879c7484f1fSmrg#ifdef SCO325 880c7484f1fSmrg#define OSM_DEVICE "/dev/error" 881c7484f1fSmrg#else 882c7484f1fSmrg#ifdef __UNIXWARE__ 883c7484f1fSmrg#define OSM_DEVICE "/dev/osm2" 884c7484f1fSmrg#define NO_READAHEAD 885c7484f1fSmrg#else 886c7484f1fSmrg#define OSM_DEVICE "/dev/osm" 887c7484f1fSmrg#endif 888c7484f1fSmrg#endif 889c7484f1fSmrg 890c7484f1fSmrgstatic FILE * 891c7484f1fSmrgosm_pipe(void) 892c7484f1fSmrg{ 893c7484f1fSmrg int tty; 894c7484f1fSmrg char ttydev[64]; 895c7484f1fSmrg 896c7484f1fSmrg if (access(OSM_DEVICE, R_OK) < 0) 897c7484f1fSmrg return NULL; 898c7484f1fSmrg#if defined (_AIX) 899c7484f1fSmrg if ((tty = open("/dev/ptc", O_RDWR)) < 0) 900eaad2c89Smrg#else 901c7484f1fSmrg if ((tty = open("/dev/ptmx", O_RDWR)) < 0) 902c7484f1fSmrg#endif 903c7484f1fSmrg return NULL; 904c7484f1fSmrg 905c7484f1fSmrg grantpt(tty); 906c7484f1fSmrg unlockpt(tty); 907c7484f1fSmrg strcpy(ttydev, (char *)ptsname(tty)); 908c7484f1fSmrg 909c7484f1fSmrg if ((child_pid = fork()) == 0) 910c7484f1fSmrg { 911c7484f1fSmrg int pty, osm, nbytes, skip; 912c7484f1fSmrg char cbuf[128]; 913c7484f1fSmrg 914c7484f1fSmrg skip = 0; 915c7484f1fSmrg#ifndef NO_READAHEAD 916c7484f1fSmrg osm = open(OSM_DEVICE, O_RDONLY); 917c7484f1fSmrg if (osm >= 0) 918c7484f1fSmrg { 919c7484f1fSmrg while ((nbytes = read(osm, cbuf, sizeof(cbuf))) > 0) 920c7484f1fSmrg skip += nbytes; 921c7484f1fSmrg close(osm); 922c7484f1fSmrg } 923c7484f1fSmrg#endif 924c7484f1fSmrg pty = open(ttydev, O_RDWR); 925c7484f1fSmrg if (pty < 0) 926c7484f1fSmrg exit(1); 927c7484f1fSmrg osm = open(OSM_DEVICE, O_RDONLY); 928c7484f1fSmrg if (osm < 0) 929c7484f1fSmrg exit(1); 930c7484f1fSmrg for (nbytes = 0; skip > 0 && nbytes >= 0; skip -= nbytes) 931c7484f1fSmrg { 932c7484f1fSmrg nbytes = skip; 933c7484f1fSmrg if (nbytes > sizeof(cbuf)) 934c7484f1fSmrg nbytes = sizeof(cbuf); 935c7484f1fSmrg nbytes = read(osm, cbuf, nbytes); 936c7484f1fSmrg } 937c7484f1fSmrg while ((nbytes = read(osm, cbuf, sizeof(cbuf))) >= 0) 938c7484f1fSmrg write(pty, cbuf, nbytes); 939c7484f1fSmrg exit(0); 940c7484f1fSmrg } 941c7484f1fSmrg signal(SIGHUP, KillChild); 942c7484f1fSmrg signal(SIGINT, KillChild); 943c7484f1fSmrg signal(SIGTERM, KillChild); 944c7484f1fSmrg return fdopen(tty, "r"); 945c7484f1fSmrg} 946c7484f1fSmrg#endif /* USE_OSM */ 947