|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T i
Length: 7785 (0x1e69)
Types: TextFile
Names: »ipc.c«
└─⟦87ddcff64⟧ Bits:30001253 CPHDIST85 Tape, 1985 Autumn Conference Copenhagen
└─⟦this⟧ »cph85dist/search/ipc.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Search/ipc.c«
#ifndef lint
static char rcsid[] = "$Header: ipc.c,v 2.2 85/08/15 17:11:09 matt Exp $";
#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.2 85/08/15 17:11:09 matt
* Adapt to 4.3 (and BRL ?)
*
* 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!
*/
#ifdef SO_DONTLINGER
if (setsockopt(newsock, SOL_SOCKET, SO_DONTLINGER, 0, 0))
errlog("error in setsockopt call\n");
#else
{
struct linger linger;
linger.l_onoff = 0; linger.l_linger = 0;
if (setsockopt(newsock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)))
errlog("error in setsockopt call\n");
}
#endif
/*
* 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;
int on = 1;
#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, &on, sizeof on) < 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;
}