v01i045: xplaces: toolplaces for X, Part01/01

Mike Wexler mikew at wyse.wyse.com
Fri Sep 23 09:16:34 AEST 1988


Submitted-by: ken at cs.rochester.edu (Ken Yap)
Posting-number: Volume 1, Issue 45
Archive-name: xplaces/part01

[xplaces doesn't seem to follow the draft ICCCM procedure of using the 
WM_COMMAND and WM_CLIENT_MACHINE to get the name and client machine
that the process is running on.]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  Makefile README default_setup patchlevel.h setenv.3
#   setenv.c xplaces.c xtools.1 xtools.c
# Wrapped by mikew at wyse on Thu Sep 22 15:22:57 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(791 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCFLAGS = -O -DDEFAULT_INITFILE=\"$(DEFAULT_INITFILE)\" -I/usr/include -L/usr/new/usr/lib/X11
XCONFDIR = /usr/new/usr/bin/X11
X# CFLAGS = -g -DDEFAULT_INITFILE=\"$(DEFAULT_INITFILE)\"
X
XDEFAULT_INITFILE = /usr/new/usr/lib/X11/xtools.defaults
X
X.SUFFIXES:	.o .h .c .a
X
Xall:		xtools xplaces
X
Xxtools:		xtools.o setenv.o
X		cc $(CFLAGS) -o xtools xtools.o setenv.o
X
Xsetenv.o:	setenv.c
X
Xxplaces:	xplaces.o
X		cc $(CFLAGS) -o xplaces xplaces.o -lX
X
Xinstall:
X		install -m 755 xtools $(CONFDIR)/xtools
X		install -m 755 xplaces $(CONFDIR)/xplaces
X		cp default_setup $(DEFAULT_INITFILE)
X		cp xtools.1 /usr/man/mann/xtools.n
X		cp setenv.3 /usr/man/mann/setenv.n
X#		nroff -man xtools.1 > /usr/man/cat1/xtools.1
X#		nroff -man setenv.3 > /usr/man/cat3/setenv.3
X
Xclean: 
X		rm -f *~* *.bak core *.o xtools xplaces
END_OF_FILE
if test 791 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(436 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X	xtools allows one to create a personalized window 
Xconfiguration. xtools reads the startup file $HOME/.xtools (failing 
Xthat, $Xlibrary/xtools.defaults) and starts up the tools specified.
XEach line of the file specifies a command to be executed.
XLines beginning with # are comments.
X	xplaces prints on standard output the names of the tools 
Xand the geometry. The output, after a little editing, can be used
Xin an initialization file.
END_OF_FILE
if test 436 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'default_setup' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'default_setup'\"
else
echo shar: Extracting \"'default_setup'\" \(123 characters\)
sed "s/^X//" >'default_setup' <<'END_OF_FILE'
Xxnwm -m
Xxclock -analog =164x164+980+23
Xxterm -fn vtsingle -fb vtbold =80x65+1+23
Xxterm -C -fn 6x13 -fb 6x13 =80x24+661+555
END_OF_FILE
if test 123 -ne `wc -c <'default_setup'`; then
    echo shar: \"'default_setup'\" unpacked with wrong size!
fi
# end of 'default_setup'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
echo shar: Extracting \"'patchlevel.h'\" \(21 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X#define PATCHLEVEL 0
END_OF_FILE
if test 21 -ne `wc -c <'patchlevel.h'`; then
    echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
if test -f 'setenv.3' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'setenv.3'\"
else
echo shar: Extracting \"'setenv.3'\" \(1041 characters\)
sed "s/^X//" >'setenv.3' <<'END_OF_FILE'
X.TH SETENV 3 "22 October 1985"
X.SH NAME
Xsetenv, delenv \- add/change/delete environment variables
X.SH SYNOPSIS
X.nf
X.B setenv (name, value)
X.B char *name, *value;
X
X.B delenv (name)
X.B char *name;
X.fi
X.SH DESCRIPTION
X.I Setenv
Xallows a program to set environment variables.
X.I Delenv
Xallows a program to delete them.
XThese routines follow on logically from
X.IR getenv (3).
X.SH EXAMPLES
X.nf
Xsetenv ("EDITOR", "/usr/ucb/ex");
Xdelenv ("EDITOR");
X.fi
X.SH NOTES
XThe third argument to routine
X.B main
Xstill points to the original environment after execution of these routines.
XThe flag
X.I \-lsjm
Xneeds to be given to
X.IR cc (1)
Xor
X.IR ld (1).
X.SH "RETURN VALUES"
X.I Setenv
Xand
X.I delenv
Xboth return 0 on success and -1 if enough memory couldn't be allocated.
X.I Delenv
Xcan also return 1 meaning that the
X.B name
Xwasn't found in the current environment.
XThe first call to
X.I setenv
Xor
X.I delenv
Xinitialises both routines.
XAfter that,
X.I delenv
Xcannot return -1.
X.SH "SEE ALSO"
Xgetenv (3), execve (2)
X.SH AUTHOR
XStephen J. Muir, Lancaster University.
END_OF_FILE
if test 1041 -ne `wc -c <'setenv.3'`; then
    echo shar: \"'setenv.3'\" unpacked with wrong size!
fi
# end of 'setenv.3'
fi
if test -f 'setenv.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'setenv.c'\"
else
echo shar: Extracting \"'setenv.c'\" \(4480 characters\)
sed "s/^X//" >'setenv.c' <<'END_OF_FILE'
X/* Written by Stephen J. Muir, Computing Dept., Lancaster University */
X
X# include <strings.h>
X
X/* This is the number of extra array elements to allocate each time it becomes
X * necessary.
X */
X# define INC	10
X
Xextern char	**environ, *malloc ();
Xextern int	free ();
X
Xstatic char	**original, **current, **limit;
X
X/* This routine should be called only once (when either "setenv" or "delenv" is
X * called for the first time).  It would only be called again if it fails due
X * to lack of memory.  It makes a copy of the original environment because the
X * original environment array and its elements were not obtained from "malloc"
X * and the "free" routine cannot, therefore, be called with any of its
X * elements.
X *
X * return values:
X *	 0: success
X *	-1: out of memory - nothing has changed
X */
Xstatic	/* this is a private routine */
Xinitialise ()
X	{ register char	**old, **new_ptr, *tmp, **new_env;
X
X	  /* count number of existing strings */
X	  for (old = environ; *old; ++old)
X		;
X
X	  /* make space for extra strings */
X	  if ((new_ptr =
X	       new_env =
X	       (char **)malloc (sizeof (char **) * ((old - environ) + INC + 1))
X	      )
X	      == 0
X	     )
X		return (-1);
X
X	  /* "limit" points to the last element of the array -- it is used to
X	   * decide when to recreate it
X	   */
X	  limit = new_env + (old - environ) + INC;
X
X	  /* copy across old strings */
X	  for (old = environ; *old; ++old)
X	  { if ((tmp = malloc (strlen (*old) + 1)) == 0)
X	    { /* out of memory -- undo everything */
X	      while (new_ptr != new_env)
X		free (*--new_ptr);
X	      free ((char *)new_ptr);
X	      return (-1);
X	    }
X	    strcpy (tmp, *old);
X	    *new_ptr++ = tmp;
X	  }
X	  /* "current" points to the null pointer at the end of the array */
X	  *(current = new_ptr) = 0;
X
X	  /* this is really just a flag to say it's initialised */
X	  original = environ;
X	  /* overwrite old environment with new */
X	  environ = new_env;
X	  return (0);
X	}
X
X/* This is a special routine to compare a string "name" of the form "NAME" with
X * a string "name_value" of the form "NAME=VALUE".  It returns zero if the
X * comparison is successful
X */
Xstatic	/* this is a private routine */
Xdiffer (name, name_value)
X	char	*name, *name_value;
X	{ while (*name && *name_value)
X		if (*name++ != *name_value++)
X			return (1);
X	  return (*name_value != '=');
X	}
X
X/* This routine deletes an environment variable, e.g. delenv ("SHELL");
X *
X * return values:
X *	 0: success
X *	 1: environment variable not found
X *	-1: out of memory - nothing has changed
X */
Xdelenv (name)
X	char	*name;
X	{ register char	**ptr;
X
X	  /* initialise if necessary */
X	  if (original == 0 && initialise ())
X		return (-1);
X
X	  /* attempt to find it */
X	  for (ptr = environ; *ptr && differ (name, *ptr); ++ptr)
X		;
X	  if (*ptr == 0)
X		return (1);	/* not found */
X
X	  /* delete it */
X	  free (*ptr);
X	  *ptr = *--current;
X	  *current = 0;
X	  return (0);
X	}
X
X/* This routine sets a new environment variable, replacing an existing one
X * where appropriate, e.g. setenv ("SHELL", "/bin/csh");
X *
X * return values:
X *	 0: success
X *	-1: out of memory - nothing has changed
X */
Xsetenv (name, value)
X	char	*name, *value;
X	{ register char	**old, **new_ptr, *cp, *tmp, **new_env;
X
X	  /* initialise if necessary */
X	  if (original == 0 && initialise ())
X		return (-1);
X
X	  /* allocate space for the new string */
X	  if ((cp = tmp = malloc (strlen (name) + strlen (value) + 2)) == 0)
X		return (-1);
X
X	  /* find an existing one if we can - we do this now as we will lose
X	   * the original "name" pointer in the while loop following
X	   */
X	  for (old = environ; *old && differ (name, *old); ++old)
X		;
X
X	  /* make the new entry */
X	  while (*name)
X		*cp++ = *name++;
X	  *cp++ = '=';
X	  while (*value)
X		*cp++ = *value++;
X	  *cp = '\0';
X
X	  /* case 1: overwrite previous value */
X	  if (*old)
X	  { free (*old);
X	    *old = tmp;
X	  }
X
X	  /* case 2: no previous value and no space left - allocate more */
X	  else if (current == limit)
X	  { if ((new_ptr =
X		 new_env =
X		 (char **)malloc (sizeof (char **) *
X				  ((old - environ) + INC + 1)
X				 )
X		) == 0
X	       )
X	    { free (tmp);
X	      return (-1);
X	    }
X	    limit = new_env + (old - environ) + INC;
X	    for (old = environ; *old; )
X		*new_ptr++ = *old++;
X	    *new_ptr++ = tmp;
X	    *(current = new_ptr) = 0;
X	    free ((char *)environ);
X	    environ = new_env;
X	  }
X
X	  /* case 3: no previous value and there is enough space */
X	  else
X	  { *current++ = tmp;
X	    *current = 0;
X	  }
X	  return (0);
X	}
END_OF_FILE
if test 4480 -ne `wc -c <'setenv.c'`; then
    echo shar: \"'setenv.c'\" unpacked with wrong size!
fi
# end of 'setenv.c'
fi
if test -f 'xplaces.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xplaces.c'\"
else
echo shar: Extracting \"'xplaces.c'\" \(2244 characters\)
sed "s/^X//" >'xplaces.c' <<'END_OF_FILE'
X/*
X**	A program to take a snapshot of the names and sizes of
X**	windows currently on the screen for use as an initialization spec.
X**	See manual page for further explaination.
X**
X**	Ken Yap
X**	Placed in public domain
X**	Feb 1988
X*/
X
X#include	<stdio.h>
X#include	<X11/Xlib.h>
X#include	<X11/Xutil.h>
X
Xfatal(message)
X	char		*message;
X{
X	fprintf(stderr, "%s\n", message);
X	exit(1);
X}
X
Xmain(argc, argv)
X	int		argc;
X	char		*argv[];
X{
X	register Display	*d;
X	register int		width, height;
X	int			nchildren;
X	char			*win_name;
X	Window			root_win, parent_win, *child_list;
X	XWindowAttributes	win_info;
X	XSizeHints		hints;
X
X	if ((d = XOpenDisplay(NULL)) == NULL)
X		fatal("Can't open display");
X
X	/* get a list of children of the root window */
X	if (XQueryTree(d, DefaultRootWindow(d), &root_win, &parent_win,
X		&child_list, &nchildren) == 0)
X		fatal("Can't query window tree");
X	/* scan list */
X	for ( ; nchildren-- > 0; child_list++)
X	{
X		/* what is the name? */
X		if (!XFetchName(d, *child_list, &win_name))
X			continue;		/* not fatal */
X
X		/* what do we know about it? */
X		if (!XGetWindowAttributes(d, *child_list, &win_info))
X			continue;
X
X		if (win_info.class != InputOutput)
X			continue;		/* only live windows desired */
X
X		if (!XGetNormalHints(d, *child_list, &hints))
X			continue;
X
X		/* need size either from user or program */
X		if (!(hints.flags & (USSize || PSize)))
X			continue;
X
X		/* if no increment then assume 1 */
X		if (!(hints.flags & PResizeInc))
X			hints.width_inc = hints.height_inc = 1;
X
X		/* if no position then assume +0+0 */
X		if (!(hints.flags & (USPosition || PPosition)))
X			hints.x = hints.y = 0;
X
X		/* if no min width or height then assume 0 */
X		if (!(hints.flags & PMinSize))
X			hints.min_width = hints.min_height = 0;
X
X		/* terminal windows sizes are in characters so this
X		will compute the geometry correctly */
X		if (hints.width_inc > 1 && hints.height_inc > 1)
X		{
X			width = (hints.width - hints.min_width) / hints.width_inc;
X			height = (hints.height - hints.min_height) / hints.height_inc;
X		}
X		else
X		{
X			width = win_info.width;
X			height = win_info.height;
X		}
X
X		if (win_name == NULL)
X			continue;		/* ignore anonymous windows */
X		printf("%s =%dx%d+%d+%d\n", win_name,
X			width, height, hints.x, hints.y);
X	}
X}
END_OF_FILE
if test 2244 -ne `wc -c <'xplaces.c'`; then
    echo shar: \"'xplaces.c'\" unpacked with wrong size!
fi
# end of 'xplaces.c'
fi
if test -f 'xtools.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtools.1'\"
else
echo shar: Extracting \"'xtools.1'\" \(1937 characters\)
sed "s/^X//" >'xtools.1' <<'END_OF_FILE'
X.TH XTOOLS 1 "1 Feb 1988" "X Version 11"
X.SH NAME
Xxtools - start up personal X window configuration
X.br
Xxplaces - take snapshot of personal X window configuration
X.SH SYNOPSIS
X.B xtools
X[ -f initfile ]
X.br
X.B xplaces
X.SH DESCRIPTION
X.I xtools 
Xallows one to create a personalized window configuration.
X.I xtools
Xreads the startup file $HOME/.xtools (failing that, $Xlibrary/xtools.defaults)
Xand starts up the tools specified.
XEach line of the file specifies a command to be executed.
XLines beginning with # are comments.
X.PP
X.I xtools
Xunderstands the following option:
X.PP
X.TP 8
X.B \-f \fIinitfile\fP
X\fIinitfile\fP is the name of an alternate startup file.
XIf this file cannot be found, $Xlibrary/xtools.defaults is used, if it exists.
X.PP
X.I Xtools
Xplaces its own pid in the environment variable XTOOLSPID
Xso that one can exit X at once by "kill $XTOOLSPID".
XUpon receiving SIGTERM,
X.I xtools
Xwill send SIGTERM to each of the tools in turn before exiting.
XThis command can also be taught to your favourite window manager.
X.PP
X.I xplaces
Xprints on standard output the names of the tools and the geometry.
XThe output, after a little editing, can be used
Xin an initialization file.
X.SH EXAMPLE
XHere is a configuration example:
X.sp
X.nf
Xxnwm -m
Xxclock =53x53+981+23
Xxterm -C =80x24+3+29
Xxterm =80x24+3+576
Xxterm =80x24+659+576
X.fi
X.sp
X.I xtools
Xwill start up a window manager, a clock and three terminal windows,
Xone of which will receive redirected console output on Suns.
X.PP
XOn Suns, the recommended way of running
X.I xtools
Xis by ``xinit xtools''.
XRemember to set the environment variable DISPLAY first!
X.SH SEE ALSO
Xxinit(1)
X.SH FILES
X$HOME/.xtools
X.br
X$Xlibrary/xtools.defaults
X.SH DIAGNOSTICS
XCan't find initialization file.
X.SH BUGS
X.I xplaces
Xcan only print the name the tool wants to be known by.
XThis is sometimes not the same as the name of the executable file
Xso some hand editing of the output is required.
X.SH AUTHOR
XKen Yap
END_OF_FILE
if test 1937 -ne `wc -c <'xtools.1'`; then
    echo shar: \"'xtools.1'\" unpacked with wrong size!
fi
# end of 'xtools.1'
fi
if test -f 'xtools.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtools.c'\"
else
echo shar: Extracting \"'xtools.c'\" \(4452 characters\)
sed "s/^X//" >'xtools.c' <<'END_OF_FILE'
X/*
X**	A program to start up user preferences in X windows.
X**	Reads in specs from $HOME/.xtools or $Xlibrary/xtools.
X**	See manual page for further explaination.
X**
X**	Ken Yap
X**	Placed in public domain
X**	Feb 1988
X*/
X
X#include	<stdio.h>
X#include	<signal.h>
X#include	<sys/wait.h>
X
X#ifndef	DEFAULT_INITFILE
X#define	DEFAULT_INITFILE	"/usr/new/lib/X11/xtools.defaults"
X#endif
X
Xstatic char	*progname;
X
X/* table of process id's */
Xstatic int	procid[100] = { 0 };
X#define	MAXPROCESS	(sizeof(procid)/sizeof(procid[0]))
X
Xstatic quit()
X/*
X**	Kill all children first
X*/
X{
X	register int	i;
X
X	/* send SIGTERM and SIGHUP to all children */
X	for (i = 0; i < MAXPROCESS; i++)
X		if (procid[i] > 0)
X		{
X			(void)killpg(procid[i], SIGTERM);
X			(void)kill(procid[i], SIGTERM);
X		}
X	sleep(2);		/* wait a decent interval */
X	exit(0);
X}
X
Xstatic char *skipblanks(p)
X	char	*p;
X/*
X**	Newline is whitespace too
X*/
X{
X	while (*p == ' ' || *p == '\t' || *p == '\n')
X		++p;
X	return (p);
X}
X
Xstatic char *skipword(p)
X	char	*p;
X/*
X**	But don't go past '\0'
X*/
X{
X	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
X		++p;
X	return (p);
X}
X
Xstatic int process(argv)
X	char		**argv;
X/*
X**	Fork and exec new process
X*/
X{
X	register int	pid;
X	register char	*procname;
X	char		*rindex();
X
X#ifdef	DEBUG
X	while (*argv != 0)
X		(void)printf("'%s' ", *argv++);
X	(void)printf("\n");
X	return (1);
X#endif	DEBUG
X	if ((pid = fork()) < 0)
X		return (pid);			/* error occurred */
X	if (pid > 0)				/* I am parent */
X	{
X		sleep(1);			/* give child time to startup */
X		(void)setpgrp(pid, pid);	/* ignore errors, maybe child exited quickly */
X		return (pid);
X	}
X	else					/* I am child */
X	{
X		if ((procname = rindex(*argv, '/')) == 0)
X			procname = *argv;
X		else
X			++procname;		/* last component */
X		execvp(procname, argv);
X			perror("exec");
X		exit(0);			/* should never return unless error */
X	/*NOTREACHED*/
X	}
X}
X
Xstatic execute(tool)
X	char		*tool;
X/*
X**	Chop up the command line and pass to process.
X**	Keep track of returned pid for later use.
X*/
X{
X	register char	*cmd;
X	register int	argcnt;
X	char		*argvec[100];
X#define	MAXARGS		(sizeof(argvec)/sizeof(argvec[0]))
X	register int	childpid, i;
X	char		*malloc();
X
X	if (tool[0] == '#')
X		return;			/* a comment */
X	if ((cmd = malloc(strlen(tool) + 1)) == NULL)
X		return;			/* no room */
X	(void)strcpy(cmd, tool);	/* copy command line */
X	cmd = skipblanks(cmd);
X	for (argcnt = 0; argcnt < MAXARGS - 1 && *cmd != '\0'; argcnt++)
X	{
X		argvec[argcnt] = cmd;
X		cmd = skipword(cmd);
X		if (*cmd != '\0')
X			*cmd++ = '\0';
X		cmd = skipblanks(cmd);
X	}
X	argvec[argcnt] = 0;
X	if (argcnt > 0 && (childpid = process(argvec)) > 0)
X	{
X		for (i = 0; i < MAXPROCESS; i++)	/* find free slot */
X			if (procid[i] == 0)
X				procid[i] = childpid;
X	}
X}
X
Xcleanup()
X/*
X**	Wait for zombies, if any
X*/
X{
X	register int		i, pid;
X
X	for (i = 0; i < MAXPROCESS; i++)
X		if (procid[i] > 0)
X			if (getpgrp(procid[i]) < 0)	/* gone away */
X				procid[i] = 0;		/* clear entry */
X
X	while ((pid = wait((union wait *)0)) >= 0)	/* get child */
X	{
X		for (i = 0; i < MAXPROCESS; i++)	/* remove entry */
X			if (pid == procid[i])
X			{
X				procid[i] = 0;
X				break;
X			}
X	}
X}
X
Xstatic int readfile(filename)
X	char		*filename;
X/*
X**	Attempt to open initialization file. If sucessful, read lines
X**	and send to execute.
X*/
X{
X	register FILE		*f;
X	char			line[256];
X
X	if ((f = fopen(filename, "r")) == NULL)
X		return (0);
X	while (fgets(line, sizeof(line), f) != NULL)
X		execute(line);
X	(void)fclose(f);
X	return (1);
X}
X
Xmain(argc, argv)
X	int		argc;
X	char		*argv[];
X{
X	register int		c;
X	register char		*home;
X	char			initfile[100], pidstring[20];
X	extern int		optind;
X	extern char		*optarg;
X	char			*getenv();
X
X	progname = argv[0];
X	if ((home = getenv("HOME")) != NULL)		/* if no home, use default */
X	{
X		(void)strcpy(initfile, home);
X		(void)strcat(initfile, "/.xtools");
X	}
X	else
X		(void)strcpy(initfile, DEFAULT_INITFILE);
X
X	while ((c = getopt(argc, argv, "f:")) != EOF)
X		switch (c)
X		{
X		case 'f':
X			(void)strcpy(initfile, optarg);
X			break;
X		default:
X			exit(0);
X		}
X
X	/* put own pid in environment so uwm can find it */
X	(void)sprintf(pidstring, "%d", getpid());
X	(void)setenv("XTOOLSPID", pidstring);
X
X	/* arrange to exit nicely */
X	(void)signal(SIGTERM, quit);
X
X	/* try both places */
X	if (!readfile(initfile) && !readfile(DEFAULT_INITFILE))	/* real loser */
X	{
X		(void)fprintf(stderr, "Can't find initialization file\n");
X		exit(1);
X	}
X
X	cleanup();
X	exit(0);				/* if no more children */
X}
END_OF_FILE
if test 4452 -ne `wc -c <'xtools.c'`; then
    echo shar: \"'xtools.c'\" unpacked with wrong size!
fi
# end of 'xtools.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330



More information about the Comp.sources.x mailing list