billr@saab.CNA.TEK.COM (Bill Randle) (11/22/90)
Submitted-by: Tom Boutell <boutell@freezer.it.udel.edu>
Posting-number: Volume 11, Issue 76
Archive-name: bt/Part02
Environment: INET sockets, curses
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 2 (of 2)."
# Contents: Makefile interface.c types.h
# Wrapped by billr@saab on Wed Nov 21 12:13:26 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(306 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
Xbtclient: client.o pack.o
X cc client.o pack.o -o btclient -ltermcap -lcurses -ltermlib
X
Xbtserver: bt.o pack.o interface.o
X cc bt.o pack.o interface.o -o btserver
X
Xclient.o: client.c
X cc -c -g client.c
Xpack.o: pack.c
X cc -c -g pack.c
Xinterface.o: interface.c
X cc -c -g interface.c
Xbt.o: bt.c
X cc -c -g bt.c
END_OF_FILE
if test 306 -ne `wc -c <'Makefile'`; then
echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'interface.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'interface.c'\"
else
echo shar: Extracting \"'interface.c'\" \(8905 characters\)
sed "s/^X//" >'interface.c' <<'END_OF_FILE'
X
X/* interface.c: Socket communications support& medium- level message
X * passing functions. Copyright (C) 1990 Tom Boutell on original portions.
X * All low- level socket code drawn with appreciation from:
X * SOCK.C
X * Copyright (C)1989 Dr Evil Laboratories
X * This code written by Ray Moody, Roy Riggs, Mitch Adler,
X * Bill Burdick, and Steven Grady
X * No one makes any guarantees about anything. This file maybe
X * freely distributed and modified as long as this header remains intact.
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <string.h>
X#include <ctype.h>
X#include <signal.h>
X#include <netdb.h>
X#include <varargs.h>
X
X#include "types.h"
X#include "pack.h"
X#include "bt.h"
X#include "interface.h"
X
X#define DEBUG
X#undef DEBUG
X#ifdef DEBUG
X#define debug printf
X#else
X#define debug 0+
X#define perror 0+
X#endif
X
X#define SECONDSLIMIT 0L
X#define MICROSECONDSLIMIT 1L
X
X#define LINE_LEN 1024
X#define LOST_CARRIER_MSG "F"
X
X#define NONE (fd_set *) NULL
X#define NEVER (struct timeval *) NULL
X#define IGNORE (struct sockaddr *) NULL
X
Xfd_set active;
Xstruct sockaddr_in sc_in;
Xint s;
Xchar cur_input[LINE_LEN];
Xchar *curhostname = "";
Xint playerids[20];
Xchar outputline[256];
Xvoid setupinterface() {
X int current;
X init_socket(2727);
X playertext=(outputline+1);
X for (current=1; (current<=totalplayers); current++) {
X playerids[current]=new_player(0);
X players[current].live=1;
X printf("Player %d has joined.\n",current);
X outputline[0]=_YOUARE;
X outputline[1]=64+current;
X outputline[2]=0;
X w_p(playerids[current],outputline,strlen(&outputline[0])+1);
X }
X}
X
Xvoid tellplayer(player)
X int player;
X{
X outputline[0]=_TEXT;
X w_p(playerids[player],outputline,strlen(&outputline[0])+1);
X}
X
Xvoid broadcast(messagetype,details)
X char messagetype;
X void* details;
X{
X location where;
X int thisplayer;
X int current;
X outputline[0]=messagetype;
X switch (messagetype) {
X
X case _HEXSTATUS:
X where=*(location*)details;
X outputline[1]=64+where.x;
X outputline[2]=64+where.y;
X outputline[3]=64+map[where.x][where.y].terrain;
X packint(4,map[where.x][where.y].population);
X packint(7,map[where.x][where.y].lastuse);
X packint(10,map[where.x][where.y].troops);
X outputline[13]=map[where.x][where.y].owner+64;
X outputline[14]=NULL;
X break;
X case _PLAYERSTATUS:
X thisplayer=*(int*)details;
X outputline[1]=thisplayer+64;
X packint(2,players[thisplayer].action);
X packint(5,players[thisplayer].hexes);
X packint(8,players[thisplayer].troops);
X packint(11,players[thisplayer].population);
X packint(14,players[thisplayer].citadels);
X outputline[17]=players[thisplayer].start.x+64;
X outputline[18]=players[thisplayer].start.y+64;
X outputline[19]=NULL;
X break;
X case _PLAYERDEAD:
X thisplayer=*(int*)details;
X outputline[1]=thisplayer+64;
X outputline[2]=NULL;
X break;
X case _ACTION:
X outputline[1]=NULL;
X break;
X case _STARTUP:
X outputline[1]=totalplayers+64;
X outputline[2]=NULL;
X break;
X case _TEXT:
X strcpy(&outputline[1],(char*) details);
X break;
X case _END:
X outputline[1]=NULL;
X }
X for (current=0; (current<=totalplayers); current++) {
X if (outputline[0]==_END) {
X }
X if (players[current].live) {
X w_p(playerids[current],outputline,strlen(outputline)+1);
X }
X }
X}
X
Xint getrequest(thisplayer,requesttype,specific)
X int* thisplayer;
X char* requesttype;
X char* specific;
X{
X char* received;
X static int sweep;
X int oldsweep;
X sweep++;
X if ((sweep>totalplayers) || (sweep<=0))
X sweep=1;
X oldsweep=sweep;
X while (players[sweep].live==0) {
X sweep++;
X if (sweep>totalplayers)
X sweep=1;
X if (sweep==oldsweep)
X return 0;
X }
X received=read_player(playerids[sweep]);
X *thisplayer=sweep;
X if (*received==NULL)
X return 0;
X *requesttype=received[0];
X strcpy(specific,(received+=1));
X return 1;
X }
X
X
Xvoid shutdowninterface() {
X disconnect_all();
X}
X
X
X/* - PD Socket code begins here.
X * init_socket() - intialize our socket, port is the port number to use
X * call this once at the beginning of your code
X */
X
Xint init_socket(port)
X int port;
X{
X setbuf(stdout, (char *)0);
X if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
X perror("socket");
X return 0;
X }
X sc_in.sin_family = AF_INET;
X sc_in.sin_addr.s_addr = INADDR_ANY;
X sc_in.sin_port = htons((u_short) port);
X if (bind(s, (struct sockaddr *) &sc_in, sizeof(sc_in)) < 0) {
X perror("bind");
X return 0;
X }
X if (listen(s, 5) < 0) {
X perror("listen");
X return 0;
X }
X
X FD_ZERO(&active);
X
X return 1;
X}
X
X
X/*
X * disconnect_all() - throws everyone off
X */
X
Xint disconnect_all()
X{
X register int i;
X
X for (i = 0; i < FD_SETSIZE; i++) {
X if (FD_ISSET(i, &active))
X (void) disconnect(i);
X }
X return 1;
X}
X
X
X/*
X * shut-down -- kills all connections and exits the pgm
X */
X
Xint shut_down()
X{
X (void) disconnect_all();
X exit(0);
X}
X
X
X/* hostfrom() - returns a string containing an ascii name for the host
X * that the passed socket s is connected to. Note that the
X * string is in static space. If you want to munge with it,
X * make a copy.
X */
X
Xchar *hostfrom(i)
X int i;
X{
X struct sockaddr_in from;
X int fromlen = sizeof(from);
X struct hostent *host;
X struct in_addr addr;
X
X if (getpeername(i, &from, &fromlen) < 0) {
X perror("getpeername");
X return NULL;
X }
X
X addr = from.sin_addr;
X if ((host = gethostbyaddr(&addr, sizeof(addr), AF_INET)) == NULL) {
X debug("gethostbyaddr failed");
X return NULL;
X }
X
X return curhostname = host->h_name;
X}
X
X
X/*
X * hostname() - returns curhostname
X */
X
Xchar *hostname()
X{
X return curhostname;
X}
X
X
X/*
X * new_player() - call this routine in your main loop to allow new
X * players to join. returns a playerId or -1 if no one
X * wants to join.
X * if wait == 0, then put your process to sleep until
X * someone new tries to connect.
X */
X
Xint new_player(wait)
X int wait; /* 0 - wait for activity, else don't wait */
X{
X fd_set readfds;
X int j;
X struct timeval *pWaitTime, waitTime;
X
X pWaitTime = &waitTime;
X
X if (0 == wait) {
X pWaitTime = NEVER;
X } else {
X pWaitTime->tv_sec = SECONDSLIMIT;
X pWaitTime->tv_usec = MICROSECONDSLIMIT;
X }
X
X bcopy((char *) &active, (char *) &readfds, sizeof(active));
X
X FD_SET(s, &readfds);
X
X if (select(FD_SETSIZE, &readfds, NONE, NONE, pWaitTime) < 0) {
X perror("select");
X return -1;
X }
X if (FD_ISSET(s, &readfds)) {
X if ((j = accept(s, IGNORE, (int *) 0)) < 0) {
X return -1;
X }
X FD_SET(j, &active);
X curhostname = hostfrom(j);
X debug("Test Host=%s\n", curhostname);
X return j;
X } else {
X return -1;
X }
X}
X
X
X/*
X * disconnect() - drop the player with the given id
X */
X
Xint disconnect(id)
X int id;
X{
X if (FD_ISSET(id, &active)) {
X debug("** Just dropped %d\n", id);
X FD_CLR(id, &active);
X if (close(id) < 0) {
X perror("close");
X return 0;
X }
X } else {
X debug("** Just tried to drop someone not connected\n");
X return 0;
X }
X return 1;
X}
X
X
X/*
X * read_player() - This routine returns the next string from the player
X * connected to descriptor playerFd. If there is no
X * input it returns the empty string. If the connection
X * is lost the string LOST_CARRIER_MSG is returned.
X * NOTE: control characters are replaced by spaces
X * and it is null terminated at the first nl/cr
X */
X
Xchar *read_player(playerFd)
X int playerFd;
X{
X fd_set readfds;
X struct timeval waitTime;
X
X waitTime.tv_sec = SECONDSLIMIT;
X waitTime.tv_usec = MICROSECONDSLIMIT;
X
X bcopy((char *) &active, (char *) &readfds, sizeof(active));
X
X if (select(FD_SETSIZE, &readfds, NONE, NONE, &waitTime) < 0) {
X perror("select");
X return("");
X }
X
X if (FD_ISSET(playerFd, &readfds)) {
X int nbytes, i;
X
X nbytes = read(playerFd, cur_input, LINE_LEN);
X if (nbytes < 0) {
X perror("read");
X disconnect(playerFd);
X return(LOST_CARRIER_MSG);
X } else if (nbytes == 0) {
X disconnect(playerFd);
X return(LOST_CARRIER_MSG);
X } else {
X/* Don't need control editing for(i=0; i<nbytes; ++i) {
X if (iscntrl(cur_input[i])) {
X if (cur_input[i]=='\n' ||
X cur_input[i]=='\r')
X cur_input[i] = '\n';
X else
X cur_input[i] = ' ';
X }
X }
X*/
X if (nbytes != LINE_LEN) {
X cur_input[nbytes] = '\0';
X } else {
X cur_input[LINE_LEN - 1] = '\0';
X }
X
X return((char *) cur_input);
X }
X }
X return("");
X}
X
X
X/*
X * write_player() - write to id, a string with the given length
X */
X
Xint w_p(id, str, len)
X int id, len;
X char *str;
X{
X if (id > -1) {
X if (!FD_ISSET(id, &active)) {
X debug("** Tried to write to closed id #%d.\n", id);
X return 0;
X } else if (write(id, str, len) < 0) {
X perror("Write");
X return 0;
X }
X }
X return 1;
X}
X
X
X
X
END_OF_FILE
if test 8905 -ne `wc -c <'interface.c'`; then
echo shar: \"'interface.c'\" unpacked with wrong size!
fi
# end of 'interface.c'
fi
if test -f 'types.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'types.h'\"
else
echo shar: Extracting \"'types.h'\" \(282 characters\)
sed "s/^X//" >'types.h' <<'END_OF_FILE'
Xtypedef struct {
X char terrain;
X int population;
X int lastuse;
X int troops;
X int owner;
X} hex;
X
Xtypedef struct {
X int x;
X int y;
X} location;
X
Xtypedef struct {
X int action;
X int hexes;
X int troops;
X int population;
X int citadels;
X int live;
X location start;
X} player;
X
END_OF_FILE
if test 282 -ne `wc -c <'types.h'`; then
echo shar: \"'types.h'\" unpacked with wrong size!
fi
# end of 'types.h'
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked both archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0