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