|
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 - 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«
#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; }