[comp.sources.games] v04i019: bridge - multiplayer networked bridge game, Part01/02

games@tekred.TEK.COM (05/31/88)

Submitted by: Jiang-Hsing Chu <jchu@mimsy.umd.edu>
Comp.sources.games: Volume 4, Issue 19
Archive-name: bridge/Part01

	[This is a program that allows four persons to play bridge at
	 different places, different computers, via the computer
	 communication.  Now that you've practiced your bidding with
	 v4i018, you can start playing.  -br]

#! /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 1 (of 2)."
# Contents:  README MANIFEST bridge.README bridge.c ctl_transact.c
#   init_disp.c invite.c look_up.c master_io.c master_talk.c msgs.c
#   slave_io.c
# Wrapped by billr@saab on Tue May 31 09:13:29 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(860 characters\)
sed "s/^X//" >README <<'END_OF_README'
XThis program provides communication between different machines so that people
Xcan play bridge even they are on different machine.  It is written by
XShyan-Ming Yuan and Jiang-Hsing Chu at University of Maryland, College Park.
XIt was tested on Vaxes and Sun 3/50 running BSD 4.2 and BSD 4.3.
XSince we don't have the previlege to create a 'bridge daemon' as a normal user,
Xwe decided to use 'talk daemon' instead.  The underlying communication program
Xis modified from the 'talk' program.  You will have confusion in trying to
Xconnect to the others, this is also explained in bridge.README.
X
XYou are free to use, copy, and modify these programs.  You receive the program
Xas it is.  No warranty.  No major update is expected.  But bug report is
Xwelcome.  If you have a major modification, please send me a new copy.
XThanks.  Jiang-Hsing Chu.    e-mail: jchu@mimsy
END_OF_README
if test 860 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f MANIFEST -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"MANIFEST\"
else
echo shar: Extracting \"MANIFEST\" \(744 characters\)
sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                  1	This shipping list
X Makefile                  2	
X README                    1	
X bridge.README             1	
X bridge.c                  1	
X ctl.c                     2	
X ctl.h                     2	
X ctl_transact.c            1	
X get_addrs.c               2	
X get_names.c               2	
X init_disp.c               1	
X invite.c                  1	
X invitebridge.README       2	
X look_up.c                 1	
X master_io.c               1	
X master_talk.c             1	
X msgs.c                    1	
X slave_io.c                1	
X slave_talk.c              2	
X talk.h                    2	
X talk_ctl.h                2	
END_OF_MANIFEST
if test 744 -ne `wc -c <MANIFEST`; then
    echo shar: \"MANIFEST\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f bridge.README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"bridge.README\"
else
echo shar: Extracting \"bridge.README\" \(7255 characters\)
sed "s/^X//" >bridge.README <<'END_OF_bridge.README'
XBridge is the program stored in the local site so that the player can 
Xcommunicate with other remote players.  To be able to use this program,
Xyou must have a terminal supporting "curses".  When you are invited to play
Xthe game, a message will be shown on your screen indicating someone
Xwants to talk to you as the talk program does and requests you to type
X'talk xxx@yyy.zzz.edu'.  At this moment, you should type 'bridge
Xxxx@yyy.zzz.edu' to make the connection.  It's obviously confusing because 
Xyou don't know the message is coming form some one who wants to talk to 
Xyou or form some one who wants to play bridge with you.  Unfortunately,
Xthis is what we have so far, we may be able to improve it later.
XThe confusion can be avoided by presetting the time for playing bridge
Xvia talk or mail in advance.  You can assume that you are invited to 
Xplay bridge when talk Daemon shows the message around the preset time.
X
XSince we assume that all the users of 'bridge' are experienced computer
Xusers and bridge players, there will not be any HELP information other
Xthan those shown on the screen.  Please read the followings carefully
Xbefore you start to use the program.
X
X(1)General Guide:
X   1. Always end your input with a carriage return.
X   2. Input only when you are prompted to avoid mistakes.
X   3. Some abbreviations are used:
X      N: No Trump, S: Spade, H: Heart, D: Diamond, C: Club,
X      X: Double, XX: Redouble, P: Pass, T: 10.
X
X(2)Bidding:
X   You will be prompted when it is your turn to bid.  You will be prompted
X   again if your bid is illegal.  To make a bid, type the rank(between 1 and 7)
X   followed by the suit(N,S,H,D,C); or type P, X, and XX for Pass, Double, 
X   and Redouble respectively.  Remember to end it with a carriage return.
X   Please note that a single carriage return means PASS.
X   The followings are legal INPUTs (not necessary legal bids):
X     1H, 2N, 4C, X, XX, P,...
X   The followings are not legal inputs:
X     5, S, 0D, 8C, ....
X   All the inputs are checked for the validity according to the rules of
X   bridge game.  You are encouraged to report any illegal bid which is
X   accepted by the program.
X
X(3)Playing:
X   You will be prompted when it is your turn to play.  You will be prompted
X   again if your play is illegal.  To make a play, type the suit(S,H,D,C)
X   followed by the face value(2,3,...,9,T,J,Q,K,A) and end it with a carriage
X   return.  There are three special features for playing:
X   1. Following:
X      When you are not the first person to lead a card, you can simply input
X      the face value(2,3,...,T,J,Q,K,A) which means you are following the
X      same suit.  For example, if your right hand side opponent leads S3, you
X      can type J instead of SJ when you want to play SJ.
X   2. Don't Care:
X      When you have only one choice or you don't care which card is to be 
X      played, you can simply type a carriage return.  In such case, the porgram
X      will automatically play the card which is a legal play and has the lowest
X      rank.  The cards are ranked as: SA>SK>...>S2>HA>...>C2.  To avoid the
X      disaster caused by typing mistake, this function is disabled when you
X      are in the position to lead a card except the last round.
X   3. Finish Quickly (claim):
X      The declarer, in his turn or dummy's turn to play, can claim the number
X      of tricks he can win to save time.  To make the claim, the declarer
X      has to type in Fn, where n is a number between 0 and 13 which means
X      declarer is willing to finish the game with n MORE tricks.  A single
X      "F" without any number followed means all the tricks left.  This claim
X      is subject to the approval of the opponents.  All the cards will be
X      shown on the opponents' screen to make their decision easier.  If the
X      opponents don't agree to finish the game, the play is resume after
X      all extra cards are erased from the opponents' screen.
X
X(4)Scoring
X   The scoring system of our birdge program is rubber.  To win the rubber
X   bonus, basically, you have to win two games before your opponents do.  
X   Thus, you might need a different strategy in playing rubbers.  For your
X   convenience, the scoring rule is also enclosed. Due to the limited space
X   on the screen, please note the following notation:
X
X         N-S  E-W
X      TRICK  ...  ...  <-- number of tricks won by each side so far
X      SCORE  ...  ...  <-- score below the line (see the attached scoring rule)
X                            which doesn't exceed 100 points.
X      TOTAL  ...  ...  <-- total score (including the score in SCORE entry) won
X                          by each side so far
X
XIt is also important to know whether you and/or your opponents have won a game
Xalready.  To gain this information, you have to look at the upper left corner
Xon the screen, i.e. the VUL field.  It can be interpreted as:
X
X            VUL.
X
X            NONE    <-- neither side has won a game
X            N-S     <-- N-S has won a game, but E-W hasn't
X            E-W     <-- E-W has won a game, but N-S hasn't
X            BOTH    <-- both N-S and E-W have won a game
X
X(5) Conversation:
X    All your inputs are sent to the bridge program when you are in input
X    mode.  However, if you are in conversation mode, all your inputs will
X    be sent to the screens of all other players (same as talk does, but it
X    is a multiway talk).  The ESC key is used to switch back and forth
X    between input mode and conversation mode.  You will be put in the input
X    mode at the beginning of the game.
X
X(6)Ending:
X   There is not a graceful way to end this program.  It will run forever
X   unless you type a ctrl-C. 
X
X==============================================================================
XSCORING TABLE
X
XTrick Score (below the line)
X
XSpades of Hearts	30 per trick	|  If doubled:
XDiamonds or Clubs	20 per trick	|	multiply by 2
XNotrump		40 for first trick	|  If redoubled:
X	30 for each additional trick	|	multiply by 4
X
XGame - 100 points or more below the line
X
XBonuses (above the line)
X
XRubber bonus:	500 if you win two games out of three
X		700 if you win the only two games
X
X			Not Vulnerable		Vulnerable
XSlam Bonus:  Small Slam	     500		    750
X	     Grand Slam	    1000		   1500
X
X/* NOT IMPLEMENTED
XHonors:  4 trump honors in one hand		100
X	 5 trump honors in one hand		150
X	 4 aces in one hand at notrump		150
X*/
X
XMaking Doubled (or redoubled) Contract:	 50 points
X
X			Not Vulnerable		Vulnerable
XOvertricks:  Undoubled	  trick value		trick value
X	     Doubled	  100 per trick		200 per trick
X	     Redoubled	  200 per trick	 	400 per trick
X
XPenalties (above the line)
X
X			Undoubled		Doubled
X		Not Vul.	Vul.	  Not Vul.	Vul.
XDown 1		   50		100	    100		200
XDown 2		  100		200	    300		500
XDown 3		  150		300	    500		800
XDown 4		  200		400	    700	       1100
XDown 5		  250		500	    900	       1400
XDown 6		  300		600	   1100	       1700
XDown 7		  350		700	   1300        2100
XDown 8		  400		800	   1500	       2500
X  .                .             .           .           .
X  .                .             .           .           .
X  .                .             .           .           .
X
XIf redoubled: multiply the doubled penalty by two.
X
X=============================================================================
X
END_OF_bridge.README
if test 7255 -ne `wc -c <bridge.README`; then
    echo shar: \"bridge.README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f bridge.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"bridge.c\"
else
echo shar: Extracting \"bridge.c\" \(14041 characters\)
sed "s/^X//" >bridge.c <<'END_OF_bridge.c'
X#include <stdio.h>
X
X#define EQ ==
X#define NEQ !=
X#define NOT !
X#define AND &&
X#define OR ||
X#define TRUE 1
X#define FALSE 0
X
X#define SIDE(i) ((i)%2)
X#define NEXT(i) ((i+1)%4)
X#define PARTNER(i) ((i+2)%4)
X#define IC(i) (i+'0')
X#define ALLp p=0;p<=3;++p
X
XFILE *f1;
Xchar scr[16][80];
Xint  r[4]={1,6,11,6},c[4]={18,32,18,4};
Xint hand= -1,decl,dummy,trump,dbl,ld,ldd,win[2],HBR,HBS,HBB,rs,ts[2]={0,0};
Xint vt[2]={0,0},part[2]={0,0};
Xint eofg,eofp,eofr=0;
Xint card[52],C[4][52],NS[4][4],LS[4];
Xint TV[5]={20,20,30,30,30};
Xint VUL[2][16]={0,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,
X                0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,1};
Xchar CBR,CBS,CPR,CPS;
Xextern char player[4][20];
Xchar str[80],inp[80],num[6];
Xchar FV[13]={'2','3','4','5','6','7','8','9','T','J','Q','K','A'};
Xchar SV[5]={'C','D','H','S','N'};
Xchar P[4]={'N','E','S','W'};
Xextern long seed;
X
Xinit()
X{  int p,t;
X
X   f1=fopen("bridge.log","w");
X   for(ALLp){player[p][0]=P[p];player[p][1]=':';}
X   for(ALLp){
X      str[1]='\0';
X      str[0]=P[PARTNER(p)];
X      rput(p,13,4,29,str);
X      str[0]=P[t=NEXT(p)];
X      rput(p,13,8,20,str);
X      str[0]=P[PARTNER(t)];
X      rput(p,13,8,38,str);
X      str[0]=P[p];
X      rput(p,13,12,29,str);
X      rput(p,13,17,5,player[(p+2)%4]);
X      rput(p,13,17,25,player[(p+1)%4]);
X      rput(p,13,17,45,player[p]);
X      rput(p,13,17,65,player[(p+3)%4]);
X   }
X   srandom(seed);
X}
Xrinit()
X{  int tvt,p,i,j;
X   char *d;
X
X   for(i=0;i<16;i++){
X      d=(char *)&scr[i][0];
X      for(j=0;j<80;++j) *d++ =' ';
X   }
X   sput("Hand:",0,0);sput("Vul.:",1,0);
X   sput("Bid",0,51);sput("=N==E==S==W==",1,46);
X   sput("Play",0,66);sput("=N===E===S===W===",1,60);
X   sput("--------------",5,17);
X   sput("|     N      |",6,17);
X   sput("|W          E|",7,17);
X   sput("|            |",8,17);
X   sput("|     S      |",9,17);
X   sput("--------------",10,17);
X   sput("Result:",15,47);
X   itos((++hand)+1);
X   sput(num+3,0,6);
X   for(ALLp)rput(p,8,0,0,num+3);
X
X/* for duplicate bridge
X   sput("Score:",15,62);
X   tvt=VUL[0][hand%16]*2+VUL[1][hand%16];
X*/
X/* for rubber */
X   tvt=vt[0]*2+vt[1];
X   for(ALLp){ clearw(p,11); clearw(p,10);}
X   str[1]='\0';
X   switch(tvt){
X      case 0: for(ALLp)rput(p,8,1,0,"NONE");sput("NONE",1,6);break;
X      case 1: for(ALLp){
X                 rput(p,8,1,0,"E-W ");
X                 str[0]=45+SIDE(p)*79;
X                 rput(p,10,3,8,str);
X              }
X              sput("E-W",1,6);
X              break;
X      case 2: for(ALLp){
X                 rput(p,8,1,0,"N-S ");
X                 str[0]=124-SIDE(p)*79;
X                 rput(p,10,3,8,str);
X              }
X              sput("N-S",1,6);
X              break;
X      case 3: str[0]='+';
X              for(ALLp){
X                 rput(p,8,1,0,"BOTH");
X                 rput(p,10,3,8,str);
X              }
X              sput("BOTH",1,6);
X              break;
X   }
X   for(ALLp){
X      rput(p,9,0,0,"    0");
X      rput(p,9,0,6,"    0");
X      clearw(p,0);clearw(p,1);clearw(p,2);clearw(p,3);
X      clearw(p,4);clearw(p,5);clearw(p,6);clearw(p,7);
X   }
X}
Xpscr()
X{   int i,j;
X    char *d;
X
X    for(i=0;i<16;++i){
X       d=(char *)&scr[i][0];
X       for(j=0;j<80;++j)fprintf(f1,"%c",*d++);
X       fprintf(f1,"\n");
X    }
X    fprintf(f1,"\n\n\n\n");
X    fflush(f1);
X}
X
Xsput(s,r,c)
Xchar *s;
Xint r,c;
X{   char *d;
X
X    d=(char *)&scr[r][c];
X    while(*s) *d++ = *s++;
X}
Xdeal()
X{  int i,j,rr,cc;
X   char *d;
X
X   for(i=0;i<52;++i){
X      card[i]=i;
X      for(j=0;j<4;++j)C[j][i]=0;
X   }
X   for(i=0;i<4;++i){
X      LS[i]=0;
X      for(j=0;j<4;++j) NS[i][j]=0;
X   }
X   i=52;
X   while(i>1){
X      j=random()%i--;
X      C[i/13][card[j]]=1;
X      NS[i/13][card[j]/13]++;
X      if(NS[i/13][card[j]/13]>LS[i/13]) LS[i/13]++;
X      card[j]=card[i];
X   }
X   C[0][card[0]]=1;
X   NS[0][card[0]/13]++;
X   for(i=0;i<4;++i) printhand(i,i);
X   for(i=0;i<4;++i){
X      rr=r[i]-1;cc=c[i]; if(i EQ 3) cc=cc+10-LS[i];
X      for(j=51;j>=0;--j){
X         if(j%13 EQ 12){ d=(char *)&scr[++rr][cc];*d++ =SV[j/13]; *d++ = ' ';}
X         if(C[i][j] EQ 1)*d++ = FV[j%13];
X      }
X   }
X}
Xbid()
X{  int i,j,p,rb,eofb,legalbid,NP,OB;
X   int PFBS[2][5];
X
X   for(ALLp){
X      rput(p,10,2,0,"-----------");
X      rput(p,10,4,6,"-----------");
X      for(i=0;i<=3;++i) rput(p,10,i,11,"|");
X      for(i=0;i<=3;++i) rput(p,10,i+3,5,"|");
X   }
X   for(i=0;i<2;++i)for(j=0;j<5;++j)PFBS[i][j]= -1;
X   rb=HBR=NP=0;
X   eofb=eofg=FALSE;
X   HBS= -1;
X   for(i=OB=hand%4;NOT eofb;i=NEXT(i)){
X      legalbid=FALSE;
X      do{
X         if(readbid(i)<0)continue;
X         if(CBS EQ 6){
X            if((dbl NEQ 1) OR (SIDE(i) NEQ SIDE(HBB)) OR (HBR<1))continue;
X            dbl=2;ldd=i;
X         }
X         if(CBS EQ 5){
X            if((dbl NEQ 0) OR (SIDE(i) EQ SIDE(HBB)) OR (HBR<1))continue;
X            dbl=1;ld=i;
X         }
X         if(CBR<HBR)continue;
X         if(CBR>=HBR AND CBR<8){
X            if ((CBR EQ HBR) AND (CBS<=HBS))continue;
X            dbl=0;HBR=CBR;HBS=CBS;HBB=i;
X            if(PFBS[SIDE(i)][CBS] EQ -1)PFBS[SIDE(i)][CBS]=i;
X         }
X         if(CBS EQ 7) NP++; else NP=0;
X         legalbid=TRUE;
X      }while(NOT legalbid);
X      if(NP EQ 4){eofb=eofg=TRUE;inp[0]=inp[1]='=';}
X      if((NP EQ 3) AND (HBR>0)) {eofb=TRUE;inp[0]=inp[1]='=';}
X      printbid(rb,i);
X      sput(inp,2+rb+(i<OB),47+3*(i%4));
X      if(NEXT(i) EQ OB) rb++;
X   }
X   decl=PFBS[SIDE(HBB)][HBS];
X   dummy=PARTNER(decl);
X   trump=HBS;
X   if(NOT eofg){
X      strcpy(str,"CONTRACT: ");
X      str[10]=HBR+'0'; str[11]=SV[HBS]; str[12]='/'; str[13]=P[decl]; j=14;
X      if(dbl>0){str[j++]=' ';str[j++]='X';str[j++]='/';str[j++]=P[ld];}
X      if(dbl>1)
X         {str[j++]=' ';str[j++]='X';str[j++]='X';str[j++]='/';str[j++]=P[ldd];}
X      str[j]='\0';
X      for(ALLp)rput(p,11,0,0,str);
X      sput(str+10,4+rb,47);
X   }
X}
Xplay()
X{  int r,i,ss,legalplay,winner,FL,FPS,HPR,HPS,p;
X
X   FL=NEXT(decl);
X   win[0]=win[1]=0;
X   for(r=1;r<=13;++r){
X      i=FL;
X      do{
X         legalplay=FALSE;
X         do{
X            if(readplay(i EQ dummy ? decl : i,i)<0)continue;
X            if(CPS EQ 5){
X               if(SIDE(i) NEQ SIDE(decl))continue;
X               if(CPR<0 OR CPR>13-win[0]-win[1])continue;
X               printhand(NEXT(decl),decl);
X               printhand(NEXT(decl),NEXT(dummy));
X               printhand(NEXT(dummy),decl);
X               printhand(NEXT(dummy),NEXT(decl));
X               strcpy(inp,"Declarer asks    more tricks.  Agree?");
X               if(CPR>9) inp[14]='1';
X               inp[15]=CPR%10+'0';
X               rget((1<<NEXT(decl))|(1<<NEXT(dummy)),inp);
X               if(inp[0] NEQ 'Y'){
X                  clearw(NEXT(decl),0);
X                  clearw(NEXT(decl),1);
X                  clearw(NEXT(dummy),3);
X                  clearw(NEXT(dummy),0);
X                  continue;
X               }
X               printhand(decl,NEXT(decl));
X               printhand(decl,NEXT(dummy));
X               win[SIDE(decl)]+=CPR;
X               win[1-SIDE(decl)]=13-win[SIDE(decl)];
X               itos(win[0]);for(ALLp)rput(p,9,0,0,num);
X               itos(win[1]);for(ALLp)rput(p,9,0,6,num);
X               for(ALLp){clearw(p,4);clearw(p,5);clearw(p,6);clearw(p,7);}
X               return;
X            }
X            if(i EQ FL){
X               if(CPS EQ 4) continue;
X               if(CPS EQ 6){
X		   if (r < 13) continue;
X                   else{
X                      for(ss=0;C[i][ss]<1;++ss);
X                      inp[0]=SV[CPS=ss/13];inp[1]=FV[CPR=ss%13];
X                   }
X	       }
X               if(NOT inhand(CPS,CPR,i))continue;
X               if(r EQ 1){
X                  for(ALLp) clearw(p,10);
X                  for(p=NEXT(dummy);p NEQ dummy;p=NEXT(p))printhand(p,dummy);
X                  printhand(dummy,decl);
X               }
X               winner=FL;
X               HPR=CPR;
X               FPS=HPS=CPS;
X            }
X            else{
X               if(CPS EQ 6){
X                  for(ss=NS[i][FPS]?FPS*13:0;C[i][ss]<1;++ss);
X                  inp[0]=SV[CPS=ss/13];inp[1]=FV[CPR=ss%13];
X               }
X               if(CPS EQ 4) {CPS=FPS;inp[1]=inp[0];inp[0]=SV[FPS];}
X               if((CPS NEQ FPS) AND (NS[i][FPS] NEQ 0))continue;
X               if(NOT inhand(CPS,CPR,i))continue;
X               if(CPS EQ HPS){
X                  if(CPR>HPR){winner=i;HPR=CPR;}
X               }
X               else {if(CPS EQ trump){winner=i;HPR=CPR;HPS=CPS;}}
X            }
X            printplay(i);
X            printsuit(i,i,CPS);
X            sput(inp,1+r,61+4*i);
X            sput("!",1+r,63+4*FL);
X            if(i EQ dummy)
X               for(p=NEXT(dummy);p NEQ dummy;p=NEXT(p))printsuit(p,i,CPS);
X            if(i EQ decl) printsuit(dummy,decl,CPS);
X            legalplay=TRUE;
X         }while(NOT legalplay);
X         i=NEXT(i);
X      }while(i NEQ FL);
X      itos(++win[SIDE(FL=winner)]);
X      for(ALLp) rput(p,9,0,6*SIDE(FL),num);
X      sput("*",r+1,63+4*winner);
X      if(r<13){
X         waitkey("Press return to pause.");
X         for(ALLp){clearw(p,4);clearw(p,5);clearw(p,6);clearw(p,7);}
X      }
X   }
X}
Xscore()
X{  int vt,over,otv,winside;
X
X   vt=VUL[winside=SIDE(decl)][hand%16];
X   over=win[winside]-6-HBR;
X   otv=TV[HBS];
X   if(dbl>0) otv=100*dbl*(vt+1);
X   if(over>=0){
X      rs=HBR*TV[HBS];
X      if(HBS EQ 4) rs+=10;
X      if(dbl NEQ 0) rs=rs*2*dbl;
X      if(rs>=100)rs+=(250+200*vt);
X      rs+=(50+over*otv);
X      if(dbl NEQ 0)rs+=50; 
X      if(HBR EQ 6)rs+=500+250*vt;
X      if(HBR EQ 7)rs+=1000+500*vt;
X   }
X   else{
X      if(dbl EQ 0)rs=50*over*(vt+1);
X      else rs=((200*over+100)+100*over*vt)*dbl;
X   }
X   if(rs<0){winside=1-winside;rs= -rs;}
X   ts[winside]+=rs;
X   printscore(winside);
X   itos(over);sput(num+3,15,55);
X   waitkey("Press return to pause.");
X}
Xrscore()
X{  int over,otv,winside,p;
X
X   winside=SIDE(decl);
X   over=win[winside]-6-HBR;
X   otv=TV[HBS];
X   if(dbl>0) otv=100*dbl*(vt[winside]+1);
X   if(over>=0){
X      rs=HBR*TV[HBS];
X      if(HBS EQ 4) rs+=10;
X      if(dbl NEQ 0) rs=rs*2*dbl;
X      ts[winside]+=rs;
X      ts[winside]+=(over*otv);
X      if(dbl NEQ 0)ts[winside]+=50; 
X      if(HBR EQ 6)ts[winside]+=500+250*vt[winside];
X      if(HBR EQ 7)ts[winside]+=1000+500*vt[winside];
X      part[winside]+=rs;
X      if(part[winside]>=100){
X         if(vt[winside]){
X            ts[winside]+=700-200*vt[1-winside]; vt[0]=vt[1]=0;
X            eofr=1;
X         }
X         else{vt[winside]+=1;}
X         part[0]=part[1]=0; for(ALLp)rput(p,9,1,0,"    0     0");
X      }
X      else{itos(part[winside]);for(ALLp)rput(p,9,1,6*winside,num);}
X      itos(ts[winside]);for(ALLp)rput(p,9,2,6*winside,num);
X   }
X   else{
X      if(dbl EQ 0)rs=50*over*(vt[winside]+1);
X      else rs=((200*over+100)+100*over*vt[winside])*dbl;
X      ts[1-winside]-=rs;
X      itos(ts[1-winside]);for(ALLp)rput(p,9,2,6-6*winside,num);
X   }
X   itos(over);sput(num+3,15,55);
X   waitkey("Press return to pause.");
X}
Xreadbid(i)
Xint i;
X{   
X   strcpy(inp,"It's your turn to bid ");
X   rget(1<<i,inp);
X   inp[2]='\0'; 
X   CBR=inp[0]-'0';
X   if(CBR>0 AND CBR <8) return(CBS=lookup(inp[1],SV,5));
X   CBR=8;
X   switch(inp[0]){
X      case '\n':
X      case 'P': inp[0]=inp[1]='-';CBS=7;return(CBS);
X      case 'X': if(inp[1] EQ 'X'){CBS=6;return(CBS);}
X                else{inp[1]='\0';CBS=5;return(CBS);}
X      default:  return(-1);
X   }
X}
Xreadplay(i,j)
Xint i,j;
X{
X   if (j EQ dummy) strcpy(inp,"It's dummy's turn to play ");
X   else strcpy(inp,"It's your turn to play ");
X   rget(1<<i,inp);
X   if(inp[0] EQ 'F'){
X     CPS=5;CPR=inp[1]-'0';
X     if(inp[2]>='0' AND inp[2]<='9') CPR=CPR*10+inp[2]-'0';
X     if(inp[1]=='\n') CPR=13-win[0]-win[1];
X     return(0);
X     }
X   inp[2]='\0'; 
X   if((CPR=lookup(inp[0],FV,13))>=0) {CPS=4;return(0);}
X   if(inp[0] EQ '\n'){CPS=6;return(0);}
X   CPS=lookup(inp[0],SV,4);
X   CPR=lookup(inp[1],FV,13);
X   if(CPS<0 OR CPR<0) return(-1);
X   else return(0);
X}
Xlookup(ch,t,i)
Xint i;
Xchar ch,*t;
X
X{  int j;
X 
X   for(j=i-1;j>=0;j--)if(ch EQ t[j]) return(j);
X   return(-1);
X}
Xinhand(s,r,i)
Xint s,r,i;
X
X{  int j;
X
X   j=s*13+r;
X   if(C[i][j] NEQ 1)return(FALSE);
X   C[i][j]=0;
X   NS[i][s]--;
X   return(TRUE);
X}
Xitos(i)
Xint i;
X
X{  int j,f;
X   char t;
X
X   if(i EQ 0) {num[0]=num[1]=num[2]=num[3]=' ';num[4]='0';num[5]=0;return;}
X   f=0;if(i<0){f=1;i= -i;}
X   num[0]='\0';
X   for(j=1;j<=5;j++)
X      if(i>0){
X         num[j]=i%10+'0';
X         i/=10;
X      }
X      else{ if(f){num[j]='-';f=0;} else num[j]=' ';}
X   for(i=0;i<=2;++i){
X      t=num[i];
X      num[i]=num[5-i];
X      num[5-i]=t;
X   }
X}
Xprinthand(p,h)
Xint p,h;
X
X{  int s;
X
X   for(s=0;s<4;++s)printsuit(p,h,s);
X}
Xprintsuit(p,h,s)
Xint p,h,s;
X
X{  int i,j=2,offset=0;
X   str[0]=SV[s];
X   str[1]=' ';
X   for(i=12;i>=0;--i)if(C[h][s*13+i] EQ 1)str[j++]=FV[i];
X   str[j++]=' ';str[j]='\0';
X   if((j=(6+h-p)%4) EQ 3) offset=11-LS[h];
X   rput(p,j,3-s,offset,str);
X}
Xprintplay(h)
Xint h;
X
X{  int p;
X
X   for(ALLp) rput(p,(6+h-p)%4+4,0,0,inp);
X}
Xprintscore(winside)
Xint winside;
X
X{ int p;
X
X  itos(rs);for(ALLp){rput(p,9,1,6*winside,num);rput(p,9,1,6-6*winside,"    0");}
X  sput(num,15,69);
X  itos(ts[winside]);for(ALLp)rput(p,9,2,6*winside,num);
X}
Xprintbid(rb,i)
Xint rb,i;
X{  int p;
X 
X   p=i;
X   rput(p,10,5+rb/4,6+3*(rb%4),inp); p=NEXT(p);
X   rput(p,10,3-rb%4,12+3*(rb/4),inp); p=NEXT(p);
X   rput(p,10,1-rb/4,9-3*(rb%4),inp); p=NEXT(p);
X   rput(p,10,3+rb%4,3-3*(rb/4),inp); p=NEXT(p);
X}
Xwaitkey(c)
Xchar *c;
X{  int p;
X   char t[40];
X   do {strcpy(t,c);}
X   while(rwait((1<<decl)|(1<<NEXT(decl))|(1<<NEXT(dummy)),t,2)>0);
X   for(ALLp) clearw(p,12);
X}
Xclearw(p,wn)
Xint p,wn;
X
X{  
X   str[0]='Z';
X   str[1]='\0';
X   rput(p,wn,0,0,str);
X}
X/*
Xrput(p,w,r,c,s)
Xint p,w,r,c;
Xchar *s;
X
X{   printf("p=%d, w=%d, r=%d, c=%d, s=%s",p,w,r,c,s);
X}
Xrget(p,s)
Xint p;
Xchar *s;
X{   scanf("%s",s);
X}
X*/
Xmore()
X{  int p;
X/*
X   if(NOT eofr) return;
X   strcpy(inp,"You like another rubber?");
X   rwait(15,inp,5);
X   if(inp[0] NEQ 'Y'){for(ALLp)rput(p,0,0,0,"\\"); exit();}
X   for(ALLp)clearw(p,12);
X   eofr=0;
X*/
X   return;
X}
Xbridge()
X{  int p;
X
X   init();
X   eofp=FALSE;
X   do{
X      rinit();
X      deal();
X      bid();
X      if(NOT eofg){
X         play();
X         rscore();
X      }
X      else for(ALLp) clearw(p,10);
X      pscr();
X      more();
X   }while(NOT eofp);
X}
END_OF_bridge.c
if test 14041 -ne `wc -c <bridge.c`; then
    echo shar: \"bridge.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f ctl_transact.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"ctl_transact.c\"
else
echo shar: Extracting \"ctl_transact.c\" \(2210 characters\)
sed "s/^X//" >ctl_transact.c <<'END_OF_ctl_transact.c'
X#ifndef lint
Xstatic	char sccsid[] = "@(#)ctl_transact.c 1.1 86/02/05 SMI"; /* from UCB */
X#endif
X#include "talk_ctl.h"
X#include <sys/time.h>
X
X#define CTL_WAIT 2	/* the amount of time to wait for a 
X			   response, in seconds */
X
X
X    /*
X     * SOCKDGRAM is unreliable, so we must repeat messages if we have
X     * not recieved an acknowledgement within a reasonable amount
X     * of time
X     */
X
Xctl_transact(target, msg, type, response)
Xstruct in_addr target;
XCTL_MSG msg;
Xint type;
XCTL_RESPONSE *response;
X{
X    struct sockaddr junk;
X    int read_mask;
X    int ctl_mask;
X    int nready;
X    int cc;
X    int junk_size;
X    struct timeval wait;
X
X    wait.tv_sec = CTL_WAIT;
X    wait.tv_usec = 0;
X
X    msg.type = type;
X
X    daemon_addr.sin_addr = target;
X    daemon_addr.sin_port = daemon_port;
X
X    ctl_mask = 1 << ctl_sockt;
X
X	/*
X	 * keep sending the message until a response of the right
X	 * type is obtained
X	 */
X    do {
X	    /* keep sending the message until a response is obtained */
X
X	do {
X	    cc = sendto(ctl_sockt, (char *)&msg, sizeof(CTL_MSG), 0,
X			&daemon_addr, sizeof(daemon_addr));
X
X	    if (cc != sizeof(CTL_MSG)) {
X		if (errno == EINTR) {
X			/* we are returning from an interupt */
X		    continue;
X		} else {
X		    p_error("Error on write to talk daemon");
X		}
X	    }
X
X	    read_mask = ctl_mask;
X
X	    while ((nready = select(32, &read_mask, 0, 0, &wait)) < 0) {
X		if (errno == EINTR) {
X			/* we are returning from an interupt */
X		    continue;
X		} else {
X		    p_error("Error on waiting for response from daemon");
X		}
X	    }
X	} while (nready == 0);
X
X	    /* keep reading while there are queued messages 
X	       (this is not necessary, it just saves extra
X	       request/acknowledgements being sent)
X	     */
X
X	do {
X
X	    junk_size = sizeof(junk);
X	    cc = recvfrom(ctl_sockt, (char *) response,
X			   sizeof(CTL_RESPONSE), 0, &junk, &junk_size );
X	    if (cc < 0) {
X		if (errno == EINTR) {
X		    continue;
X		}
X		p_error("Error on read from talk daemon");
X	    }
X
X	    read_mask = ctl_mask;
X
X		/* an immediate poll */
X
X	    timerclear(&wait);
X	    nready = select(32, &read_mask, 0, 0, &wait);
X
X	} while ( nready > 0 && response->type != type);
X
X    } while (response->type != type);
X}
END_OF_ctl_transact.c
if test 2210 -ne `wc -c <ctl_transact.c`; then
    echo shar: \"ctl_transact.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f init_disp.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"init_disp.c\"
else
echo shar: Extracting \"init_disp.c\" \(6607 characters\)
sed "s/^X//" >init_disp.c <<'END_OF_init_disp.c'
X#ifndef lint
Xstatic	char sccsid[] = "@(#)init_disp.c 1.1 86/02/05 SMI"; /* from UCB 1.2 83/06/23 */
X#endif
X
X/*
X * init_disp contains the initialization code for the display package,
X * as well as the signal handling routines
X */
X
X#include "talk.h"
X#include <signal.h>
X
Xextern int	ID;
Xint    curses_initialized;
X
X/* 
X * set up curses, catch the appropriate signals, and build the
X * various windows
X */
X
Xinit_disp()
X{	int i, t;
X
X    void sig_sent();
X
X    initscr();
X    curses_initialized = 1;
X
X    clear();
X    refresh();
X
X    noecho();
X    crmode();
X
X    signal(SIGINT, sig_sent);
X    signal(SIGPIPE, sig_sent);
X
X	/* curses takes care of ^Z */
X
X    comwin[0].x_nlines = 4;
X    comwin[0].x_ncols = 15;
X    comwin[0].x_win = newwin(4, 15, 0, 22);
X    
X    comwin[1].x_nlines = 4;
X    comwin[1].x_ncols = 15;
X    comwin[1].x_win = newwin(4, 15, 6, 40);
X    
X    comwin[2].x_nlines = 4;
X    comwin[2].x_ncols = 15;
X    comwin[2].x_win = newwin(4, 15, 13, 22);
X    
X    comwin[3].x_nlines = 4;
X    comwin[3].x_ncols = 15;
X    comwin[3].x_win = newwin(4, 15, 6, 5);
X    
X    comwin[4].x_nlines = 1;
X    comwin[4].x_ncols = 2;
X    comwin[4].x_win = newwin(1, 2, 5, 28);
X    
X    comwin[5].x_nlines = 1;
X    comwin[5].x_ncols = 2;
X    comwin[5].x_win = newwin(1, 2, 8, 35);
X    
X    comwin[6].x_nlines = 1;
X    comwin[6].x_ncols = 2;
X    comwin[6].x_win = newwin(1, 2, 11, 28);
X    
X    comwin[7].x_nlines = 1;
X    comwin[7].x_ncols = 2;
X    comwin[7].x_win = newwin(1, 2, 8, 22);
X    
X    comwin[8].x_nlines = 2;
X    comwin[8].x_ncols = 4;
X    comwin[8].x_win = newwin(2, 4, 1, 7);
X    
X    comwin[9].x_nlines = 3;
X    comwin[9].x_ncols = 11;
X    comwin[9].x_win = newwin(3, 11, 5, 67);
X    
X    comwin[10].x_nlines = 7;
X    comwin[10].x_ncols = 17;
X    comwin[10].x_win = newwin(7, 17, 5, 21);
X    
X    comwin[11].x_nlines = 1;
X    comwin[11].x_ncols = 30;
X    comwin[11].x_win = newwin(1, 30, 1, 50);
X    comwin[12].x_nlines = 1;
X    comwin[12].x_ncols = 40;
X    comwin[12].x_win = newwin(1, 40, 16, 40);
X    
X    comwin[13].x_nlines = 24;
X    comwin[13].x_ncols = 80;
X    comwin[13].x_win = newwin(24, 80, 0, 0);
X    
X    comwin[14].x_nlines = 5;
X    comwin[14].x_ncols = 19;
X    comwin[14].x_win = newwin(5, 19, 18, 0);
X    
X    comwin[15].x_nlines = 5;
X    comwin[15].x_ncols = 19;
X    comwin[15].x_win = newwin(5, 19, 18, 20);
X    
X    comwin[16].x_nlines = 5;
X    comwin[16].x_ncols = 19;
X    comwin[16].x_win = newwin(5, 19, 18, 40);
X    
X    comwin[17].x_nlines = 5;
X    comwin[17].x_ncols = 19;
X    comwin[17].x_win = newwin(5, 19, 18, 60);
X    
X    comwin[18].x_nlines = 1;
X    comwin[18].x_ncols = 20;
X    comwin[18].x_win = newwin(1, 20, 16, 0);
X    for (i=0; i<19; i++){ 
X    	scrollok(comwin[i].x_win, FALSE);
X    	wclear(comwin[i].x_win);
X    };
Xfor (i=14; i<18;++i) scrollok(comwin[i].x_win, TRUE);
X	wmove(comwin[13].x_win, 1, 1);
X	wprintw(comwin[13].x_win, "HAND:");
X	wmove(comwin[13].x_win, 2, 1);
X	wprintw(comwin[13].x_win, "VUL.:");
X	wmove(comwin[13].x_win, 4, 20);
X	wprintw(comwin[13].x_win, "-------------------");
X	wmove(comwin[13].x_win, 5, 20);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 6, 20);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 7, 20);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 8, 20);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 9, 20);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 10, 20);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 11, 20);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 12, 20);
X	wprintw(comwin[13].x_win, "-------------------");
X	wmove(comwin[13].x_win, 5, 38);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 6, 38);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 7, 38);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 8, 38);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 9, 38);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 10, 38);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 11, 38);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 3, 68);
X	wprintw(comwin[13].x_win, "N-S   E-W");
X	wmove(comwin[13].x_win, 4, 67);
X	wprintw(comwin[13].x_win, "----- -----");
X	wmove(comwin[13].x_win, 5, 60);
X	wprintw(comwin[13].x_win, "TRICK:     0     0");
X	wmove(comwin[13].x_win, 6, 60);
X	wprintw(comwin[13].x_win, "SCORE:     0     0");
X	wmove(comwin[13].x_win, 7, 60);
X	wprintw(comwin[13].x_win, "TOTAL:     0     0");
X	wmove(comwin[13].x_win, 9, 55);
X	wprintw(comwin[13].x_win, "ABBREVIATIONS --");
X	wmove(comwin[13].x_win, 10, 57);
X	wprintw(comwin[13].x_win, "P:PASS     N:NO TRUMP");
X	wmove(comwin[13].x_win, 11, 57);
X	wprintw(comwin[13].x_win, "S:SPADE    H:HEART");
X	wmove(comwin[13].x_win, 12, 57);
X	wprintw(comwin[13].x_win, "D:DIAMOND  C:CLUB,");
X	wmove(comwin[13].x_win, 13, 57);
X	wprintw(comwin[13].x_win, "X:DOUBLE  XX:REDOUBLE");
X	wmove(comwin[13].x_win, 14, 57);
X	wprintw(comwin[13].x_win, "T:10      F#:Finish");
X	wmove(comwin[13].x_win, 17,0);
X	wprintw(comwin[13].x_win, "--------------------------------------------------------------------------------");
X	wmove(comwin[13].x_win, 18,19);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 18,39);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 18,59);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 19,19);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 19,39);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 19,59);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 20,19);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 20,39);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 20,59);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 21,19);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 21,39);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 21,59);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 22,19);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 22,39);
X	wprintw(comwin[13].x_win, "|");
X	wmove(comwin[13].x_win, 22,59);
X	wprintw(comwin[13].x_win, "|");
X	wrefresh(comwin[13].x_win);
X
X    current_state = "No connection yet";
X}
X
Xvoid sig_sent()
X{
X    message("Connection closing. Exiting");
X    quit();
X}
X
X/*
X * All done talking...hang up the phone and reset terminal thingy's
X */
X
Xquit()
X{       int i;
X
X	if (curses_initialized) {
X	    for (i=0; i<3; i++){
X 	      wmove(comwin[i].x_win, comwin[i].x_nlines-1, 0);
X	       wclrtoeol(comwin[i].x_win);
X	       wrefresh(comwin[i].x_win);
X	    };
X	    endwin();
X	}
X
X	if (invitation_waiting) {
X	    send_delete();
X	}
X
X	exit(0);
X}
END_OF_init_disp.c
if test 6607 -ne `wc -c <init_disp.c`; then
    echo shar: \"init_disp.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f invite.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"invite.c\"
else
echo shar: Extracting \"invite.c\" \(3759 characters\)
sed "s/^X//" >invite.c <<'END_OF_invite.c'
X#ifndef lint
Xstatic	char sccsid[] = "@(#)invite.c 1.1 86/02/05 SMI"; /* from UCB 1.7 83/07/06 */
X#endif
X
X#include "talk_ctl.h"
X#include <sys/time.h>
X#include <signal.h>
X#include <setjmp.h>
X    
X    /*
X     * there wasn't an invitation waiting, so send a request containing
X     * our sockt address to the remote talk daemon so it can invite
X     * him 
X     */
X
Xint local_id, remote_id;	/* the msg.id's for the invitations
X				   on the local and remote machines.
X				   These are used to delete the 
X				   invitations. */
Xvoid re_invite();
Xjmp_buf	invitebuf;
X
Xinvite_remote()
X{
X    int nfd, read_mask, template, new_sockt;
X    struct itimerval itimer;
X    CTL_RESPONSE response;
X
X    itimer.it_value.tv_sec = RING_WAIT;
X    itimer.it_value.tv_usec = 0;
X    itimer.it_interval = itimer.it_value;
X
X    if (listen(sockt, 5) != 0) {
X	p_error("Error on attempt to listen for caller");
X    }
X
X    msg.addr = my_addr;
X    msg.id_num = -1;		/* an impossible id_num */
X
X    invitation_waiting = 1;
X
X    announce_invite();
X
X	/*
X	 * shut off the automatic messages for a while,
X	 * so we can use the interupt timer to resend the invitation
X	 */
X
X    setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
X    message("Waiting for your party to respond");
X    signal(SIGALRM, re_invite);
X    (void) setjmp(invitebuf);
X
X    while ((new_sockt = accept(sockt, 0, 0)) < 0) {
X	if (errno != EINTR) {
X	    p_error("Unable to connect with your party");
X	} else {
X	    /* we just returned from a interupt, keep trying */
X	    continue;
X	}
X    }
X
X    close(sockt);
X    sockt = new_sockt;
X
X	/* have the daemons delete the invitations now that we
X	   have connected.
X	 */
X
X    current_state = "Waiting for your party to respond";
X
X    msg.id_num = local_id;
X    ctl_transact(my_machine_addr, msg, DELETE, &response);
X    msg.id_num = remote_id;
X    ctl_transact(his_machine_addr, msg, DELETE, &response);
X    invitation_waiting = 0;
X}
X
X    /* routine called on interupt to re-invite the callee */
X
Xvoid re_invite()
X{
X    message("Ringing your party again");
X    current_line++;
X	/* force a re-announce */
X    msg.id_num = remote_id + 1;
X    announce_invite();
X    longjmp(invitebuf, 1);
X}
X
X    /* transmit the invitation and process the response */
X
Xannounce_invite()
X{
X    CTL_RESPONSE response;
X
X    current_state = "Trying to connect to your party's talk daemon";
X
X    ctl_transact(his_machine_addr, msg, ANNOUNCE, &response);
X    remote_id = response.id_num;
X
X    if (response.answer != SUCCESS) {
X
X	switch (response.answer) {
X	    
X	    case NOT_HERE :
X		message("Your party is not logged on");
X		break;
X
X	    case MACHINE_UNKNOWN :
X		message("Target machine does not recognize us");
X		break;
X
X	    case UNKNOWN_REQUEST :
X		message("Target machine can not handle remote talk");
X		break;
X
X	    case FAILED :
X		message("Target machine is too confused to talk to us");
X		break;
X
X	    case PERMISSION_DENIED :
X		message("Your party is refusing messages");
X		break;
X	}
X
X	quit();
X    }
X
X	/* leave the actual invitation on my talk daemon */
X
X    ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response);
X    local_id = response.id_num;
X}
X    
Xsend_delete()
X{
X	/* tell the daemon to remove your invitation */
X
X    msg.type = DELETE;
X
X	/* this is just a extra clean up, so just send it
X	   and don't wait for an answer */
X
X    msg.id_num = remote_id;
X    daemon_addr.sin_addr = his_machine_addr;
X    if (sendto(ctl_sockt, &msg, sizeof(CTL_MSG), 0, &daemon_addr,
X		    sizeof(daemon_addr)) != sizeof(CTL_MSG)) {
X	    perror("send_delete remote");
X    }
X
X    msg.id_num = local_id;
X    daemon_addr.sin_addr = my_machine_addr;
X    if (sendto(ctl_sockt, &msg, sizeof(CTL_MSG), 0, &daemon_addr,
X		    sizeof(daemon_addr)) != sizeof(CTL_MSG)) {
X	    perror("send_delete local");
X    }
X}
END_OF_invite.c
if test 3759 -ne `wc -c <invite.c`; then
    echo shar: \"invite.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f look_up.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"look_up.c\"
else
echo shar: Extracting \"look_up.c\" \(3343 characters\)
sed "s/^X//" >look_up.c <<'END_OF_look_up.c'
X#ifndef lint
Xstatic	char sccsid[] = "@(#)look_up.c 1.1 86/02/05 SMI"; /* from UCB 1.2 83/03/28 */
X#endif
X
X#include "talk_ctl.h"
X
X    /* see if the local daemon has a invitation for us */
X
XCTL_RESPONSE swapresponse();
X
Xcheck_local()
X{
X    CTL_RESPONSE response;
X
X	/* the rest of msg was set up in get_names */
X
X    msg.ctl_addr = ctl_addr;
X
X    if (!look_for_invite(&response)) {
X
X	    /* we must be initiating a talk */
X
X	return(0);
X    }
X
X        /*
X	 * there was an invitation waiting for us, 
X	 * so connect with the other (hopefully waiting) party 
X	 */
X
X    current_state = "Waiting to connect with caller";
X
X    response = swapresponse(response);
X    while (connect(sockt, &response.addr, sizeof(response.addr)) != 0) {
X	if (errno == ECONNREFUSED) {
X
X		/* the caller gave up, but his invitation somehow
X		 * was not cleared. Clear it and initiate an 
X		 * invitation. (We know there are no newer invitations,
X		 * the talkd works LIFO.)
X		 */
X
X	    ctl_transact(his_machine_addr, msg, DELETE, &response);
X	    close(sockt);
X	    open_sockt();
X	    return(0);
X	} else if (errno == EINTR) {
X		/* we have returned from an interupt handler */
X	    continue;
X	} else {
X	    p_error("Unable to connect with initiator");
X	}
X    }
X
X    return(1);
X}
X
X    /* look for an invitation on 'machine' */
X
Xlook_for_invite(response)
XCTL_RESPONSE *response;
X{
X    struct in_addr machine_addr;
X
X    current_state = "Checking for invitation on caller's machine";
X
X    ctl_transact(his_machine_addr, msg, LOOK_UP, response);
X
X	/* the switch is for later options, such as multiple 
X	   invitations */
X
X    switch (response->answer) {
X
X	case SUCCESS:
X
X	    msg.id_num = response->id_num;
X	    return(1);
X
X	default :
X		/* there wasn't an invitation waiting for us */
X	    return(0);
X    }
X}
X
X/*  
X * heuristic to detect if need to reshuffle CTL_RESPONSE structure
X */
X
X#define swapshort(a) (((a << 8) | ((unsigned short) a >> 8)) & 0xffff)
X#define swaplong(a) ((swapshort(a) << 16) | (swapshort(((unsigned)a >> 16))))
X
X#ifdef sun
Xstruct ctl_response_vax {
X	char type;
X	char answer;
X	short junk;
X	int id_num;
X	struct sockaddr_in addr;
X};
X
XCTL_RESPONSE
Xswapresponse(rsp)
X	CTL_RESPONSE rsp;
X{
X	struct ctl_response_vax swaprsp;
X	
X	if (rsp.addr.sin_family != AF_INET) {
X		bcopy(&rsp, &swaprsp, sizeof(CTL_RESPONSE));
X		swaprsp.addr.sin_family = swapshort(swaprsp.addr.sin_family);
X		if (swaprsp.addr.sin_family == AF_INET) {
X			rsp.addr = swaprsp.addr;
X			rsp.type = swaprsp.type;
X			rsp.answer = swaprsp.answer;
X			rsp.id_num = swaplong(swaprsp.id_num);
X		}
X	}
X	return rsp;
X}
X#endif
X
X#ifdef vax
Xstruct ctl_response_sun {
X	char type;
X	char answer;
X	unsigned short id_num2;
X	unsigned short id_num1;
X	short sin_family;
X	short sin_port;
X	short sin_addr2;
X	short sin_addr1;
X};
X
XCTL_RESPONSE
Xswapresponse(rsp)
X	CTL_RESPONSE rsp;
X{
X	struct ctl_response_sun swaprsp;
X	
X	if (rsp.addr.sin_family != AF_INET) {
X		bcopy(&rsp, &swaprsp, sizeof(struct ctl_response_sun));
X		if (swaprsp.sin_family == swapshort(AF_INET)) {
X			rsp.type = swaprsp.type;
X			rsp.answer = swaprsp.answer;
X			rsp.id_num = swapshort(swaprsp.id_num1)
X			    | (swapshort(swaprsp.id_num2) << 16);
X			rsp.addr.sin_family = swapshort(swaprsp.sin_family);
X			rsp.addr.sin_port = swaprsp.sin_port;
X			rsp.addr.sin_addr.s_addr =
X			    swaprsp.sin_addr2 | (swaprsp.sin_addr1 << 16);
X		}
X	}
X	return rsp;
X}
X#endif
END_OF_look_up.c
if test 3343 -ne `wc -c <look_up.c`; then
    echo shar: \"look_up.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f master_io.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"master_io.c\"
else
echo shar: Extracting \"master_io.c\" \(4055 characters\)
sed "s/^X//" >master_io.c <<'END_OF_master_io.c'
X#ifndef lint
Xstatic	char sccsid[] = "@(#)io.c 1.1 86/02/05 SMI"; /* from UCB 1.3 83/07/06 */
X#endif
X
X/* this file contains the I/O handling and the exchange of 
X   edit characters. This connection itself is established in
X   ctl.c
X */
X
X#include "talk.h"
X#include <stdio.h>
X#include <errno.h>
X#include <sys/time.h>
X
X#define A_LONG_TIME 10000000
X#define STDIN_MASK (1<<fileno(stdin))	/* the bit mask for standard
X					   input */
Xextern int errno;
Xextern int INPORT, OUTPORT, OUTEND;
X
X/*
X * The routine to do the actual talking
X */
X
Xtalk()
X{
X    register int read_template, sockt_mask, inportmask;
X    BMSG	buf;
X    char string[10],ch;
X    int read_set, nb,flag,nbuf=sizeof buf;
X    struct timeval wait;
X
X    current_line = 0;
X
X    sockt_mask = (1<<sockt);
X    inportmask = (1<<INPORT);
X
X	/*
X	 * wait on both the other process (sockt_mask) and 
X	 * standard input ( STDIN_MASK )
X	 */
X
X    read_template = sockt_mask | inportmask;
X
X    forever {
X
X	read_set = read_template;
X
X	wait.tv_sec = 100000;
X	wait.tv_usec = 0;
X
X	select(32, &read_set, 0, 0, &wait);
X
X	if ( read_set & sockt_mask ) { 
X
X		/* There is data on sockt */
X	    nb=read(sockt,&buf,nbuf);
X	    if(nb==nbuf)write(OUTPORT, &buf, nbuf);
X	}
X	
X	if ( read_set & inportmask ) {
X
X		/* we can't make the tty non_blocking, because
X		   curses's output routines would screw up */
X	    nb=read(INPORT,&buf,nbuf);
X	    if(nb==nbuf)write(sockt, &buf, nbuf);
X	}
X    }
X}
X
Xextern int	errno;
Xextern int	sys_nerr;
Xextern char	*sys_errlist[];
X
X    /* p_error prints the system error message on the standard location
X       on the screen and then exits. (i.e. a curses version of perror)
X     */
X
Xp_error(string) 
Xchar *string;
X{
X    char *sys;
X
X    sys = "Unknown error";
X    if(errno < sys_nerr) {
X	sys = sys_errlist[errno];
X    }
X
X
X    printf("[%s : %s (%d)]\n", string, sys, errno);
X    quit();
X}
X
X    /* display string in the standard location */
X
Xmessage(string)
Xchar *string;
X{
X}
Xtalk1()
X{	char	ch,ins[2][40];
X	static char *im[2]={"Conversation","Input       "};
X	int	rtn, i, ityp,iwn,wn, row, col, readmask,read_template;
X	int	inport_mask,read_set;
X	BMSG	buf;
X	int	ki[2],nb,nbuf=sizeof buf;
X	struct	timeval wait;
X
X	ityp=1;iwn=12;ki[0]=ki[1]=0;
X	wmove(comwin[18].x_win,0,0);
X	wprintw(comwin[18].x_win,"%s",im[ityp]);
X	wrefresh(comwin[18].x_win);
X	inport_mask=(1<<INPORT);
X	read_template=inport_mask | STDIN_MASK;
X	forever {
X		read_set=read_template;
X		wait.tv_sec=100000;
X		wait.tv_usec=0;
X		select(32,&read_set,0,0,&wait);
X		if(read_set&inport_mask){
X			nb=read(INPORT,&buf,nbuf);
X		    if(nb==nbuf){
X			wn=WN;row=ROW;col=COL;
X			if(row<80) wmove(comwin[wn].x_win,row,col);
X                        if(wn<14&&STR[0]=='\\'){
X                             TYPE=64;write(OUTPORT,&buf,nbuf);
X                             endwin();exit();}
X			if(STR[0]=='Z'|wn==12) wclear(comwin[wn].x_win);
X                        if(STR[0]!='Z') wprintw(comwin[wn].x_win,"%s",STR);
X			wrefresh(comwin[wn].x_win);
X		    }
X		}
X		if(read_set&STDIN_MASK){
X			read(0,&ch,1);
X                        if(ityp==1&&ch=='\\') {
X                             TYPE=64;write(OUTPORT,&buf,nbuf);
X                             write(OUTEND,&ch,1);endwin();exit();}
X			if(ityp==1&&ch<='z'&&ch>='a') ch&=223;
X			switch(ch){
X			     case 27:   ityp=1-ityp;iwn=28-iwn;
X					wmove(comwin[18].x_win,0,0);
X					wprintw(comwin[18].x_win,"%s",im[ityp]);
X					wrefresh(comwin[18].x_win);
X					break;
X			     case '\b': if(ki[ityp]>0){
X						ki[ityp]--;
X						waddch(comwin[iwn].x_win,ch);
X						wrefresh(comwin[iwn].x_win);
X					}
X					break;
X			     default:   ins[ityp][ki[ityp]++]=ch;
X					waddch(comwin[iwn].x_win,ch);
X					wrefresh(comwin[iwn].x_win);
X					
X			}
X			if(ki[ityp]>=comwin[iwn].x_ncols-1&&ch!='\n'){
X				ch='\n';ins[ityp][ki[ityp]++]=ch;
X				waddch(comwin[iwn].x_win,ch);
X				wrefresh(comwin[iwn].x_win);
X			}
X			if(ch=='\n'){
X				if(ityp){wclear(comwin[iwn].x_win);
X					 wrefresh(comwin[iwn].x_win);}
X				TYPE=ityp;ins[ityp][ki[ityp]]='\0';
X				ROW=81;ki[ityp]=0;
X				strcpy(STR,ins[ityp]);
X				write(OUTPORT,&buf,nbuf);
X			}
X		}
X	}
X}
X
END_OF_master_io.c
if test 4055 -ne `wc -c <master_io.c`; then
    echo shar: \"master_io.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f master_talk.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"master_talk.c\"
else
echo shar: Extracting \"master_talk.c\" \(4015 characters\)
sed "s/^X//" >master_talk.c <<'END_OF_master_talk.c'
X#include	<errno.h>
X#include	<signal.h>
X#include	<stdio.h>
X#include	"talk.h"
X#include	<sys/time.h>
X
Xextern	int	errno;
Xxwin_t comwin[19];
Xint	inport[5], outport[5], pid[5];
Xint	INPORT, OUTPORT, ID;
Xint     INEND,OUTEND;
Xchar	player[4][20];
Xchar	*getlogin(),*cp;
Xchar *current_state;
Xlong 	seed;
Xstruct timeval wait;
Xint	readmask;
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{	int	fides1[2], fides2[2],endpipe[2];
X	int	i,j, rtn, nb ,wp,read_set,read_template;
X	char	ins[40],ch;
X    BMSG	buf;
X	int nbuf=sizeof buf;
X    struct sgttyb tty;
X    struct ltchars ltc;
X    struct timeval wait;
X	int	inmask[4], sinmask, readmask, readtmp,intyp;
X	char	inp[40],*cp,tbuf[10];
X
X	time(&seed);
X        pipe(endpipe);
X	for (i=0; i<=4; i++){
X		rtn = pipe(fides1);
X		if (rtn == -1){
X		    printf("Error in pipe1, errno = %d\n", errno);
X		    exit(-1);
X		};
X
X		rtn = pipe(fides2);
X		if (rtn == -1){
X		    printf("Error in pipe2, errno = %d\n", errno);
X		    exit(-1);
X		};
X
X		for (pid[i]=fork(); pid[i]<0;pid[i]=fork());
X		if (pid[i] == 0){
X		    ID = i;
X		    INPORT = fides1[0];
X		    OUTPORT = fides2[1];
X			switch(i){
X                     	   case 4: INEND=endpipe[0];
X                                   bridge();
X				   exit();
X                           case 3: OUTEND=endpipe[1];
X                                   init_disp();
X				   talk1();
X                                   exit();
X                           case 2:
X                           case 1:
X                           case 0:
X		    		   comm(2, &argv[i]);
X		    		   exit();
X			}
X		};
X		inport[i] = fides2[0];
X		outport[i] = fides1[1];
X                cp=(char *)player[i];cp+=2;
X		if(i==3)strncpy(cp, getlogin(), 6);
X		if (i<3){strncpy(cp, argv[i+1], 6);
X			do{
X			rtn = read(inport[i], tbuf, 10);
X			}while(rtn <= 1);
X		}
X	};
X	read_template=0; wp=0; ins[0]=ins[1]=ins[2]=0;
X	for(i=0;i<=4;++i){read_template|=(1<<inport[i]);}
X	forever{
X		read_set=read_template;
X		wait.tv_sec=100000;
X		select(32,&read_set,0,0,&wait);
X		for(i=0;i<=3;++i){
X			if(!(read_set&(1<<inport[i]))) continue;
X			nb=read(inport[i],&buf,nbuf);
X			if(nb==nbuf){
X                        if(TYPE==64)exit();
X			if(TYPE){
X				if(!(wp&(1<<i))) continue;
X				wp-=(1<<i);
X				for(j=0;j<=2;++j) ins[j]|=STR[j];
X			}
X			else{
X				for(j=0;j<=3;++j){
X					WN=14+(j-i+6)%4;
X					if(i!=j){
X					  write(outport[j],&buf,sizeof buf);
X					}
X				}
X			}
X			}
X		}
X		if(read_set&(1<<inport[4])){
X			nb=read(inport[4],&buf,nbuf);
X			if(nb==nbuf){
X			intyp=TYPE;
X			for(i=0;i<=3;++i){
X				if(TYPE&(1<<i)) write(outport[i],&buf,nbuf);
X			}
X			if(TYPE>15) wp=TYPE&15; else wp=0;
X                        ins[0]=ins[1]=ins[2]=0;
X			}
X		}
X		if(intyp<32&&intyp>15 && wp ==0){ 
X			strncpy(STR,ins,3);
X			write(outport[4],&buf,nbuf);intyp=0;}
X		if(intyp>31&&((intyp&15)^wp)){ 
X			write(outport[4],&buf,nbuf);intyp=0;}
X	}
X}
X
Xcomm(argc, argv)
Xint argc;
Xchar *argv[];
X{	char	string[10];
X
X	get_names(argc, argv);
X
X
X	open_ctl();
X	open_sockt();
X	start_msgs();
X
X	if ( !check_local() ) {
X	    invite_remote();
X	}
X
X	end_msgs();
X	write(OUTPORT, string, 10);
X
X	talk();
X}
X 
X 
Xrsend(p, ww, rr, cc, s)
Xint	p, ww, rr, cc;
Xchar	*s;
X{	BMSG	buf;
X	int	nbuf = sizeof buf, rtn;
X	char	w, r, c;
X
X	w = ww; r = rr; c = cc;
X		WN = w; ROW = r; COL = c; TYPE = p; strcpy(STR, s);
X		rtn = write(OUTPORT, &buf, nbuf);
X		if (rtn <= 0){
X			printf("lost pipe write %d, %d", p, errno);
X			exit();
X		};
X}
X
Xrput(p,w,r,c,s)
Xint p,w,r,c;
Xchar *s;
X{
X   rsend(1<<p,w,r,c,s);
X}
X
Xrwait(p, s, t)
Xint	p;
Xlong	t;
Xchar	*s;
X{
X	char	ch;
X	int	readset=0,rtn;
X	struct	timeval	wait;
X	BMSG	buf;
X
X	if(t<100)p+=16;
X	rsend(p+16,12,0,0,s);
X	wait.tv_sec=0;
X	readset=(1<<INPORT);
X	while(select(32,&readset,0,0,&wait)>0){
X		wait.tv_sec=0;
X		read(INPORT,&buf,sizeof buf);
X		readset=(1<<INPORT);
X	}
X	wait.tv_sec=t;
X	wait.tv_usec=0;
X	readset=(1<<INPORT)|(1<<INEND);
X	rtn=select(32,&readset,0,0,&wait);
X	if (rtn>0){
X                if(readset&(1<<INEND)) exit();
X		read(INPORT,&buf,sizeof buf);
X		strncpy(s,STR,3);
X	}
X	return(rtn);
X}	
X
Xrget(p, s)
Xint	p;
Xchar	*s;
X{
X	rwait(p,s,99999);
X}
END_OF_master_talk.c
if test 4015 -ne `wc -c <master_talk.c`; then
    echo shar: \"master_talk.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f msgs.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"msgs.c\"
else
echo shar: Extracting \"msgs.c\" \(922 characters\)
sed "s/^X//" >msgs.c <<'END_OF_msgs.c'
X#ifndef lint
Xstatic	char sccsid[] = "@(#)msgs.c 1.1 86/02/05 SMI"; /* from UCB 1.4 83/07/06 */
X#endif
X
X/* 
X * a package to display what is happening every MSG_INTERVAL seconds
X * if we are slow connecting.
X */
X
X#include <signal.h>
X#include <stdio.h>
X#include <sys/time.h>
X#include "talk.h"
X
X#define MSG_INTERVAL 4
X#define LONG_TIME 100000
X
Xchar *current_state;
Xint current_line = 0;
X
Xstatic struct itimerval itimer;
Xstatic struct timeval wait = { MSG_INTERVAL , 0};
Xstatic struct timeval undo = { LONG_TIME, 0};
X    
X
Xdisp_msg()
X{
X    message(current_state);
X}
X
Xstart_msgs()
X{
X    message(current_state);
X    signal(SIGALRM, disp_msg);
X    itimer.it_value = itimer.it_interval = wait;
X    setitimer(ITIMER_REAL, &itimer, (struct timerval *)0);
X}
X
Xend_msgs()
X{
X    signal(SIGALRM, SIG_IGN);
X    timerclear(&itimer.it_value);
X    timerclear(&itimer.it_interval);
X    setitimer(ITIMER_REAL, &itimer, (struct timerval *)0);
X}
END_OF_msgs.c
if test 922 -ne `wc -c <msgs.c`; then
    echo shar: \"msgs.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f slave_io.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"slave_io.c\"
else
echo shar: Extracting \"slave_io.c\" \(2340 characters\)
sed "s/^X//" >slave_io.c <<'END_OF_slave_io.c'
X#include "talk.h"
X#include <stdio.h>
X#include <errno.h>
X#include <sys/time.h>
X
X#define A_LONG_TIME 10000000
X#define STDIN_MASK (1<<fileno(stdin))	/* the bit mask for standard
X					   input */
Xextern int errno;
X
X/*
X * The routine to do the actual talking
X */
X
X
Xtalk()
X{	char	ch,ins[2][40];
X	static char *im[2]={"Conversation","Input       "};
X	int	rtn, i, ityp,iwn,wn, row, col, readmask,read_template;
X	int	sockt_mask,read_set;
X	BMSG	buf;
X	int	ki[2],nb,nbuf=sizeof buf;
X	struct	timeval wait;
X
X	ityp=1;iwn=12;ki[0]=ki[1]=0;
X	wmove(comwin[18].x_win,0,0);
X	wprintw(comwin[18].x_win,"%s",im[ityp]);
X	wrefresh(comwin[18].x_win);
X	sockt_mask=(1<<sockt);
X	read_template=sockt_mask | STDIN_MASK;
X	forever {
X		read_set=read_template;
X		wait.tv_sec=100000;
X		wait.tv_usec=0;
X		select(32,&read_set,0,0,&wait);
X		if(read_set&sockt_mask){
X			nb=read(sockt,&buf,nbuf);
X		    if(nb==nbuf){
X			wn=WN;row=ROW;col=COL;
X			if(row<80) wmove(comwin[wn].x_win,row,col);
X                        if(wn<14&&STR[0]=='\\'){endwin();exit();}
X			if(STR[0]=='Z'|wn==12) wclear(comwin[wn].x_win);
X                        if(STR[0]!='Z') wprintw(comwin[wn].x_win,"%s",STR);
X			wrefresh(comwin[wn].x_win);
X		    }
X		}
X		if(read_set&STDIN_MASK){
X			read(0,&ch,1);
X			if(ityp==1&&ch<='z'&&ch>='a') ch&=223;
X			switch(ch){
X			     case 27:   ityp=1-ityp;iwn=28-iwn;
X					wmove(comwin[18].x_win,0,0);
X					wprintw(comwin[18].x_win,"%s",im[ityp]);
X					wrefresh(comwin[18].x_win);
X					break;
X			     case '\b': if(ki[ityp]>0){
X						ki[ityp]--;
X						waddch(comwin[iwn].x_win,ch);
X						wrefresh(comwin[iwn].x_win);
X					}
X					break;
X			     default:   ins[ityp][ki[ityp]++]=ch;
X					waddch(comwin[iwn].x_win,ch);
X					wrefresh(comwin[iwn].x_win);
X					
X			}
X			if(ki[ityp]>=comwin[iwn].x_ncols-1&&ch!='\n'){
X				ch='\n';ins[ityp][ki[ityp]++]=ch;
X				waddch(comwin[iwn].x_win,ch);
X				wrefresh(comwin[iwn].x_win);
X			}
X			if(ch=='\n'){
X				if(ityp){wclear(comwin[iwn].x_win);
X					 wrefresh(comwin[iwn].x_win);}
X				TYPE=ityp;ins[ityp][ki[ityp]]='\0';
X				ROW=81;ki[ityp]=0;
X				strcpy(STR,ins[ityp]);
X				write(sockt,&buf,nbuf);
X			}
X		}
X	}
X}
X
X
Xp_error(string) 
Xchar *string;
X{
X    char *sys;
X
X    sys = "Unknown error";
X
X
X    printf("[%s : %s (%d)]\n", string, sys, errno);
X    quit();
X}
X
X    /* display string in the standard location */
X
Xmessage(string)
Xchar *string;
X{
X}
END_OF_slave_io.c
if test 2340 -ne `wc -c <slave_io.c`; then
    echo shar: \"slave_io.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
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