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