[comp.sources.x] v01i001: xtools: an easy way to start X programs

mikew@wyse.wyse.com (Mike Wexler) (08/16/88)

Submitted-by: rusty@cartan.berkeley.edu (Rusty C. Wright)
Posting-number: Volume 1, Issue 1
Archive-name: xtools/part01

[Xtools is a convenient way to start up your X applications when your system
doesn't support starting up the X window system from the getty process.
The applications that xtools starts up are specified in a .xtools file.
You can have different .xtools files, one for each host.
I had a couple of problems with it.  First it didn't understand 
shell notations suchs as "abc def" as being one parameter.  Second
when running under awm, its confirmation box had to be positioned with
the mouse and it appeared behind the main xtools window anyway.]

#! /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 shell archive."
# Contents:  top_setup.c home_setup.c quit_button.c help_button.c
#   confirm_setup.c main.c client_start.c globs.c parse.c yep_button.c
#   nope_button.c setenv.c home_globs.h globs.h confirm_globs.h
#   xtools.xbm Imakefile dot_xtools xtools.man setenv.3
# Wrapped by rusty@velveeta on Tue Jul  5 21:37:52 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'top_setup.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'top_setup.c'\"
else
echo shar: Extracting \"'top_setup.c'\" \(1679 characters\)
sed "s/^X//" >'top_setup.c' <<'END_OF_FILE'
X# include <X11/Intrinsic.h>
X# include <X11/StringDefs.h>
X# include <X11/Command.h>
X# include <X11/Shell.h>
X# include <X11/Form.h>
X# include <stdio.h>
X
X# include "home_globs.h"
X# include "globs.h"
X
X# include "xtools.xbm"
X
XString			display_name;
Xstatic Widget		top_shell;
X
Xstatic XrmOptionDescRec options[] = {
X	{ "-file",	"file",		XrmoptionSepArg,	NULL },
X	{ "-debug",	"debug",	XrmoptionIsArg,		"False" },
X};
X
Xstatic XtResource	resources[] = {
X	{ "file", "file", XtRString, sizeof(char *), (Cardinal) &file,
X		  XtRString, NULL },
X	{ "debug", "debug", XtRBoolean, sizeof(Boolean), (Cardinal) &debug,
X		  XtRBoolean, 0 },
X};
X
XWidget
Xtop_setup(argc, argv)
X	int		argc;
X	char		**argv;
X{
X	Widget		top_form;
X	Arg		args[1];
X
X	top_shell = XtInitialize("top", "XTools", options,
X				 XtNumber(options), &argc, argv );
X	if (argc != 1)
X		usage();
X
X	XtGetApplicationResources(top_shell, (caddr_t) NULL, resources,
X				  XtNumber(resources), NULL, 0);
X
X	XtSetArg(args[0], XtNiconPixmap,
X		 XCreateBitmapFromData(XtDisplay(top_shell),
X				       XtScreen(top_shell)->root,
X				       xtools_bits, xtools_width,
X				       xtools_height));
X	XtSetValues(top_shell, args, 1);
X
X	XtSetArg(args[0], XtNallowShellResize, True);
X	XtSetValues(top_shell, args, 1);
X
X# ifdef use_popup
X	top_form = top_shell;
X# else /* use_popup */
X	top_form = XtCreateManagedWidget("top", formWidgetClass, top_shell,
X				  NULL, 0);
X
X	XtSetArg(args[0], XtNallowShellResize, True);
X	XtSetValues(top_form, args, 1);
X# endif /* use_popup */
X
X	display_name = XDisplayString(XtDisplay(top_shell));
X
X	return(top_form);
X}
X
Xvoid
Xtop_start(home_form)
X	Widget		home_form;
X{
X	XtManageChild(home_form);
X	XtRealizeWidget(top_shell);
X}
END_OF_FILE
if test 1679 -ne `wc -c <'top_setup.c'`; then
    echo shar: \"'top_setup.c'\" unpacked with wrong size!
fi
# end of 'top_setup.c'
fi
if test -f 'home_setup.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'home_setup.c'\"
else
echo shar: Extracting \"'home_setup.c'\" \(1399 characters\)
sed "s/^X//" >'home_setup.c' <<'END_OF_FILE'
X# include <X11/Intrinsic.h>
X# include <X11/StringDefs.h>
X# include <X11/Command.h>
X# include <X11/Form.h>
X# include <stdio.h>
X
X# include "home_globs.h"
X
Xstatic char label_text[] = "xtools";
X
Xstatic Arg label_args[] = {
X	{ XtNlabel,		(XtArgVal) label_text },
X	{ XtNborderWidth,	(XtArgVal) 0 },
X};
X
Xstatic int label_args_n = XtNumber(label_args);
X
XWidget		quit_button;
X
XWidget
Xhome_setup(parent)
X	Widget		parent;
X{
X	Widget		home_form;
X	Widget		label_widget;
X	Widget		help_button;
X	Arg		args[1];
X
X	home_form = XtCreateWidget("home", formWidgetClass, parent,
X				   NULL, 0);
X
X	label_widget = XtCreateManagedWidget("home", labelWidgetClass,
X					     home_form, label_args,
X					     label_args_n);
X
X	quit_button = XtCreateManagedWidget("quit", commandWidgetClass,
X					    home_form, quit_button_args,
X					    quit_button_args_n);
X	XtSetArg(args[0], XtNfromVert, label_widget);
X	XtSetValues(quit_button, args, 1);
X	XtAddCallback(quit_button, XtNcallback, quit_func,
X		      (caddr_t) home_form);
X
X	help_button = XtCreateManagedWidget("help", commandWidgetClass,
X					    home_form, help_button_args,
X					    help_button_args_n);
X	XtSetArg(args[0], XtNfromHoriz, quit_button);
X	XtSetValues(help_button, args, 1);
X	XtSetArg(args[0], XtNfromVert, label_widget);
X	XtSetValues(help_button, args, 1);
X	XtAddCallback(help_button, XtNcallback, help_func,
X		      (caddr_t) home_form);
X
X	return(home_form);
X}
END_OF_FILE
if test 1399 -ne `wc -c <'home_setup.c'`; then
    echo shar: \"'home_setup.c'\" unpacked with wrong size!
fi
# end of 'home_setup.c'
fi
if test -f 'quit_button.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'quit_button.c'\"
else
echo shar: Extracting \"'quit_button.c'\" \(476 characters\)
sed "s/^X//" >'quit_button.c' <<'END_OF_FILE'
X# include <X11/Intrinsic.h>
X# include <X11/StringDefs.h>
X# include <stdio.h>
X
X# include "home_globs.h"
X# include "confirm_globs.h"
X
Xstatic char	quit_button_label[] = "quit";
X
XArg quit_button_args[] = {
X	{ XtNlabel,		(XtArgVal) quit_button_label }
X};
X
Xint quit_button_args_n = XtNumber(quit_button_args);
X
Xvoid
Xquit_func(w, client_data, call_data)
X	Widget		w;
X	caddr_t		client_data;
X	caddr_t		call_data;
X{
X	XtSetSensitive(quit_button, False);
X	confirm((Widget) client_data);
X}
END_OF_FILE
if test 476 -ne `wc -c <'quit_button.c'`; then
    echo shar: \"'quit_button.c'\" unpacked with wrong size!
fi
# end of 'quit_button.c'
fi
if test -f 'help_button.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'help_button.c'\"
else
echo shar: Extracting \"'help_button.c'\" \(491 characters\)
sed "s/^X//" >'help_button.c' <<'END_OF_FILE'
X# include <X11/Intrinsic.h>
X# include <X11/StringDefs.h>
X# include <X11/Form.h>
X# include <stdio.h>
X
X# include "home_globs.h"
X
Xstatic char	help_button_label[] = "help";
X
XArg help_button_args[] = {
X	{ XtNlabel,		(XtArgVal) help_button_label },
X	{ XtNsensitive,		(XtArgVal) False },
X};
X
Xint help_button_args_n = XtNumber(help_button_args);
X
Xvoid
Xhelp_func(w, client_data, call_data)
X	Widget		w;
X	caddr_t		client_data;
X	caddr_t		call_data;
X{
X	/* (void) printf("no help at the moment.\n"); */
X}
END_OF_FILE
if test 491 -ne `wc -c <'help_button.c'`; then
    echo shar: \"'help_button.c'\" unpacked with wrong size!
fi
# end of 'help_button.c'
fi
if test -f 'confirm_setup.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'confirm_setup.c'\"
else
echo shar: Extracting \"'confirm_setup.c'\" \(2616 characters\)
sed "s/^X//" >'confirm_setup.c' <<'END_OF_FILE'
X# include <X11/Intrinsic.h>
X# include <X11/StringDefs.h>
X# include <X11/Command.h>
X# include <X11/Shell.h>
X# include <X11/Form.h>
X# include <stdio.h>
X
X# include "home_globs.h"
X# include "confirm_globs.h"
X# include "globs.h"
X
XWidget		confirm_form;
X
X# ifdef use_popup
XWidget		confirm_popup;
X
Xstatic Arg confirm_popup_args[] = {
X	{ XtNx,		0 },
X	{ XtNy,		0 }
X};
X
Xstatic int confirm_popup_args_n = XtNumber(confirm_popup_args);
X# endif /* use_popup */
X
Xstatic char label_text[] = "REALLY QUIT?";
X
Xstatic Arg label_args[] = {
X	{ XtNlabel,		(XtArgVal) label_text },
X	{ XtNborderWidth,	(XtArgVal) 0 },
X};
X
Xstatic int label_args_n = XtNumber(label_args);
X
XWidget
Xconfirm_setup(parent, home_form)
X	Widget		parent;
X	Widget		home_form;
X{
X	Widget		yep_button;
X	Widget		nope_button;
X	Widget		label_widget;
X	Arg		args[1];
X
X# ifdef use_popup
X	XtSetArg(confirm_popup_args[0], XtNx,
X		 DisplayWidth(XtDisplay(parent),
X			      XDefaultScreen(XtDisplay(parent)))/2);
X	XtSetArg(confirm_popup_args[1], XtNy,
X		 DisplayHeight(XtDisplay(parent),
X			      XDefaultScreen(XtDisplay(parent)))/2);
X
X	confirm_popup = XtCreatePopupShell("confirm",
X					   transientShellWidgetClass, parent,
X					   confirm_popup_args,
X					   confirm_popup_args_n);
X
X	confirm_form = XtCreateManagedWidget("confirm", formWidgetClass,
X					     confirm_popup, NULL, 0);
X# else /* use_popup */
X	confirm_form = XtCreateWidget("confirm", formWidgetClass,
X					     parent, NULL, 0);
X# endif /* use_popup */
X
X/*	XtSetArg(label_args[2], XtNfont, query_font); */
X	label_widget = XtCreateManagedWidget("confirm", labelWidgetClass,
X					     confirm_form, label_args,
X					     label_args_n);
X
X	yep_button = XtCreateManagedWidget("yep", commandWidgetClass,
X					   confirm_form, yep_button_args,
X					   yep_button_args_n);
X	XtSetArg(args[0], XtNfromVert, label_widget);
X	XtSetValues(yep_button, args, 1);
X	XtAddCallback(yep_button, XtNcallback, yep_func, (caddr_t) parent);
X
X	nope_button = XtCreateManagedWidget("nope", commandWidgetClass,
X					    confirm_form, nope_button_args,
X					    nope_button_args_n);
X	XtSetArg(args[0], XtNfromVert, label_widget);
X	XtSetValues(nope_button, args, 1);
X	XtSetArg(args[0], XtNfromHoriz, yep_button);
X	XtSetValues(nope_button, args, 1);
X	XtAddCallback(nope_button, XtNcallback, nope_func,
X		      (caddr_t) home_form);
X
X# ifdef use_popup
X	XtRealizeWidget(confirm_popup);
X# endif /* use_popup */
X
X	return(confirm_form);
X}
X
Xconfirm(home_form)
X	Widget		home_form;
X{
X# ifdef use_popup
X	XtPopup(confirm_popup, XtGrabExclusive);
X# else /* use_popup */
X	XtUnmanageChild(home_form);
X	XtManageChild(confirm_form);
X# endif /* use_popup */
X}
END_OF_FILE
if test 2616 -ne `wc -c <'confirm_setup.c'`; then
    echo shar: \"'confirm_setup.c'\" unpacked with wrong size!
fi
# end of 'confirm_setup.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(692 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X# include <X11/Intrinsic.h>
X# include <stdio.h>
X
X# include "home_globs.h"
X# include "globs.h"
X
Xmain(argc, argv)
X	int		argc;
X	char		**argv;
X{
X	extern void	top_start();
X	Widget		top_form;
X	Widget		home_form;
X
X	/*
X	 * top_setup calls xtinitialize which parses argv for us.
X	 */
X	top_form = top_setup(argc, argv);
X
X	setenv("DISPLAY", display_name);
X
X	/*
X	 * client_start reads .xtools and starts the clients.
X	 */
X	if (client_start() == -1)
X		exit(1);
X
X	if (! debug) {
X		home_form = home_setup(top_form);
X		top_start(home_form);
X		(void) confirm_setup(top_form, home_form);
X
X		XtMainLoop();
X	}
X
X	exit(0);
X}
X
Xusage() {
X	(void) fprintf(stderr, "usage: xtools [-debug] [-file name]\n");
X	exit(1);
X}
END_OF_FILE
if test 692 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'client_start.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'client_start.c'\"
else
echo shar: Extracting \"'client_start.c'\" \(5194 characters\)
sed "s/^X//" >'client_start.c' <<'END_OF_FILE'
X# include <X11/Intrinsic.h>
X# include <sys/wait.h>
X# include <sys/file.h>
X# include <signal.h>
X# include <fcntl.h>
X# include <pwd.h>
X# include <stdio.h>
X
X# include "globs.h"
X
Xstatic int	pids[128];
Xstatic int	npids;
Xstatic int	dohang;
X
X/*
X * client_start reads the .xtools file and runs each line.
X */
Xclient_start() {
X	extern char	*index();
X	extern void	shutdown();
X	extern void	cleanup();
X	extern char	*getname();
X	extern char	*getline();
X	FILE		*fd;
X	char		*cp;
X
X	/*
X	 * if getname can't file a .xtools file then just
X	 * start an xterm console.
X	 */
X	if ((cp = getname()) == NULL) {
X		if (execute("xterm -C &") == -1) {
X			fprintf(stderr, "can't start console xterm\n");
X			return(-1);
X		}
X		return(0);
X	}
X
X	if ((fd = fopen(cp, "r")) == NULL) {
X		(void) fprintf(stderr, "open: ");
X		perror(cp);
X		return(-1);
X	}
X
X	if (fcntl(fileno(fd), F_SETFD, 1) == -1) {
X		(void) fprintf(stderr, "fcntl: ");
X		perror(cp);
X		(void) fclose(fd);
X		return(-1);
X	}
X
X	(void) signal(SIGINT, (int (*)()) shutdown);
X	(void) signal(SIGCHLD, (int (*)()) cleanup);
X
X	while ((cp = getline(fd)) != NULL) {
X		if (execute(cp) == -1)
X			(void) fprintf(stderr, "can't execute \"%s\"\n", cp);
X	}
X	dohang = 0;
X
X	fclose(fd);
X
X	return(0);
X}
X
X/*
X * getname returns the pathname to the user's .xtools file.
X */
Xstatic char *
Xgetname() {
X	extern char	*getenv();
X	extern char	*rindex();
X	struct passwd	*pw;
X	char		*home, *cp;
X	char		host[128];
X	static char	path[256];
X
X	if (file != NULL)
X		return(file);
X
X	if ((home = getenv("HOME")) == NULL) {
X		if ((pw = getpwuid(getuid())) == NULL) {
X			(void) fprintf(stderr, "who are you?\n");
X			return(NULL);
X		}
X		home = pw->pw_dir;
X		endpwent();
X	}
X
X	/*
X	 * try finding a .xtools file of the form .xtools-hostname, where
X	 * hostname can be the fully qualified host name or it can have
X	 * the upper domains missing.  for example,
X	 *	.xtools-velveeta.berkeley.edu
X	 *	.xtools-velveeta.berkely
X	 *	.xtools-velveeta
X	 * will all work.
X	 */
X	if (gethostname(host, sizeof(host)) != -1) {
X		sprintf(path, "%s/.xtools-%s", home, host);
X		if (access(path, F_OK) == 0)
X			return(path);
X
X		/* try trimming off domain */
X		while ((cp = rindex(host, '.')) != NULL) {
X			*cp = NULL;
X			sprintf(path, "%s/.xtools-%s", home, host);
X			if (access(path, F_OK) == 0)
X				return(path);
X		}
X	}
X
X	sprintf(path, "%s/.xtools", home);
X
X	if (access(path, F_OK) == 0)
X		return(path);
X
X	(void) strcpy(path, DEFAULT_STARTUP);
X
X	if (access(path, F_OK) == 0)
X		return(path);
X
X	return(NULL);
X}
X
X/*
X * execute runs the line and remembers the pid of the process.
X */
Xstatic
Xexecute(line)
X	char		*line;
X{
X	extern char	**getargs();
X	extern void	checkamp();
X	char		**args;
X	int		pid;
X	int		i;
X
X	if ((args = getargs(line)) == NULL)
X		return(-1);
X
X	checkamp(args);
X
X	if (debug) {
X		(void) printf("execvp(\"%s\"", args[0]);
X		for (i = 1; args[i] != NULL; i++)
X			(void) printf(", \"%s\"", args[i]);
X		(void) printf(")\n");
X		return(0);
X	}
X
X	if ((pid = fork()) == 0) {
X		if (setpgrp(0, getpid()) == -1)
X			perror("setpgrp(0)");
X
X		execvp(args[0], &args[0]);
X
X		(void) fprintf(stderr, "can't execvp(\"%s\"): ", args[0]);
X		perror("execvp");
X		exit(1);
X	}
X	else if (pid > 0) {
X		for (i = 0; i < npids; i++) {
X			if (pids[i] == 0)
X				pids[i] = pid;
X		}
X		if (i == npids)
X			pids[npids++] = pid;
X
X		/* sleep(1); */	/* helps reduce thrashing */
X
X		/*
X		 * don't bother checking return status because
X		 * some programs do their work and then exit.
X		 */
X		(void) setpgrp(pid, pid);
X	}
X	else	/* pid == -1, fork failed */
X		return(-1);
X
X	cleanup();
X
X	return(0);
X}
X
X/*
X * checkamp checks for an ampersand as either
X * the last argument (i.e., it has a space in
X * front of it, or the last argument has an
X * ampersand appended to it.
X */
Xstatic void
Xcheckamp(args)
X	char	**args;
X{
X	int	i, amploc;
X	char	*cp;
X
X	dohang = 1;
X
X	for (i = 0; args[i] != NULL; i++)
X		continue;
X
X	i--;	/* back up to last non-NULL arg */
X
X	cp = args[i];
X	if (strcmp(cp, "&") == 0) {
X		args[i] = NULL;
X		dohang = 0;
X	}
X	else if (cp[amploc = strlen(cp)-1] == '&') {
X		cp[amploc] = NULL;
X		dohang = 0;
X	}
X}
X
X# define SIGS	(sizeof(sigs) / sizeof(sigs[0]))
Xint	sigs[] = { SIGTERM /* , SIGHUP, SIGKILL */ };
X
X/*
X * shutdown is called when quitting.  it kills all outstanding
X * processes.
X */
Xstatic void
Xshutdown() {
X	int		i, j;
X
X	for (j = 0; j < SIGS; j++) {
X		for (i = 0; i < npids; i++) {
X			if (pids[i] == 0)
X				continue;
X
X			/*
X			 * don't try to kill children that have
X			 * already exited.
X			 */
X			if (getpgrp(pids[i]) == -1) {
X				pids[i] = 0;
X				continue;
X			}
X
X			if (killpg(pids[i], sigs[j]) == -1) {
X				if (debug)
X					(void) printf("can't kill pid %d\n",
X						      pids[i]);
X				continue;
X			}
X		}
X	}
X
X	dohang = 0;
X	cleanup();
X
X	exit(0);
X}
X
X/*
X * cleanup collectes dead children.
X */
Xstatic void
Xcleanup() {
X	union wait	status;
X	int		options;
X	int		pid;
X	int		i;
X
X	options = (dohang == 1) ? 0 : WNOHANG;
X
X	while ((pid = wait3(&status, options, (struct rusage *) NULL)) > 0) {
X		for (i = 0; i < npids; i++) {
X			if (pids[i] == pid) {
X				if (debug)
X					(void) printf("caught pid %d\n",
X						      pids[i]);
X				pids[i] = 0;
X			}
X		}
X
X		/* pull up the tail */
X		while (pids[npids-1] == 0) {
X			npids--;
X			if (npids == 0)
X				return;
X		}
X	}
X}
END_OF_FILE
if test 5194 -ne `wc -c <'client_start.c'`; then
    echo shar: \"'client_start.c'\" unpacked with wrong size!
fi
# end of 'client_start.c'
fi
if test -f 'globs.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'globs.c'\"
else
echo shar: Extracting \"'globs.c'\" \(84 characters\)
sed "s/^X//" >'globs.c' <<'END_OF_FILE'
X# include <X11/Intrinsic.h>
X
XXFontStruct	*query_font;
XBoolean		debug;
XString		file;
END_OF_FILE
if test 84 -ne `wc -c <'globs.c'`; then
    echo shar: \"'globs.c'\" unpacked with wrong size!
fi
# end of 'globs.c'
fi
if test -f 'parse.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'parse.c'\"
else
echo shar: Extracting \"'parse.c'\" \(1327 characters\)
sed "s/^X//" >'parse.c' <<'END_OF_FILE'
X# include <X11/Intrinsic.h>
X# include <X11/StringDefs.h>
X# include <ctype.h>
X# include <stdio.h>
X
X# include "globs.h"
X
X/*
X * getline reads a line from the .xtools file and trims
X * any leading whitespace.  lines that begin with a # and
X * empty lines are skipped.
X */
Xchar *
Xgetline(fd)
X	FILE		*fd;
X{
X	extern char	*index();
X	static char	buf[BUFSIZ];
X	char		*cp;
X
X	for (cp = &buf[0]; cp < &buf[BUFSIZ]; cp++)
X		*cp = 0;
X
X	for (;;) {
X		if (fgets(buf, sizeof(buf), fd) == NULL)
X			return(NULL);
X
X		if ((cp = index(buf, '\n')) != NULL)
X			*cp = NULL;
X
X		/* skip leading spaces */
X		for (cp = &buf[0]; *cp != NULL; cp++) {
X			if (! isspace(*cp))
X				break;
X		}
X
X		if ((*cp != NULL) && (*cp != '#'))
X			break;
X	}
X
X	return(cp);
X}
X
X# define MAXARGS	128
X
X/*
X * getargs breaks up a space-delimited line and returns it
X * as an array of char *.
X */
Xchar **
Xgetargs(line)
X	char		*line;
X{
X	static char	*args[MAXARGS];
X	char		*cp;
X	int		i;
X
X	for (i = 0; i < MAXARGS; i++)
X		args[i] = NULL;
X
X	cp = line;
X
X	for (i = 0; *cp != NULL; i++) {
X		args[i] = cp;
X
X		/* skip to end of word */
X		while ((*cp != NULL) && (! isspace(*cp)))
X			cp++;
X
X		if (*cp == NULL)
X			break;
X
X		*cp++ = NULL;
X
X		if (debug)
X			(void) printf("args[%d]=%s\n", i, args[i]);
X
X		/* skip over spaces */
X		while ((*cp != NULL) && (isspace(*cp)))
X			cp++;
X	}
X
X	return(args);
X}
END_OF_FILE
if test 1327 -ne `wc -c <'parse.c'`; then
    echo shar: \"'parse.c'\" unpacked with wrong size!
fi
# end of 'parse.c'
fi
if test -f 'yep_button.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'yep_button.c'\"
else
echo shar: Extracting \"'yep_button.c'\" \(468 characters\)
sed "s/^X//" >'yep_button.c' <<'END_OF_FILE'
X# include <X11/Intrinsic.h>
X# include <X11/StringDefs.h>
X# include <X11/Form.h>
X# include <stdio.h>
X
Xstatic char	yep_button_label[] = "yep";
X
XArg yep_button_args[] = {
X	{ XtNfromVert,		(XtArgVal) NULL },
X	{ XtNlabel,		(XtArgVal) yep_button_label }
X};
X
Xint yep_button_args_n = XtNumber(yep_button_args);
X
Xvoid
Xyep_func(w, client_data, call_data)
X	Widget		w;
X	caddr_t		client_data;
X	caddr_t		call_data;
X{
X	XtDestroyWidget((Widget) client_data);
X	shutdown();
X	exit(0);
X}
END_OF_FILE
if test 468 -ne `wc -c <'yep_button.c'`; then
    echo shar: \"'yep_button.c'\" unpacked with wrong size!
fi
# end of 'yep_button.c'
fi
if test -f 'nope_button.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nope_button.c'\"
else
echo shar: Extracting \"'nope_button.c'\" \(628 characters\)
sed "s/^X//" >'nope_button.c' <<'END_OF_FILE'
X# include <X11/Intrinsic.h>
X# include <X11/StringDefs.h>
X# include <X11/Form.h>
X# include <stdio.h>
X
X# include "home_globs.h"
X# include "confirm_globs.h"
X
Xstatic char	nope_button_label[] = "nope";
X
XArg nope_button_args[] = {
X	{ XtNlabel,		(XtArgVal) nope_button_label }
X};
X
Xint nope_button_args_n = XtNumber(nope_button_args);
X
Xvoid
Xnope_func(w, client_data, call_data)
X	Widget		w;
X	caddr_t		client_data;
X	caddr_t		call_data;
X{
X# ifdef use_popup
X	XtPopdown(confirm_popup);
X	XtSetSensitive(quit_button, True);
X# else /* use_popup */
X	XtUnmanageChild(confirm_form);
X	XtManageChild((Widget) client_data);
X# endif /* use_popup */
X}
END_OF_FILE
if test 628 -ne `wc -c <'nope_button.c'`; then
    echo shar: \"'nope_button.c'\" unpacked with wrong size!
fi
# end of 'nope_button.c'
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 'home_globs.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'home_globs.h'\"
else
echo shar: Extracting \"'home_globs.h'\" \(211 characters\)
sed "s/^X//" >'home_globs.h' <<'END_OF_FILE'
Xextern void		quit_func();
Xextern void		help_func();
X
Xextern int		help_button_args_n;
Xextern int		quit_button_args_n;
X
Xextern Arg		help_button_args[];
Xextern Arg		quit_button_args[];
X
Xextern Widget		quit_button;
END_OF_FILE
if test 211 -ne `wc -c <'home_globs.h'`; then
    echo shar: \"'home_globs.h'\" unpacked with wrong size!
fi
# end of 'home_globs.h'
fi
if test -f 'globs.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'globs.h'\"
else
echo shar: Extracting \"'globs.h'\" \(195 characters\)
sed "s/^X//" >'globs.h' <<'END_OF_FILE'
Xextern XFontStruct	*query_font;
Xextern Boolean		debug;
Xextern String		file;
Xextern String		display_name;
X
Xextern Widget		top_setup();
Xextern Widget		home_setup();
Xextern Widget		confirm_setup();
END_OF_FILE
if test 195 -ne `wc -c <'globs.h'`; then
    echo shar: \"'globs.h'\" unpacked with wrong size!
fi
# end of 'globs.h'
fi
if test -f 'confirm_globs.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'confirm_globs.h'\"
else
echo shar: Extracting \"'confirm_globs.h'\" \(274 characters\)
sed "s/^X//" >'confirm_globs.h' <<'END_OF_FILE'
Xextern void	yep_func();
Xextern void	nope_func();
X
Xextern Arg	yep_button_args[];
Xextern Arg	nope_button_args[];
X
Xextern int	yep_button_args_n;
Xextern int	nope_button_args_n;
X
Xextern Widget	confirm_form;
X
X# ifdef use_popup
Xextern Widget	confirm_popup;
X# endif /* use_popup */
END_OF_FILE
if test 274 -ne `wc -c <'confirm_globs.h'`; then
    echo shar: \"'confirm_globs.h'\" unpacked with wrong size!
fi
# end of 'confirm_globs.h'
fi
if test -f 'xtools.xbm' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtools.xbm'\"
else
echo shar: Extracting \"'xtools.xbm'\" \(2462 characters\)
sed "s/^X//" >'xtools.xbm' <<'END_OF_FILE'
X#define xtools_width 58
X#define xtools_height 58
Xstatic char xtools_bits[] = {
X 0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0x01,0x00,0x00,
X 0x00,0x00,0x00,0xf8,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0xf8,0xff,0x07,0x00,
X 0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,
X 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x80,0xff,0xff,
X 0x1f,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x80,0xff,
X 0xff,0x1f,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x80,
X 0xff,0xff,0x1f,0x00,0x00,0x00,0x00,0x80,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,
X 0x80,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x0f,0x00,0x00,0x00,
X 0x00,0x00,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x07,0x00,0x00,
X 0x00,0x00,0x00,0xfe,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0xfc,0xff,0x01,0x00,
X 0x00,0x00,0x00,0x00,0xf8,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,
X 0x01,0x00,0x00,0xc0,0x1f,0x80,0xff,0xff,0x07,0xf0,0x00,0xf0,0x7f,0x00,0xff,
X 0xff,0x0f,0xf8,0x01,0xf8,0xff,0x81,0xff,0xff,0x1f,0xf8,0x03,0xfc,0xff,0xc1,
X 0x3f,0xfc,0x39,0xfc,0x03,0xfe,0xff,0xe7,0x0f,0xf0,0x70,0xfc,0x03,0xfe,0xff,
X 0xf7,0x03,0xc0,0x60,0xfc,0x03,0xfe,0xff,0xff,0xe3,0xc0,0x60,0xfc,0x03,0xff,
X 0xff,0xff,0x31,0x80,0xcc,0xfc,0x03,0xff,0xff,0xff,0x11,0x00,0xde,0xff,0x01,
X 0xff,0xff,0xff,0x11,0x00,0xbf,0xf8,0x01,0xff,0xff,0xff,0x10,0x1e,0x7f,0xf0,
X 0x00,0xff,0xff,0xff,0x20,0x3f,0x3d,0x40,0x00,0xff,0xff,0xff,0x00,0x7f,0x11,
X 0x80,0x00,0xff,0xff,0xff,0x00,0xbf,0x12,0x00,0x01,0xff,0xff,0xff,0x01,0x9d,
X 0x0a,0x00,0x01,0xfe,0xff,0xff,0x01,0x81,0x0c,0x00,0x01,0xfe,0xff,0xff,0x01,
X 0x81,0x0c,0x00,0x01,0xfe,0xff,0xff,0x03,0x82,0x0a,0x80,0x00,0xfc,0xff,0xfd,
X 0x07,0x44,0x01,0x80,0x00,0xf8,0xff,0xfc,0x0f,0x78,0x01,0x80,0x00,0xe0,0x7f,
X 0xfc,0x3f,0x00,0x01,0x80,0x00,0xc0,0x1f,0xfc,0xff,0x00,0x03,0x40,0x00,0x00,
X 0x00,0xfc,0xff,0x03,0x00,0x60,0x00,0x00,0x00,0xf8,0x3f,0x00,0x00,0x20,0x00,
X 0x00,0x00,0xf8,0x8f,0x03,0x00,0x30,0x00,0x00,0x00,0xf8,0xc7,0x00,0x00,0x18,
X 0x00,0x00,0x00,0xf8,0xc3,0x03,0x00,0x06,0x00,0x00,0x00,0xf0,0x43,0x0e,0xc0,
X 0x03,0x00,0x00,0x00,0xe0,0x41,0xfc,0x7f,0x02,0x00,0x00,0x00,0xe0,0x81,0xf0,
X 0x7f,0x02,0x00,0x00,0x00,0x80,0x01,0xe0,0x7f,0x02,0x00,0x00,0x00,0x80,0x01,
X 0xe0,0x3f,0x01,0x00,0x00,0x00,0x00,0x02,0xc0,0x9f,0x01,0x00,0x00,0x00,0x00,
X 0x0e,0x80,0xcf,0x00,0x00,0x00,0x00,0x00,0xf8,0x10,0x60,0x00,0x00,0x00,0x00,
X 0x00,0xc0,0x27,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x07,0x00,0x00};
END_OF_FILE
if test 2462 -ne `wc -c <'xtools.xbm'`; then
    echo shar: \"'xtools.xbm'\" unpacked with wrong size!
fi
# end of 'xtools.xbm'
fi
if test -f 'Imakefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Imakefile'\"
else
echo shar: Extracting \"'Imakefile'\" \(558 characters\)
sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
X       INCLUDES = -I$(TOP) -I$(TOP)/X11
XLOCAL_LIBRARIES = $(XAWLIB) $(XTOOLLIB) $(XLIB)
XDEFAULT_STARTUP = $(LIBDIR)/xtools_startup
X    STD_DEFINES = -DDEFAULT_STARTUP=\"$(DEFAULT_STARTUP)\" -Duse_popup
X
X	   SRCS = top_setup.c home_setup.c quit_button.c help_button.c \
X		confirm_setup.c main.c client_start.c globs.c parse.c \
X		yep_button.c nope_button.c setenv.c
X
X	   OBJS = top_setup.o home_setup.o quit_button.o help_button.o \
X		confirm_setup.o main.o client_start.o globs.o parse.o \
X		yep_button.o nope_button.o setenv.o
X
XComplexProgramTarget(xtools)
END_OF_FILE
if test 558 -ne `wc -c <'Imakefile'`; then
    echo shar: \"'Imakefile'\" unpacked with wrong size!
fi
# end of 'Imakefile'
fi
if test -f 'dot_xtools' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dot_xtools'\"
else
echo shar: Extracting \"'dot_xtools'\" \(295 characters\)
sed "s/^X//" >'dot_xtools' <<'END_OF_FILE'
Xxrdb		.xrdb
Xxsetroot	-grey
Xxhost		yuban ovaltine bosco
Xxset		m 8 8 r off c 100
Xtwm &
Xxterm		-i -name velveeta -T velveeta #0x0-85+100 &
Xxterm		-i -name cartan -T cartan #0x0-85+240 -e cartan -e  &
Xxterm		-i -C -r -name console -T console #0x0-85+380 &
Xxperfmon	=175x290-115+0 &
Xxclock &
Xxbiff &
END_OF_FILE
if test 295 -ne `wc -c <'dot_xtools'`; then
    echo shar: \"'dot_xtools'\" unpacked with wrong size!
fi
# end of 'dot_xtools'
fi
if test -f 'xtools.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xtools.man'\"
else
echo shar: Extracting \"'xtools.man'\" \(3941 characters\)
sed "s/^X//" >'xtools.man' <<'END_OF_FILE'
X.TH XTOOLS 1 
X.SH NAME
Xxtools \- easy way to start X programs
X.SH SYNOPSIS
Xxinit xtools [-display hostname:dpy] [normal Xaw options]
X.SH DESCRIPTION
X.I xtools
Xis a convenient way to start up your X applications when your system
Xdoesn't support starting up the X window system from the getty
Xprocess.
X.PP
XThe applications that
X.I xtools
Xstarts up are specified in a .xtools file.  You can have different
X.I .xtools
Xfiles, one for each host.
X.I xtools
Xfirst tries to open the file .xtools-fully.qualified.domain.name where
X``fully.qualified.domain.name'' is the fully qualified domain name of
Xyour workstation (as returned by the gethostname() system call).  If
Xthat file doesn't exist then, starting at the right, it trims off
Xportions of the domain name and retries.  Using the above example
Xdomain name, the following files would be tried in order:
X.sp
X.nf
X .xtools-fully.qualified.domain.name
X .xtools-fully.qualified.domain
X .xtools-fully.qualified
X .xtools-fully
X .xtools
X.fi
X.sp
XIf none of the .xtools files with a machine or domain name exist then
Xit uses just ``.xtools''.
X.SH CONFIGURATION FILE FORMAT
XThe format of the .xtools file is the same as if you were typing the
Xcommands to the shell.  (But note that csh-style tilde expansion is
Xnot implemented.)  In particular, it is important to note that the
Xcommand lines in the .xtools file must have an ampersand (&) at the
Xend if the command is expected to run in the background (for example,
Xxterm).  A bug in
X.I xtools
Xrequires you to put all of those commands that don't run in the
Xbackground first.  Here is a sample .xtools file
X.sp
X.nf
Xxrdb		.xrdb
Xxsetroot	-grey
Xxhost		yuban ovaltine bosco
Xxset		m 8 8 r off c 100
Xtwm &
Xxterm		-i #0x0-85+100 &
Xxterm		-i #0x0-85+240 -e cartan -e  &
Xxterm		-i -C -r #0x0-85+380 &
Xxperfmon	=175x290-115+0 &
Xxclock &
Xxbiff &
X.fi
X.sp
X.SH STARTING AND QUITING
XSince
X.I xtools
Xis started by
X.I xinit
Xthe DISPLAY environment variable isn't set, so you must either set it
Xprior to starting xinit, or you can use the -display option with
X.I xtools
Xand
X.I xtools
Xwill propogate it down to the programs that it starts.  Here's an
Xexample csh alias for starting the X Window System using
X.I xtools
Xon a SUN workstation:
X.sp
X.nf
Xalias x 'xinit xtools -iconic -geo -1-100 -display ${hostname}":"0 ; \\
Xsetkeys reset ; \\
Xclear'
X.fi
X.sp
Xwhere the hostname variable was set earlier with
X.sp
X.nf
Xset hostname = ` hostname | sed -e 's/\..*//' `
X.fi
X.PP
XSince
X.I xtools
Xwas started by
X.I xinit
Xyou must quit
X.I xtools
Xin order to quit the X Window System.
X.I xtools
Xhas a small window with two buttons labeled ``quit'' and ``help''.
XThe help button isn't implemented yet so it is dimmed.  When you click
Xon the quit button a confirmation box pops up; if you click on the
X``yep'' button then
X.I xtools
Xwill send a kill signal to all of the programs that it started.
X.SH OPTIONS
X.I xtools
Xtakes all of the standard toolkit options.  In addition, you may
Xspecifiy an alternate configuration file by using the -file option
Xfollowing it with the name of the configuration file.
X.SH "X DEFAULTS"
XThe available names and classes for the widgets used are:
X.RS
X.nf
X.ta 4i
XNAME	CLASS
X
Xtop	Shell
X
Xtop.home	Shell.Form
Xtop.home.home	Shell.Form.Label
Xtop.home.quit	Shell.Form.Command
Xtop.home.help	Shell.Form.Command
X
Xtop.confirm	Shell.Shell
Xtop.confirm.confirm	Shell.Shell.Form
Xtop.confirm.confirm.confirm	Shell.Shell.Form.Label
Xtop.confirm.confirm.yep	Shell.Shell.Form.Command
Xtop.confirm.confirm.nope	Shell.Shell.Form.Command
X.fi
X.RE
X.PP
XThese can be used to set fonts, colors, etc. tailored to the user's
Xneeds.  As a color example:
X.PP
X.RS
X.ta 4i
X.nf
Xxtools*quit.Background:				mauve
Xxtools*confirm.yep.Background:			peach
Xxtools*confirm.nope.Background:			plum
Xxtools*geometry:				-1-100
Xxtools*icon:					on
Xxtools*home.font:				vbee-36
Xxtools*confirm.font:				vbee-36
X.fi
X.RE
X.SH AUTHOR
X.ta 1.2i
XRusty C. Wright
X.br
X	rusty@cartan.berkeley.edu
X.br
X	ucbvax!cartan!rusty
END_OF_FILE
if test 3941 -ne `wc -c <'xtools.man'`; then
    echo shar: \"'xtools.man'\" unpacked with wrong size!
fi
# end of 'xtools.man'
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
echo shar: End of shell archive.
exit 0
-- 
Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330