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