matt@oddjob.UUCP (Matt Crawford) (08/11/85)
: This is a shar archive. Extract with sh, not csh. echo x - main.c sed -e 's/^X//' > main.c << '!xxENDITxx!' X#ifndef lint Xstatic char rcsid[] = "$Header: main.c,v 2.2 85/08/06 22:26:37 matt Exp $"; X#endif X/* X * X * search X * X * multi-player and multi-system search and destroy. X * X * Original by Greg Ordy 1979 X * Rewrite by Sam Leffler 1981 X * Socket code by Dave Pare 1983 X * Ported & improved X * by Matt Crawford 1985 X * X * main game iteration loop X * X * Copyright (c) 1979 X * X * $Log: main.c,v $ X * Revision 2.2 85/08/06 22:26:37 matt X * Victims lose 20% of their points to their killers. X * X * Change handling of messages to provide echo of text. X * (per hastings@navajo) X * X * Revision 2.1 85/04/10 17:31:23 matt X * Major de-linting and minor restructuring. X * X * Revision 1.6 85/02/11 15:02:50 matt X * Inform new player that game is in GUTS mode X * X * Revision 1.5 85/02/11 12:46:33 matt X * fixed spelling of "bonzai" X * X * Revision 1.4 85/02/11 12:43:54 matt X * added GUTS mode X * X * Revision 1.3 85/02/10 19:18:59 matt X * Added more realistic orbiting. X * X * Revision 1.2 85/02/09 23:49:49 matt X * Eliminated the dependence on the value of the mask after X * select() times out. Use the return value to distinguish X * a timeout!! X * X */ X X#include <stdio.h> X#include <sgtty.h> X#include <sys/types.h> X#include <sys/ioctl.h> X#include <errno.h> X#include <sys/socket.h> X#include <netinet/in.h> X#include <sys/un.h> X#include <netdb.h> X#include <sys/file.h> X#include <sys/time.h> X X#include "defines.h" X#include "structs.h" X X/* X * Major data bases X */ Xt_torps torps[NTORP]; /* torpedoes data base */ Xt_sbase sbase[NBASE]; /* star bases data base */ Xt_planet planet; /* planet data base */ Xt_alien alien[NALIEN]; /* aliens data base */ Xt_burst bursts[NBURST]; /* shrapnel data base */ Xt_player player[NPLAYER]; /* players */ X Xint dtabsiz; /* descriptor table size */ Xint pfd; /* playerfile fd */ Xint loc_sock; /* local socket */ Xint errfile; /* error log file */ Xint nplayer; /* # of players currently in game */ Xint nobody; /* is anybody playing? */ X#ifdef INET Xint in_sock; /* internet socket */ X#endif X Xt_player *whoscab; /* identity of current scab */ Xint TDIST; /* max distance a torpedo can go */ Xchar xxi; Xchar yyi; Xchar ppx; /* planet x-coord */ Xchar ppy; /* planet y-coord */ Xchar dx; Xchar dy; Xlong ptime; /* search playing time counter */ X Xint NALIENS = NALIEN; Xextern int errno; X/* X * Solar flare stuff X */ Xint sfcount; /* solar flare timer */ Xint sfflag; /* solar flare in progress */ X Xint gutsflag; /* playing in guts mode */ X Xint numbnode; Xstruct plist *avl; Xt_player *wholist; Xchar visual[NPLAYER][NPLAYER];/* group visibility matrix */ Xstruct timeval tim_inp; X X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X extern t_player *newplayer(); X extern void apilot(), X autopi(), X bcast(), X bflush(), X cput(), X dock(), X done(), X enteritem(), X facts(), X fnode(), X gathermsg(), X groupm(), X home(), X init(), X initplayer(), X invisible(), X joing(), X launch(), X lookg(), X magnif(), X makeburst(), X makeflare(), X makescab(), X movealien(), X moveburst(), X nuke(), X orbit(), X orbmove(), X outgame(), X phaser(), X pmesg(), X prompt(), X pstatus(), X quitg(), X rmsg(), X seeall(), X seescab(), X sethome(), X set_delay(), X uplst(), X xploit(); X X register t_player *p; X register t_player *pl; X register t_alien *pa; X register t_burst *pb; X register t_sbase *ps; X register t_torps *pt; X t_player *np; X char x, y; X int mf; X int gutsvote; X char buf[255]; X char xx, yy, c; X int port_num = DEFAULT_IN_PORT; X int nfds; X int mask; X int save_mask; X X dtabsiz = getdtablesize(); X X#ifdef INET X if (argc > 2) { X printf("searchd: arg count error\n"); X exit(1); X } X if (argc == 2) X port_num = atoi(argv[1]); X#endif X#ifndef DEBUG X if (fork()) X exit(0); X { int s; X for (s = 0; s < dtabsiz; s++) X (void) close(s); X (void) open("/", 0); X (void) dup2(0, 1); X (void) dup2(0, 2); X s = open("/dev/tty", 2); X if (s >= 0) { X (void)ioctl(s, TIOCNOTTY, NULLCH); X (void)close(s); X } X } X#endif X /* X * set up data bases X */ X init(); X /* X * set up sockets: port number doesn't matter X * if INET isn't defined X */ X if (!initsocks(port_num)) X exit(1); X /* X * block indefinitely until the first player enters the game X * then start the player loop X */ X save_mask = 0; X#ifdef INET X save_mask = 01<<loc_sock | 01<<in_sock; X#else X save_mask = 01<<loc_sock; X#endif X nobody = 1; X /* X * Main loop -- works in a hard run polling the input socket X * of each player. Each turn around the loop defines a time X * unit in search. X */ X for (;;) { X ptime++; /* time marches on ... */ X if (--sfcount == 0) { /* ring a ding, time for a flare */ X makeflare(); X NALIENS = NALIEN-nplayer; X } X /* X * if nobody's playing, wait until someone generates X * some sort of request X */ X if (nobody || !nplayer) { X gutsflag = FALSE; X tim_inp.tv_usec = 0L; X tim_inp.tv_sec = 3600L; X do { X mask = save_mask; X nfds = select(dtabsiz, &mask, NULLINT, NULLINT, &tim_inp); X } while (nfds == 0); X tim_inp.tv_sec = 0L; X nobody = 0; X } X if ((ptime % 16) == 0) { X np = newplayer(save_mask); X if (np != NULL) { X nplayer++; X initplayer(np); X sprintf(buf, "new player %s\n", np->plname); X errlog(buf); X for (p = player; p < &player[NPLAYER]; p++) X if (p->status.alive == TRUE && p != np) X pmesg(p, "From scanners-- NEW PLAYER"); X if (gutsflag) X pmesg(np, "This game is in GUTS mode"); X } X } else X set_delay(); X /* X * Command scanning loop... X */ X nobody = 0; X gutsvote = !gutsflag; X for (p = player; p < &player[NPLAYER]; p++) { X if (p->status.alive == FALSE) { X nobody++; X continue; X } X gutsvote = gutsflag ? gutsvote || p->status.guts X : gutsvote && p->status.guts; X if (p->status.ap == TRUE) /* update autopilot */ X apilot(p); X if (p->status.orb == TRUE) /* update orbiting */ X orbmove(p); X x = p->offx; X y = p->offy; X if (!p->ninput) X if (pinput(p) < 0) X continue; X if (p->ninput <= 0) X goto constvel; X c = (*p->pinputq++)&0177; X p->ninput--; X /* X * Two letter commands (e.g. launch torpedo) are X * marked as a command pending, so that when the X * second char comes in it can be processed entirely. X */ X if (p->cmdpend > 0) { X switch (p->cmd) { X case 'h': X home(p, c); X break; X case '5': X case 't': X p->status.ap = FALSE; X launch((thing *)p, c, PLAYER, x, y, X 1, p->curx, p->cury, 0); X break; X case 'g': X groupm(p, c); X break; X case 'q': X quitg(p, c); X break; X case 'n': X nuke(p, c); X break; X case 'j': X joing(p, c); X break; X case 's': X sethome(p, c); X break; X case 'b': X bcast(p, c); X break; X case 'a': X autopi(p, c); X break; X case 'r': X rmsg(p, c); X break; X case 'm': X magnif(p, c); X break; X case 'Q': X if (c != 'Y' && c != 'y') { X p->cmd = p->cmdpend = 0; X prompt(p, ""); X goto constvel; X } X done(p); X break; X } X goto constvel; X } X switch (c) { X case 'e': X if (p->energy != p->preve) { X cput(EGYDATA, p, "%d", p->energy); X p->preve = p->energy; X } X break; X case 'p': X if (p->points != p->prevp) { X cput(PTDATA, p, "%d", p->points); X p->prevp = p->points; X } X break; X case 'f': X facts(p); X break; X case 'l': X lookg(p); X break; X case 'x': X xploit(p); X break; X case '0': X if (p->whocent == 0) X break; X if (isalien(p->whocent)) { X pa = (t_alien *)p->whocent; X /* X * Register a hit on an alien X */ X pa->hit++; X if (pa->hit > 25) X pa->stats = DEAD; X pa->cix = -1; X pa->ciy = (rand()%3)-1; X p->points = p->points+4; X write(p->socket, "\007", 1); X } X break; X case 'i': X invisible(p); X break; X case 'c': X cput(TMDATA, p, "%d", (int)ptime); X break; X case 'o': X orbit(p); X x = p->offx; X y = p->offy; X break; X case 'z': X seescab(p); X break; X case 'd': X dock(p); X break; X case 'v': X cput(VLDATA, p, "%d %d", p->offx, p->offy); X break; X case 'G': X p->status.guts = TRUE; X break; X case 'W': X p->status.guts = FALSE; X break; X case '\014': /* ^L */ X case '@': X fnode(p->plstp); X initplayer(p); X break; X case 'Q': X prompt(p, "Really quit?"); X goto savecmd; X case 'q': X case 'j': X prompt(p, "enter group members"); X goto savecmd; X case 'b': X case 'g': X gathermsg(p); X /*FALL THRU*/ X case 'r': X case 'h': X case 't': X case 'a': X case 'm': X case 's': X case 'n': X case '5': X savecmd: X p->cmdpend++; X p->cmd = c; X break; X default: X goto vel; X } X goto constvel; X vel: X /* X * Velocity changes handled here... X */ X p->status.ap = p->status.orb = FALSE; X switch (c) { X case NO: X y--; X break; X case NE: X x++; X y--; X break; X case EA: X x++; X break; X case SE: X x++; X y++; X break; X case SO: X y++; X break; X case SW: X x--; X y++; X break; X case WE: X x--; X break; X case NW: X x--; X y--; X break; X default: X goto constvel; X } X p->offx = x; X p->offy = y; X cput(VLDATA, p, "%d %d", p->offx, p->offy); X constvel: X /* X * Update energy total for player: X * standing still adds one unit/iteration X * magnification costs energy proportional to M-factor X * velocity > 1 in any direction costs one unit/iter X * invisibility costs INCOST/iteration X */ X p->curx = p->curx+x; X p->cury = p->cury+y; X if ((x > 1 || x < -1) || (y > 1 || y < -1)) X p->energy--; X if (x == 0 && y == 0) X p->energy++; X if (p->mflg > 1) X p->energy -= p->mflg; X if (p->status.invis == TRUE) X p->energy = p->energy-INCOST; X if (p->energy > p->maxe) X p->energy = p->maxe; X if (p->energy <= 0) X outgame(p); X if (p->status.crash == TRUE) { X pstatus(p, "Crash into planet--all is lost!!"); X if (p->points >= 50) X p->points -= 50; X p->status.killed = TRUE; X done(p); X } X /* X * Update energy display only every 16 iterations -- X * otherwise, it would be constantly updated at X * great expense X */ X if (p->energy != p->preve && (ptime&017) == 0) { X cput(EGYDATA, p, "%d", p->energy); X p->preve = p->energy; X } X if (p->points != p->prevp) { X cput(PTDATA, p, "%d", p->points); X p->prevp = p->points; X } X } X if (nobody < NPLAYER) X nobody = 0; X if (gutsvote && !gutsflag) X seeall("\07Entering GUTS mode-- beware!"); X else if (gutsflag && !gutsvote) X for (p = player; p < &player[NPLAYER]; p++) X if (p->status.alive == TRUE) X pmesg(p, "Entering WIMP mode"); X gutsflag = gutsvote; X moveburst(); X /* X * Update the state of the aliens... X */ X for (pa = alien; pa < &alien[NALIEN]; pa++) { X if (pa->stats == DEAD) X continue; X if (pa->type == WANDER) { X pa->count--; X /* time to change direction */ X if (pa->count == 0) { X pa->cix = (rand()%3)-1; X pa->ciy = (rand()%3)-1; X pa->count = (rand()%50)+30; X } X } X /* shankers "dance" */ X if (pa->type == SHANK && pa->aname == NAMESH) X movealien(pa); X else { X pa->cx = pa->cx + pa->cix; X pa->cy = pa->cy + pa->ciy; X } X } X /* X * Update motion of torpedoes X */ X for (pt = torps; pt < &torps[NTORP]; pt++) { X if (pt->owner == 0) X continue; X pt->torx += pt->xinc; X pt->tory += pt->yinc; X pt->tcount--; X /* X * Check for alien hits X */ X for (pa = alien; pa < &alien[NALIEN]; pa++) { X if (pa->stats == DEAD) X continue; X if (pa->cx == pt->torx && pa->cy == pt->tory) { X /* shot by a shanker */ X if(isalien(pt->owner)) X continue; X pa->hit++; X if (pa->hit > 25) { X makeburst(pa->cx, pa->cy); X pa->stats = DEAD; X } X pl = (t_player *)pt->owner; X /* 6 points for any hit on an alien */ X pl->points += 6; X pl->ahits++; X /* X-aliens are worth 20 points */ X if (pa->type == WANDER) X pl->points += 20; X /* X * move off in a random direction X * after a hit X */ X pa->cix = (rand()%3)-1; X pa->ciy = (rand()%3)-1; X if (pa->cix == 0 && pa->ciy == 0) X pa->cix = pa->ciy = 1; X /* X * Hit a shanker -- they fight back X */ X if (pa->type == SHANK) { X pa->aname = NAMESH; X pa->whotoget = pt->owner; X pl->points += 20; X pa->count = 0; X pmesg(pl, "From a shanker-- bonzai!"); X } X pstatus(pl, "\007Torpedo hit on alien!"); X pt->owner = 0; X } X } X if (pt->tcount == 0) X pt->owner = 0; X } X /* X * Main screen update loop... X */ X for (p = player; p < &player[NPLAYER]; p++) { X if (p->status.alive == FALSE) X continue; X wholist = p; X x = p->curx; X y = p->cury; X mf = p->mflg; X p->whocent = 0; X dx = x-ppx; X dy = y-ppy; X /* X * Display any portion of Quartone visible X */ X if (dx > -18 && dx < 18 && dy > -10 && dy < 10) { X register int pp; X X for (pp = 0; pp != 17; pp++) { X dx = planet.places[pp][0]; X dy = planet.places[pp][1]; X if (!onscreen (dx, dy, x, y)) X continue; X if (dx == x && dy == y) X p->status.crash = TRUE; X xx = (dx-x)/mf+XWIND; X yy = (dy-y)/mf+YWIND; X enteritem(xx, yy, NAMEP); X } X } X /* X * Shrapnel around? X */ X for (pb = bursts; pb < &bursts[NBURST]; pb++) { X if (pb->cbactive == 0) X continue; X dx = x-pb->cbx; X dy = y-pb->cby; X if (dx > -21 && dx < 21 && dy > -13 && dy < 13) { X register int is; X X for (is = 0; is != 9; is++) { X dx = pb->shrap[is][0]; X dy = pb->shrap[is][1]; X if (dx == 0 && dy == 0) X continue; X if (!onscreen (dx, dy, x, y)) X continue; X /* a piece hit -- mark it */ X if (dx == x && dy == y) X p->status.bur = TRUE; X xx = (dx-x)/mf+XWIND; X yy = (dy-y)/mf+YWIND; X enteritem(xx, yy, '.'); X } X } X } X /* X * Any star bases visible? X */ X for (ps = sbase; ps < &sbase[NBASE]; ps++) { X if (!onscreen (ps->xpos, ps->ypos, x, y)) X continue; X if (ps->xpos == x && ps->ypos == y) X p->whocent = (thing *)ps; X xx = (ps->xpos-x)/mf+XWIND; X yy = (ps->ypos-y)/mf+YWIND; X enteritem(xx, yy, '*'); X } X /* X * Show other players -- take care of groups X */ X for (pl = player; pl < &player[NPLAYER]; pl++) { X register int shift; X X if (pl == p) X continue; X if (pl->status.alive == FALSE) X continue; X if (!onscreen (pl->curx, pl->cury, x, y)) X continue; X if (pl->status.invis == TRUE) { X if (!visual[pl-player][p-player]) X continue; X shift = 'a'-'A'; X } else X shift = 0; X if (pl->curx == x && pl->cury == y) { X p->whocent = (thing *)pl; X pl->whocent = (thing *)p; X } X xx = (pl->curx-x)/mf+XWIND; X yy = (pl->cury-y)/mf+YWIND; X c = (pl-player)+'A'+shift; X enteritem(xx, yy, c); X } X /* X * Show visible aliens... X */ X for (pa = alien; pa < &alien[NALIEN]; pa++) { X if (pa->stats == DEAD) X continue; X if (!onscreen (pa->cx, pa->cy, x, y)) X continue; X if (pa->cx == x && pa->cy == y) X p->whocent = (thing *)pa; X xx = (pa->cx-x)/mf+XWIND; X yy = (pa->cy-y)/mf+YWIND; X enteritem(xx, yy, pa->aname); X if (pa->type == SHANK && (t_player *)(pa->whotoget) == p) X pa->onscr = ON; X } X /* X * Track torpedoes... X */ X for (pt = torps; pt < &torps[NTORP]; pt++) { X if (pt->owner == 0) X continue; X if (!onscreen (pt->torx, pt->tory, x, y)) X continue; X if (pt->torx == x && pt->tory == y) X p->whocent = (thing *)pt; X xx = (pt->torx-x)/mf+XWIND; X yy = (pt->tory-y)/mf+YWIND; X enteritem(xx, yy, '+'); X } X /* X * Update the display -- attempts minimal changes X */ X uplst(); X if (p->offx != 0) X cput(POS1DATA, p, "%d", p->curx); X if (p->offy != 0) X cput(POS2DATA, p, "%d", p->cury); X if (p->status.bur == TRUE) { /* shrapnel damage */ X pmesg(p, "From damage control-- Shrapnel!!"); X cput(INDATA, p, "off"); X p->status.bur = FALSE; X p->status.invis = FALSE; X p->energy -= SHRAPCOST; X if (p->energy < 0) X p->energy = 0; X p->maxe -= SHRAPCOST; X } X /* X * Check for damage X */ X if (isalien(p->whocent) && ((t_alien *)p->whocent)->type == WANDER) { X /* X * X-alien collision X */ X p->maxe = p->maxe-15; X if (p->energy > p->maxe) X p->energy = p->maxe; X pmesg(p, "From engine room-- Collision!!"); X } X /* X * Torpedo hit, and not in orbit X */ X if (istorp(p->whocent) && X (gutsflag || p->status.orb == FALSE)) { X pt = (t_torps *)p->whocent; X /* X * If it's a shanker, let it get back to X * wandering -- it's done its job X */ X if (isalien(pt->owner)) { X phaser((t_alien *)pt->owner, p); X pt->owner = 0; X continue; X } X /* X * Torpedo hit by a player X */ X pl = (t_player *)pt->owner; X if (pl == p) { X pt->owner = 0; X pmesg(p, "From damage control-- SELF HIT!!!"); X p->points -= 75; X if (p->points < 0) X p->points = 0; X continue; X } X pt->owner = 0; X pstatus(pl, "\007Hit on %c", (p-player)+'A'); X pstatus(p, "\007Torpedo damage suffered!"); X pl->points += 50; X pl->phits++; X p->maxe -= 50; X if (p->energy > p->maxe) X p->energy = p->maxe; X if (p->maxe <= 0) { X int booty = p->points / 5; X pmesg(p, "From damage control-- FATAL HIT!"); X pmesg(pl, "From navigation-- TOTAL DESTRUCTION!"); X pl->points += 5 + booty; X pl->pkills++; X p->points -= booty; X /* X * Time for a new scab?? X */ X if ((pl->pkills%4) == 0) X makescab(pl); X makeburst(p->curx, p->cury); X p->status.killed = TRUE; X done(p); X } X } X } X /* X * trying to minimize the number of writes to the sockets. X */ X for (p = player; p < &player[NPLAYER]; p++) { X if (p->status.alive == TRUE) X bflush(p); X } X } X} !xxENDITxx! echo x - ipc.c sed -e 's/^X//' > ipc.c << '!xxENDITxx!' X#ifndef lint Xstatic char rcsid[] = "$Header: ipc.c,v 2.1 85/04/10 17:31:13 matt Stab $"; X#endif X/* X * X * search X * X * multi-player and multi-system search and destroy. X * X * Original by Dave Pare 1984 X * Ported & improved X * by Matt Crawford 1985 X * X * routines to initialize and watch the communications sockets X * for new players, "searchwho" and "sdata" requests. X * X * Copyright (c) 1984 X * X * $Log: ipc.c,v $ X * Revision 2.1 85/04/10 17:31:13 matt X * Major de-linting and minor restructuring. X * X * Revision 1.6 85/02/24 22:50:47 matt X * Make the select() polls into real polls by setting the timeouts X * to zero. This cuts down on context switches and speeds the game X * up IMMENSELY! X * X * Revision 1.5 85/02/11 14:59:28 matt X * Tell searchwho that game is in GUTS mode X * X * Revision 1.4 85/02/09 23:48:52 matt X * Eliminated the dependence on the value of the mask after X * select() times out. Use the return value to distinguish X * a timeout!! X * X * Revision 1.3 84/07/08 17:03:41 matt X * Added Log X * X * Revision 1.2 84/07/07 18:20:50 matt X * Put new->p_speed into host byte order after reading from client X */ X X#include <stdio.h> X#include <sgtty.h> X#include <sys/types.h> X#include <sys/ioctl.h> X#include <errno.h> X#include <sys/socket.h> X#include <sys/un.h> X#include <sys/file.h> X#include <sys/time.h> X X#ifdef INET X#include <netinet/in.h> X#include <netdb.h> X#endif X X#include "defines.h" X#include "structs.h" X X#ifdef INET Xstruct sockaddr_in in_addr; X#endif Xstruct sockaddr loc_addr; X Xextern int dtabsiz; X X/* X * newplayer checks to see if there is a new player waiting X * on one of the communication sockets. If there is some input X * waiting, newplayer() checks to see if it's a request from X * "searchwho", or if it's an actual player requesting to X * enter the game. X * X * newplayer() returns the new player, or a NULL if no new player X * was found. X */ X Xt_player *newplayer(mask) Xint mask; X{ X extern void core_dump(); X extern char *strcpy(); X extern t_player *startup(); X extern t_player player[NPLAYER]; X extern int errno, X loc_sock, X nobody, X gutsflag; X#ifdef INET X extern int in_sock; X#endif X extern struct timeval tim_inp; X register t_player *p, *np; X t_file *new; X long lbuf[1024]; /* Try to force alignment */ X char *buf = (char *)lbuf; X int newsock, X nfds, X namelen, X i; X struct sockaddr muck_loc_addr; X#ifdef INET X struct sockaddr_in muck_in_addr; X#endif X X X tim_inp.tv_sec = tim_inp.tv_usec = 0L; X nfds = select(dtabsiz, &mask, NULLINT, NULLINT, &tim_inp); X if (nfds < 0 && errno != EINTR) X errlog("select error in newplayer()\n"); X if (nfds == 0) X return 0; X#ifdef INET X if (mask & 01<<loc_sock) { X namelen = sizeof(loc_addr); X newsock = accept(loc_sock, &muck_loc_addr, &namelen); X } else { X namelen = sizeof(in_addr); X newsock = accept(in_sock, (struct sockaddr *)&muck_in_addr, X &namelen); X } X#else X namelen = sizeof(loc_addr); X newsock = accept(loc_sock, &muck_loc_addr, &namelen); X#endif X if (newsock < 0) { X sprintf(buf,"accept error: %d, errno: %d\n", errno); X errlog(buf); X core_dump(); X } X /* X * don't take forever when we close the socket! X */ X if (setsockopt(newsock, SOL_SOCKET, SO_DONTLINGER, 0, 0)) X errlog("error in setsockopt call\n"); X /* X * Sure hope the following read gives all the data in X * one shot. It isn't guaranteed to, you know! X */ X i = read(newsock, buf, sizeof(lbuf)); X if ( i == 1 ) { /* Special Request */ X switch ( *buf ) { X case 'w': /* "who's playing search?" */ X buf[0] = NULL; X for (p=player; p < &player[NPLAYER]; p++) { X if (p->status.alive == FALSE) X continue; X if (*buf == NULL) X sprintf(buf, "%s player points\n", X gutsflag?"*game in GUTS mode*\n":""); X sprintf(buf,"%s\n%-16s %-5d", buf, X p->plname,p->points); X } X if (buf[0] == NULL) { X (void)strcpy(buf, "nobody playing"); X nobody++; X } X write(newsock, buf, strlen(buf)); X errlog("searchwho request\n"); X break; X case '#': /* "dump the player list" (top secret) */ X for (p=player; p < &player[NPLAYER]; p++) X if (p->status.alive == TRUE) X write(newsock, (char *)p, X sizeof(t_player)); X errlog("sdata request\n"); X break; X default: /* garbage! */ X write(newsock, "What?\n", 6); X errlog("garbage request\n"); X break; X } X shutdown(newsock, 2); X close(newsock); X return 0; X } else if (i != sizeof(t_file)) { X /* X * some sort of flaky number X */ X write(newsock, "You didn't send a complete packet!\n", 35); X shutdown(newsock, 2); X close(newsock); X { X char errbuf[1024]; X X sprintf(errbuf, "bad new-player read, %d bytes\n"); X errlog(errbuf); X } X return 0; X } X /* X * use buf as the t_file structure X */ X new = (t_file *)lbuf; X new->p_speed = ntohl(new->p_speed); X if ((np = startup(newsock, new)) == NULL) { X errlog("startup returned NULL in newplayer()\n"); X shutdown(newsock, 2); X close(newsock); X return 0; X } X return np; X} X X X/* X * initsocks initializes the two "new player" communications X * sockets. It returns 1 if everything is ok, and 0 if not. X * Argument is passed in host byte order. X */ X Xint initsocks(port) Xint port; X{ X extern char *rindex(), *strcpy(); X extern int loc_sock; X#ifdef INET X extern int in_sock; X char hostname[40]; X struct servent *serv; X#endif X char buf[255]; X X#ifdef INET X /* X * connect to the internet address for our search daemon X * complain if we can't connect (for whatever reason) X */ X in_sock = socket(AF_INET, SOCK_STREAM, 0); X if (in_sock < 0) { X errlog("error creating internet socket\n"); X return 0; X } X if (gethostname(hostname, sizeof(hostname))) { X errlog("error getting host name\n"); X return 0; X } X serv = getservbyname("search", "tcp"); X if (serv == NULL || htons((short)port) != serv->s_port) { X sprintf(buf, "listening at port %d\n", port); X errlog(buf); X in_addr.sin_port = htons((short)port); X } else X in_addr.sin_port = serv->s_port; X if (setsockopt(in_sock, SOL_SOCKET, SO_REUSEADDR, 0, 0) < 0) X errlog("error in setsockopt (SO_REUSEADDR)\n"); X if (bind(in_sock, (struct sockaddr *)&in_addr, sizeof(in_addr))) { X errlog("error binding internet port\n"); X return 0; X } X listen(in_sock, 5); X#endif X /* X * bind and listen at the local socket "/tmp/slock" X */ X loc_sock = socket(AF_UNIX, SOCK_STREAM, 0); X if (loc_sock < 0) { X errlog("error making local socket\n"); X return 0; X } X (void)strcpy(loc_addr.sa_data, SLOCK); X /* X * get rid of the old one. X */ X unlink(loc_addr.sa_data); X if (bind(loc_sock, &loc_addr, strlen(loc_addr.sa_data)+2)) { X errlog("error binding local socket\n"); X return 0; X } X chmod(loc_addr.sa_data, 0666); X listen(loc_sock, 5); X return 1; X} X X/* X * read input from the socket X * X */ X Xint pinput(p) Xregister t_player *p; X{ X extern int errlog(); X extern void done(); X extern int errno; X register int i = 0; X int mask; X extern struct timeval tim_inp; X int nfds; X X if (p->socket < 0) { X errlog("bad socket number\n"); X done(p); X return -1; X } X mask = 0; X mask = 01 << p->socket; X /* X * poll the socket for input X */ X tim_inp.tv_sec = tim_inp.tv_usec = 0L; X nfds = select(dtabsiz, &mask, NULLINT, NULLINT, &tim_inp); X if (nfds < 0 && errno != EINTR) { X errlog("error, input select\n"); X return -1; X } X if (nfds > 0) { X i = read(p->socket, p->inputq, QSIZE); X /* X * socket shut down from other side X * clean up after the player X */ X if (i <= 0) { X errlog("player died\n"); X done(p); X return -1; X } X p->ninput = i; X p->pinputq = p->inputq; X } X return i; X} !xxENDITxx!