File:  [Research Unix] / researchv9 / X11 / src / X.V11R1 / clients / xinit / xinit.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:22:00 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#ifndef lint
static char *rcsid_xinit_c = "$Header: /var/lib/cvsd/repos/research/researchv9/X11/src/X.V11R1/clients/xinit/xinit.c,v 1.1.1.1 2018/04/24 17:22:00 root Exp $";
#endif	lint
#include <X11/copyright.h>

/* Copyright    Massachusetts Institute of Technology    1986	*/

#include <X11/Xlib.h>
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <sys/time.h>		/* unused but resource.h needs it */
#include <sys/resource.h>
#include <sys/wait.h>
#include <errno.h>

#define	TRUE		1
#define	FALSE		0
#define	OK_EXIT		0
#define	ERR_EXIT	1
#define DEFAULT_SERVER "X"
#define DEFAULT_DISPLAY ":0"
char *default_client[] = {
	"xterm", "=+1+1", "-n", "login",
#ifdef sun
	"-C",
#endif
	"unix:0", NULL};
char *server[100];
char *client[100];
char *displayNum;
char *program;
Display *xd;			/* server connection */
union wait	status;
int serverpid = -1;
int clientpid = -1;
extern int	errno;

sigCatch(sig)
	int	sig;
{
	signal(SIGQUIT, SIG_IGN);
	signal(SIGINT, SIG_IGN);
	Error("signal %d\n", sig);
	shutdown(serverpid, clientpid);
	exit(1);
}

main(argc, argv)
int argc;
register char **argv;
{
	register char **sptr = server;
	register char **cptr = client;
	register char **ptr;
	int pid, i;

	program = *argv++;
	argc--;

	/*
	 * copy the client args.
	 */
	if (argc == 0 || (**argv != '/' && !isalpha(**argv)))
		for (ptr = default_client; *ptr; )
			*cptr++ = *ptr++;
	while (argc && strcmp(*argv, "--")) {
		*cptr++ = *argv++;
		argc--;
	}
	*cptr = NULL;
	if (argc) {
		argv++;
		argc--;
	}

	/*
	 * Copy the server args.
	 */
	if (argc == 0 || (**argv != '/' && !isalpha(**argv))) {
		*sptr++ = DEFAULT_SERVER;
	} else {
		*sptr++ = *argv++;
		argc--;
	}
	if (argc > 0 && (argv[0][0] == ':' && isdigit(argv[0][1])))
		displayNum = *argv;
	else
		displayNum = *sptr++ = DEFAULT_DISPLAY;
	while (--argc >= 0)
		*sptr++ = *argv++;
	*sptr = NULL;

	/*
	 * Start the server and client.
	 */
	signal(SIGQUIT, sigCatch);
	signal(SIGINT, sigCatch);
	if ((serverpid = startServer(server)) > 0
	 && (clientpid = startClient(client)) > 0) {
		pid = -1;
		while (pid != clientpid && pid != serverpid)
			pid = wait(NULL);
	}
	signal(SIGQUIT, SIG_IGN);
	signal(SIGINT, SIG_IGN);

	shutdown(serverpid, clientpid);

	if (serverpid < 0 || clientpid < 0)
		exit(ERR_EXIT);
	exit(OK_EXIT);
}


/*
 *	waitforserver - wait for X server to start up
 */

waitforserver(serverpid)
	int	serverpid;
{
	int	ncycles	 = 120;		/* # of cycles to wait */
	int	cycles;			/* Wait cycle count */
	char	display[100];		/* Display name */

	strcpy(display, "unix");
	strcat(display, displayNum);
	for (cycles = 0; cycles < ncycles; cycles++) {
		if (xd = XOpenDisplay(display)) {
			return(TRUE);
		}
		else {
			if (!processTimeout(serverpid, 1, "server to start"))
				return(FALSE);
		}
	}

	return(FALSE);
}

/*
 * return TRUE if we timeout waiting for pid to exit, FALSE otherwise.
 */
processTimeout(pid, timeout, string)
	int	pid, timeout;
	char	*string;
{
	int	i = 0, pidfound = -1;
	static char	*laststring;

	for (;;) {
		if ((pidfound = wait3(&status, WNOHANG, NULL)) == pid)
			break;
		if (timeout) {
			if (i == 0 && string != laststring)
				fprintf(stderr, "\nwaiting for %s ", string);
			else
				fprintf(stderr, ".", string);
			fflush(stderr);
		}
		if (timeout)
			sleep (1);
		if (++i > timeout)
			break;
	}
	laststring = string;
	return( pid != pidfound );
}

Error(fmt, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
	char	*fmt;
{
	extern char	*sys_errlist[];

	fprintf(stderr, "%s: ", program);
	if (errno)
		fprintf(stderr, "%s: ", sys_errlist[ errno ]);
	fprintf(stderr, fmt, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
}

Fatal(fmt, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
	char	*fmt;
{
	Error(fmt, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
	exit(ERR_EXIT);
}

startServer(server)
	char *server[];
{
	int	serverpid;

	serverpid = vfork();
	switch(serverpid) {
	case 0:
		close(0);
		close(1);

		/*
		 * prevent server from getting sighup from vhangup()
		 * if client is xterm -L
		 */
		setpgrp(0,0);

		execvp(server[0], server);
		Fatal("Server \"%s\" died on startup\n", server[0]);
		break;
	case -1:
		break;
	default:
		/*
		 * don't nice server
		 */
		setpriority( PRIO_PROCESS, serverpid, -1 );

		errno = 0;
		if (! processTimeout(serverpid, 0, "")) {
			serverpid = -1;
			break;
		}
		/*
		 * kludge to avoid race with TCP, giving server time to
		 * set his socket options before we try to open it
		 */
		sleep(5);

		if (waitforserver(serverpid) == 0) {
			Error("Can't connect to server\n");
			shutdown(serverpid, -1);
			serverpid = -1;
		}
		break;
	}

	return(serverpid);
}

startClient(client)
	char *client[];
{
	int	clientpid;

	if ((clientpid = vfork()) == 0) {
		setreuid(-1, -1);
		setpgrp(0, getpid());
		execvp(client[0], client);
		Fatal("Client \"%s\" died on startup\n", client[0]);
	}
	return (clientpid);
}

shutdown(serverpid, clientpid)
	int	serverpid, clientpid;
{
	/* have kept display opened, so close it now */
	if (clientpid > 0) {
		XCloseDisplay(xd);

		/* HUP all local clients to allow them to clean up */
		errno = 0;
		if (killpg(clientpid, SIGHUP) != 0)
			Error("can't killpg(%d, SIGHUP) for client\n",
				clientpid);
	}

	if (serverpid < 0)
		return;
	errno = 0;
	if (kill(serverpid, SIGTERM) < 0) {
		if (errno == EPERM)
			Fatal("Can't kill server\n");
		if (errno == ESRCH)
			return;
	}
	if (! processTimeout(serverpid, 10, "server to terminate"))
		return;

	fprintf(stderr, "timeout... send SIGKILL");
	fflush(stderr);
	errno = 0;
	if (kill(serverpid, SIGKILL) < 0) {
		if (errno == ESRCH)
			return;
	}
	if (processTimeout(serverpid, 3, "server to die"))
		Fatal("Can't kill server\n");
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.