DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T i

⟦91be46001⟧ TextFile

    Length: 7466 (0x1d2a)
    Types: TextFile
    Names: »ipc.c.orig«

Derivation

└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
    └─ ⟦this⟧ »cph85dist/search/ipc.c.orig« 

TextFile

#ifndef lint
static char rcsid[] = "$Header: ipc.c,v 2.1 85/04/10 17:31:13 matt Stab $";
#endif
/*
 *
 * search
 *
 * multi-player and multi-system search and destroy.
 *
 * Original by Dave Pare	1984
 * Ported & improved
 *      by Matt Crawford	1985
 *
 * routines to initialize and watch the communications sockets
 * for new players, "searchwho" and "sdata" requests.
 *
 * Copyright (c) 1984
 *
 * $Log:	ipc.c,v $
 * Revision 2.1  85/04/10  17:31:13  matt
 * Major de-linting and minor restructuring.
 * 
 * Revision 1.6  85/02/24  22:50:47  matt
 * Make the select() polls into real polls by setting the timeouts
 * to zero.  This cuts down on context switches and speeds the game
 * up IMMENSELY!
 * 
 * Revision 1.5  85/02/11  14:59:28  matt
 * Tell searchwho that game is in GUTS mode
 * 
 * Revision 1.4  85/02/09  23:48:52  matt
 * Eliminated the dependence on the value of the mask after
 * select() times out.  Use the return value to distinguish
 * a timeout!!
 * 
 * Revision 1.3  84/07/08  17:03:41  matt
 * Added Log
 * 
 * Revision 1.2  84/07/07  18:20:50  matt
 * Put new->p_speed into host byte order after reading from client
 */

#include <stdio.h>
#include <sgtty.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/file.h>
#include <sys/time.h>

#ifdef INET
#include <netinet/in.h>
#include <netdb.h>
#endif

#include "defines.h"
#include "structs.h"

#ifdef INET
struct	sockaddr_in in_addr;
#endif
struct	sockaddr loc_addr;

extern	int	dtabsiz;

/*
 * newplayer checks to see if there is a new player waiting
 * on one of the communication sockets.  If there is some input
 * waiting, newplayer() checks to see if it's a request from
 * "searchwho", or if it's an actual player requesting to
 * enter the game.
 *
 * newplayer() returns the new player, or a NULL if no new player
 * was found.
 */

t_player *newplayer(mask)
int mask;
{
	extern	void	core_dump();
	extern	char	*strcpy();
	extern	t_player	*startup();
	extern	t_player	player[NPLAYER];
	extern	int	errno,
			loc_sock,
			nobody,
			gutsflag;
#ifdef INET
	extern	int	in_sock;
#endif
	extern	struct	timeval	tim_inp;
	register	t_player	*p,	*np;
	t_file	*new;
	long	lbuf[1024];	/* Try to force alignment */
	char	*buf = (char *)lbuf;
	int	newsock,
		nfds,
		namelen,
		i;
	struct	sockaddr	muck_loc_addr;
#ifdef INET
	struct	sockaddr_in	muck_in_addr;
#endif


	tim_inp.tv_sec = tim_inp.tv_usec = 0L;
	nfds = select(dtabsiz, &mask, NULLINT, NULLINT, &tim_inp);
	if (nfds < 0 && errno != EINTR)
		errlog("select error in newplayer()\n");
	if (nfds == 0) 
		return 0;
#ifdef INET
	if (mask & 01<<loc_sock) {
		namelen = sizeof(loc_addr);
		newsock = accept(loc_sock, &muck_loc_addr, &namelen);
	} else {
		namelen = sizeof(in_addr);
		newsock = accept(in_sock, (struct sockaddr *)&muck_in_addr,
				 &namelen);
	}
#else
	namelen = sizeof(loc_addr);
	newsock = accept(loc_sock, &muck_loc_addr, &namelen);
#endif
	if (newsock < 0) {
		sprintf(buf,"accept error: %d, errno: %d\n", errno);
		errlog(buf);
		core_dump();
	}
	/*
	 * don't take forever when we close the socket!
	 */
	if (setsockopt(newsock, SOL_SOCKET, SO_DONTLINGER, 0, 0))
		errlog("error in setsockopt call\n");
	/*
	 * Sure hope the following read gives all the data in
	 * one shot.  It isn't guaranteed to, you know!
	 */
	i = read(newsock, buf, sizeof(lbuf));
	if ( i == 1 ) {	/* Special Request */
		switch ( *buf ) {
		case 'w':	/* "who's playing search?" */
			buf[0] = NULL;
			for (p=player; p < &player[NPLAYER]; p++) {
				if (p->status.alive == FALSE)
					continue;
				if (*buf == NULL)
					sprintf(buf, "%s  player   points\n",
					 gutsflag?"*game in GUTS mode*\n":"");
				sprintf(buf,"%s\n%-16s %-5d", buf,
						p->plname,p->points);
			}
			if (buf[0] == NULL) {
				(void)strcpy(buf, "nobody playing");
				nobody++;
			}
			write(newsock, buf, strlen(buf));
			errlog("searchwho request\n");
	        break;
		case '#':	/* "dump the player list" (top secret) */
			for (p=player; p < &player[NPLAYER]; p++)
				if (p->status.alive == TRUE)
					write(newsock, (char *)p,
						sizeof(t_player));
			errlog("sdata request\n");
	        break;
		default:	/* garbage! */
			write(newsock, "What?\n", 6);
			errlog("garbage request\n");
	        break;
		}
		shutdown(newsock, 2);
		close(newsock);
		return 0;
	} else if (i != sizeof(t_file)) {
		/*
		 * some sort of flaky number
		 */
		write(newsock, "You didn't send a complete packet!\n", 35);
		shutdown(newsock, 2);
		close(newsock);
		{
			char	errbuf[1024];

			sprintf(errbuf, "bad new-player read, %d bytes\n");
			errlog(errbuf);
		}
		return 0;
	}
	/*
	 * use buf as the t_file structure
	 */
	new = (t_file *)lbuf;
	new->p_speed = ntohl(new->p_speed);
	if ((np = startup(newsock, new)) == NULL) {
		errlog("startup returned NULL in newplayer()\n");
		shutdown(newsock, 2);
		close(newsock);
		return 0;
	}
	return np;
}


/*
 * initsocks initializes the two "new player" communications
 * sockets.  It returns 1 if everything is ok, and 0 if not.
 * Argument is passed in host byte order.
 */

int initsocks(port)
int port;
{
	extern	char	*rindex(),	*strcpy();
	extern	int loc_sock;
#ifdef INET
	extern	int in_sock;
	char	hostname[40];
	struct	servent *serv;
#endif
	char	buf[255];

#ifdef INET
	/*
	 * connect to the internet address for our search daemon
	 * complain if we can't connect (for whatever reason)
	 */
	in_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (in_sock < 0) {
		errlog("error creating internet socket\n");
		return 0;
	}
	if (gethostname(hostname, sizeof(hostname))) {
		errlog("error getting host name\n");
		return 0;
	}
	serv = getservbyname("search", "tcp");
	if (serv == NULL || htons((short)port) != serv->s_port) {
		sprintf(buf, "listening at port %d\n", port);
		errlog(buf);
		in_addr.sin_port = htons((short)port);
	} else
		in_addr.sin_port = serv->s_port;
	if (setsockopt(in_sock, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0)
		errlog("error in setsockopt (SO_REUSEADDR)\n");
	if (bind(in_sock, (struct sockaddr *)&in_addr, sizeof(in_addr))) {
		errlog("error binding internet port\n");
		return 0;
	}
	listen(in_sock, 5);
#endif
	/*
	 * bind and listen at the local socket "/tmp/slock"
	 */
	loc_sock = socket(AF_UNIX, SOCK_STREAM, 0);
	if (loc_sock < 0) {
		errlog("error making local socket\n");
		return 0;
	}
	(void)strcpy(loc_addr.sa_data, SLOCK);
	/*
	 * get rid of the old one.
	 */
	unlink(loc_addr.sa_data);
	if (bind(loc_sock, &loc_addr, strlen(loc_addr.sa_data)+2)) {
		errlog("error binding local socket\n");
		return 0;
	}
	chmod(loc_addr.sa_data, 0666);
	listen(loc_sock, 5);
	return 1;
}

/*
 * read input from the socket
 *
 */

int pinput(p)
register t_player *p;
{
	extern	int	errlog();
	extern	void	done();
	extern	int	errno;
	register	int	i = 0;
	int	mask;
	extern	struct	timeval	tim_inp;
	int	nfds;

	if (p->socket < 0) {
		errlog("bad socket number\n");
		done(p);
		return -1;
	}
	mask = 0;
	mask = 01 << p->socket;
	/*
	 * poll the socket for input
	 */
	tim_inp.tv_sec = tim_inp.tv_usec = 0L;
	nfds = select(dtabsiz, &mask, NULLINT, NULLINT, &tim_inp);
	if (nfds < 0 && errno != EINTR) {
		errlog("error, input select\n");
		return -1;
	}
	if (nfds > 0) {
		i = read(p->socket, p->inputq, QSIZE);
		/*
		 * socket shut down from other side
		 * clean up after the player
		 */
		if (i <= 0) {
			errlog("player died\n");
			done(p);
			return -1;
		}
		p->ninput = i;
		p->pinputq = p->inputq;
	}
	return i;
}