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