[comp.windows.x] better xinit needed

janssen@titan.sw.mcc.com (Bill Janssen) (09/20/88)

Here's the xinit I wrote for X10 (in shar format).  With *few* changes,
it will work for X11 as well.  Unpack it, check the placement of libraries
in the Makefile, and "make xinit".  The program does contain some X10
Xlib calls that will have to be changed to X11 (just XOpenDisplay and
XCloseDisplay, I think).  Note that the C source is created from the
".c.proto" file by the Makefile.

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by  on Mon Sep 19 18:59:53 CDT 1988
# Contents:  Makefile default-xtools xinit.1 xinit.c.proto
 
echo x - Makefile
sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
XRootConfig = /usr/local/X

XBINDIR = ${XRootConfig}/bin
XLIBDIR = ${XRootConfig}/lib/X
XINCLDIR = ${XRootConfig}/include
#
#

#

# Copyright 1986, Massachusetts Institute of Technology.

INCLUDES = -I${XINCLDIR}

CFLAGS = -g ${INCLUDES}

all: xinit

xinit: xinit.o
	cc ${CFLAGS} xinit.o -o xinit ${XLIBDIR}/libX.a

xinit.o: xinit.c
	cc ${CFLAGS} xinit.c -c

xinit.c: xinit.c.proto
	sed 's|$$<XRootConfig>|'"${XRootConfig}|g" < xinit.c.proto > xinit.c

install: xinit
	install -m 755 xinit ${XBINDIR}
	install -m 755 default-xtools ${XLIBDIR}

config: 
	-rm -f xinit.c
	make xinit.c

clean: 
	rm -f xinit.o xinit *~* *.bak core \#*

@//E*O*F Makefile//
chmod u=r,g=r,o=r Makefile
 
echo x - default-xtools
sed 's/^@//' > "default-xtools" <<'@//E*O*F default-xtools//'
#	default xtools file
#
# - window manager -
#
uwm
#
# - terminal emulator -
#
xterm =80x24+20+20
#
# - clock -
#
xclock =100x100+1000+800
@//E*O*F default-xtools//
chmod u=r,g=r,o=r default-xtools
 
echo x - xinit.1
sed 's/^@//' > "xinit.1" <<'@//E*O*F xinit.1//'
@.TH XINIT 1 "2 February 1988" "X Version 10.4  (MCC-STP)"
@.SH NAME
xinit - X window system initializer
@.SH SYNOPSIS
@.B xinit
[options] [server arguments]
@.SH DESCRIPTION
@.I Xinit
is intended to be used when the X window system server is not run automatically
from \fIinit(8)\fP,
and the window system must be started from a shell running on
the display.  This might be true, for example, if a normal login is run in a
glass-tty emulator on a workstation console, so that different window systems
can easily be run on the display at different times.  It can also be used
to start up an X session in overview mode on top of a SunView session.
@.PP
\fIXinit\fP starts up the server and a list of client applications
which are read from the file $HOME/.xtools, or from a default file.
The typical tools are
\fIxterm(1)\fP, the terminal emulator,
\fIxclock(1)\fP, a clock tool, and
\fIuwm(1)\fP, the user window manager.
If no console seems to be running on the machine (i.e., if SunView doesn't
seem to be running) a console version of \fIxterm\fP is also started.
When the user eventually terminates the X server, \fIxinit\fP automatically
terminates.
@.PP
By default, 
\fIxinit\fP expects the server to exist in an executable named ``X'' in
the search path, 
and for \fIxterm(1)\fP, \fIuwm(1)\fP, and \fIxclock(1)\fP to also exist
in the search path.  It starts
up the X server on display 0, and then starts up
all of the tools contained in the tools file, which is the file found
by looking for one of the following files in the following order:
@.br
@.in +1i
$HOME/.xtools-\fIserver-name\fP
@.br
$HOME/.xtools
@.br
\fIX-home-directory\fP/lib/default-xtools
@.br
@.in -1i
where \fIserver-name\fP is the name of the X server started,
such as ``twas:0'',
and \fIX-home-directory\fP is the directory from the various X libraries
are suspended.
@.PP
After the server is started, \fIxinit\fP will wait until it can connect
to the server, before starting any tools.  This may take as long as 90
seconds, and during that time your screen will be blank.
@.PP
Any options found, aside from those listed in the OPTIONS section of
this man page, are assumed to be options to the X server, as documented
in \fIX(1)\fP, and are passed to the server.
@.SH OPTIONS
@.TP
@.B \-\fIserver\fP server-executable
Specifies that the server \fBserver-executable\fP other than the
default X server, ``X'', is to
be used.  It is searched for using the user's normal exec path.
@.TP
@.B \-\fIoverview\fP
Specifies that the X server is to be run in \fIoverview(1)\fP mode over an
existing SunView window server.  When in overview mode, the server
will respond to \fBXUnmapWindow (RootWindow)\fP by suspending the
server, which will in turn cause overview to iconify.  Similarly, when
in overview mode, the server will respond to
\fBXDestroyWindow (RootWindow)\fP by terminating the server.  The
\fIuwm(1)\fP options \fBf.suspend\fP and \fBf.kill-X\fP use these calls
to accomplish their actions.
@.TP
@.B \-\fIdebug\fP
Enables some debugging print out.  Not generally useful.
@.TP
@.B \-\fInoconsole\fP
Specifies that no console window is to be started automatically,
even if xinit believes that one should be started.  xinit will normally
start one if there is no evidence that Suntools is running.
@.TP
@.B \-\fItoolsfile\fP filename
Specifies that the tools to be started up after the server is running
are to be read from the file \fBfilename\fP.
@.SH EXAMPLES
@.sp
@.B xinit -server /usr/local/X10/bin/Xsun-new -toolsfile newtools
@.sp
@.in +1i
Specifies that the server program /usr/local/X10/bin/Xsun-new is to be used,
and the tools to be started are described in the file ``newtools''.
@.sp
@.in -1i
@.sp
\fBxinit /dev/cgtwo0 1 -0 DarkGreen -1 Wheat\fP
@.sp
@.in +1i
None of the arguments or options are for \fIxinit\fP, so they
are passed as arguments to the X server.  (They
specify that the normal X server is to be run on device ``/dev/cgtwo0'',
that the display is to be number 1 (``host:1''), that the ``black''
color is to be DarkGreen, and the ``white'' color is to be Wheat.)
@.in -1i
@.sp
@.B xinit -overview
@.sp
@.in +1i
Specifies that the X server is to be run under \fIoverview(1)\fP.
@.in -1i
@.SH FILES
$HOME/.xtools-\fIdisplay\fP
@.br
$HOME/.xtools
@.br
\fIX-home-directory\fP/lib/default-xtools
@.sp
These files contain a number of lines, specifying tools to start up
attached to the newly-started X server.  Blank lines and lines beginning
with the comment character `#' are ignored.  The default file contains
the lines:
@.sp
@.in +1i
@.F B
@.nf
#	default xtools file
#
# - window manager -
#
uwm
#
# - terminal emulator -
#
xterm =80x24+20+20
#
# - clock -
#
xclock -analog =100x100+1000+800
@.fi
@.in -1i
@.F R
@.sp
@.SH AUTHOR
Bill Janssen, MCC Software Technology Program
@.SH "SEE ALSO"
X(1), X(8C), xterm(1), uwm(1), xclock(1), overview(1)
@//E*O*F xinit.1//
chmod u=r,g=r,o=r xinit.1
 
echo x - xinit.c.proto
sed 's/^@//' > "xinit.c.proto" <<'@//E*O*F xinit.c.proto//'
#include <X/mit-copyright.h>

/* Copyright    Massachusetts Institute of Technology    1986	*/

#include <stdio.h>
#include <ctype.h>
#include <signal.h>

#include <X/Xlib.h>	/* for XOpenDisplay and XCloseDisplay */

char *getenv();

#define default_server  "X"
#define default_screen  "/dev/fb"
#define default_display "0"

#define DEFAULT_TOOLS_FILENAME  "$<XRootConfig>/lib/X/default-xtools"

#define DEFAULT_XFONTPATH	"$<XRootConfig>/lib/X/font"

char   *server[255];
char   *client[255];
char   *Toolsfile = NULL;

static char envbuf[256];
static char fontpathbuf[256];

short   debug = 0;

short   overview = 0;

char    *display_number;
char    server_name[255];

char    HomeDirectory[256];
int	SunviewPresent;
char    *ServerProgram;
int	NoConsole;

/* ************************************************************ */
/*                                                              */
/*                                                              */
/* ************************************************************ */

main(argc, argv)
int     argc;
char  **argv;
{
  int serverpid;


    ScanArguments(argc, argv);


    serverpid = InitServerAndClient();


    WaitForServer(serverpid);

}


/* ************************************************************ */
/*                                                              */
/*                                                              */
/* ************************************************************ */

/* scan the argument list for xinit and create the "server" and
   "client" argument lists */

ScanArguments(argc, argv)
int     argc;
register char **argv;
{
    register char **ptr;
    register char **sptr = server;
    register char **cptr = client;
    char hostnamebuf[64];
    char *home;

    SunviewPresent = (getenv ("WINDOW_PARENT") != NULL);
    home = getenv ("HOME");
    strcpy (HomeDirectory, home);
    ServerProgram = default_server;
    NoConsole = 0;

 /* skip over the first argument -- xinit program name */
    argv++, argc--;

 while (argc > 0)
   {
     /* test for debug switch */

     if (strcmp(*argv, "-debug") == 0)
       {
	 debug = 1;
	 fprintf(stderr, "Debugging on\n");
	 argv++, argc--;
       }

     /* test for overview mode */

     else if (strcmp(*argv, "-overview") == 0)
       {
	 if (SunviewPresent)
	   {
	     *sptr++ = "/usr/bin/overview";
	     *sptr++ = "-w";
	   }
	 overview = 1;
	 argv++, argc--;
       }

     /* test for tools file */

     else if ((argc > 1) && strcmp(*argv, "-toolsfile") == 0)
       {
	 Toolsfile = argv[1];
	 if (debug) fprintf (stderr, "tool file is %s\n", Toolsfile);
	 argv += 2;  argc -= 2;
      }

     /* test for no-console flag */

     else if (strcmp (*argv, "-noconsole") == 0)
       {
	 NoConsole = 1;
	 if (debug) fprintf (stderr, "NoConsole is true\n");
	 argv++, argc--;
       }

     /* test for non-standard server */

     else if ((argc > 1) && strcmp (*argv, "-server") == 0)
       {
	 ServerProgram = argv[1];
	 argv += 2;
	 argc -= 2;
       }

     else
       break;
   }

    *sptr++ = ServerProgram;

 /* next arguments are to X */

    if (argc == 0)		/* use defaults:  "X" */
      {
	*sptr++ = default_screen;
	display_number = default_display;
	*sptr++ = default_display;
      }
    else if (**argv == '/')     /* "X <device> ..." */
      {
	*sptr++ = *argv++;
	argc--;
	if (argc > 0 && isdigit(**argv))	/* "X <device> <number> ..." */
	  {
	    *sptr++ = display_number = *argv++;
	    argc--;
	  }
	else
	  *sptr++ = display_number = default_display;
      }
    else if (isdigit(**argv))			/* "X <number> ..." */
      {
	*sptr++ = default_screen;
	*sptr++ = display_number = *argv++;
	argc--;
      }
    else					/* "X ..." */
      {
	*sptr++ = default_screen;
	display_number = default_display;
	*sptr++ = default_display;
      }

    if (debug)
	{
	    fprintf(stderr, "Parsing options, arguments so far are:  ");
	    WriteArguments(server);
	}

 /* copy the rest of the parameters to give to the server */

    while (--argc >= 0)
	*sptr++ = *argv++;
    *sptr = NULL;

 /* create the name of the server */

    gethostname (hostnamebuf, sizeof(hostnamebuf));
    sprintf (server_name, "%s:%s", hostnamebuf, display_number);

}


/* ************************************************************ */
/*                                                              */
/*                                                              */
/* ************************************************************ */

InitServerAndClient()
{
    int     serverpid;
    int     clientpid;
    int     pid;
    Display *disp;
    char    *fontpath;

    /* set up font path */

    if ((fontpath = getenv("XFONTPATH")) == NULL)
      {
	fprintf (fontpathbuf, "XFONTPATH=%s", DEFAULT_XFONTPATH);
	putenv (fontpathbuf);
      }

    if (debug)
	{
	    fprintf(stderr, "Starting server: ");
	    WriteArguments(server);
	}

 /* fork a subprocess for the server */

    serverpid = fork();
    if (debug) fprintf(stderr,  "Server pid is %d\n",serverpid);
    if (serverpid == 0)
	{
	    close(0);
	    close(1);
	    execvp(server[0], server);
	    perror(server[0]);
	    exit(1);
	}
    if (serverpid < 0)
	{
	    fprintf(stderr, "Couldn't fork server\n");
	    perror(server[0]);
	    exit(1);
	}

    /* wait for the server to get started */

    if (debug) fprintf (stderr, "Attempting to open display %s\n",
			server_name);
    while ((disp = XOpenDisplay (server_name)) == NULL)
      sleep (2);
    if (debug) fprintf (stderr, "Opened display %s\n", DisplayName());
    XCloseDisplay (disp);

    /* set up the name of the display in the environment */

    sprintf (envbuf, "DISPLAY=%s", server_name);
    putenv (envbuf);

    /* if no evidence of suntools start a console */

    if ((! SunviewPresent) && (! NoConsole))
      system ("xterm -n Console -C =80x24+0+0 &");

    /* start tools */

    StartTools (Toolsfile);

    return serverpid;
}


/* ************************************************************ */
/*                                                              */
/*                                                              */
/* ************************************************************ */

/* print an argument list */

WriteArguments(argv)
char **argv;
{
  while (*argv != NULL)
    fprintf(stderr, "%s ", *argv++);
  fprintf(stderr, "\n");
}


/* start tools, reading from file $HOME/.xtools if present, and from
   $<XRootConfig>/lib/X/default-xtools otherwise.
*/

StartTools (toolsfile)

     char *toolsfile;
{
  char *home;
  FILE *file;
  char buf[256];
  char command[256];
  int  buflen, i;

  if (toolsfile != NULL)
    file = fopen (toolsfile, "r");
  else
    file = NULL;

  if (file != NULL && debug) fprintf (stderr, "tools file is %s\n", toolsfile);

  if ((file == NULL) && (HomeDirectory != NULL))
    {
      sprintf (buf, "%s/.xtools-%s", HomeDirectory, server_name);
      file = fopen (buf, "r");
      if (file != NULL && debug)
	fprintf (stderr, "tools file is %s\n", buf);
      if (file == NULL)
	{
	  sprintf (buf, "%s/.xtools", HomeDirectory);
	  file = fopen (buf, "r");
	  if (file != NULL && debug)
	    fprintf (stderr, "tools file is %s\n", buf);
	}
    }

  if (file == NULL)
    file = fopen (DEFAULT_TOOLS_FILENAME, "r");
  if (file != NULL && debug)
    fprintf (stderr, "tools file is %s\n", DEFAULT_TOOLS_FILENAME);


  if (file == NULL)
    {
      hard_coded_defaults();
      return;
    }

  while (fgets (buf, sizeof(buf), file) != NULL)
    {
      if (*buf == '#')			/* comment line */
	continue;
      buf[buflen = strlen(buf) - 1] = '\0';	/* remove newlines */
      for (i = buflen;  i >= 0;  i -= 1)
	if (!isspace(buf[i]))
	  break;
      if (i < 0)
	continue;				/* ignore blank lines */
      sprintf (command, "%s &", buf);
      if (debug) fprintf (stderr, "command is %s\n", command);
      system (command);
    }
}

hard_coded_defaults ()
{
  if (debug) fprintf (stderr, "using hard-coded tool defaults\n");
  system ("xterm =80x24+20+20 &");
  system ("uwm &");
  system ("xclock -analog =100x100+1000+790 &");
}

WaitForServer (pid)

     int pid;
{
  int i;

  while ((i = wait (0)) != pid)
    ;
}
@//E*O*F xinit.c.proto//
chmod u=r,g=r,o=r xinit.c.proto
 
exit 0
--