[comp.sources.games] v03i090: cchess - corrispondence chess, Part05/05

games-request@tekred.TEK.COM (03/02/88)

Submitted by: Jan Wolter <janc@crim.eecs.umich.edu>
Comp.sources.games: Volume 3, Issue 90
Archive-name: cchess/Part05

#! /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 5 (of 5)."
# Contents:  def.h reap.c
# Wrapped by billr@tekred on Tue Jan 12 12:09:57 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f def.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"def.h\"
else
echo shar: Extracting \"def.h\" \(10411 characters\)
sed "s/^X//" >def.h <<'END_OF_def.h'
X/*	C O R R E S P O N D E N C E   C H E S S			Version 1.00
X *
X *	These are the defines for cchess.
X *
X *	(C) Apr 1986 - Jan Dithmar Wolter.
X */
X
Xtypedef char boolean;
X
X/* For lint we always turn on the UNCHAR flag */
X#ifdef lint
X#define UNCHAR
X#endif
X
X#ifdef UNCHAR
Xtypedef short schar;
X#else
Xtypedef char schar;
X#endif
X
X#ifdef USYS_5
X#define index	strchr
X#define NODUP2
X#endif
X
X/* SCO seems to have problems with register directives in some situations */
X#ifdef SCO
X#define REGISTER
X#else
X#define REGISTER register
X#endif
X
X/* Handle 4.3bsd as superset of 4.2bsd */
X#ifdef U43BSD
X#define U42BSD
X#endif
X
X/* Fake the 4.2bsd directory routines for non-4.2bsd systems */
X#ifndef U42BSD
X#define DIR		FILE
X#define opendir(n)	fopen(n,"r")
X#define telldir(f)	ftell(f)
X#define seekdir(f,o)	fseek(f,o,0)
X#define rewinddir(f)	rewind(f)
X#define closedir(f)	close(f)
X#endif U42BSD
X
X#define BELL '\007'
X
X#undef TRUE		/* Some systems already define these, here or there */
X#undef FALSE
X#define TRUE 1
X#define FALSE 0
X
X/* Code numbers for pieces */
X
X#define WHITE (schar)  1
X#define BLACK (schar) -1
X
X#define SQ   (schar) 0		/* Blank Square   */
X
X#define WK  (schar)  1		/* White King	   */
X#define WQ  (schar)  2		/* White Queen	   */
X#define WB  (schar)  3		/* White Bishop	   */
X#define WN  (schar)  4		/* White Knight	   */
X#define WR  (schar)  5		/* White Rook	   */
X#define WP  (schar)  6		/* White Pawn	   */
X#define WM  (schar)  7		/* White Minister  */
X#define WE  (schar)  8		/* White Elephant  */
X#define WD  (schar)  9		/* White Duke      */
X#define WJ  (schar)  10		/* White Jester    */
X#define WH  (schar)  11		/* White Maharajah */
X
X#define BK  (schar) -1		/* Black King	   */
X#define BQ  (schar) -2		/* Black Queen	   */
X#define BB  (schar) -3		/* Black Bishop	   */
X#define BN  (schar) -4		/* Black Knight	   */
X#define BR  (schar) -5		/* Black Rook	   */
X#define BP  (schar) -6		/* Black Pawn	   */
X#define BM  (schar) -7		/* Black Minister  */
X#define BE  (schar) -8		/* Black Elephant  */
X#define BD  (schar) -9		/* Black Duke      */
X#define BJ  (schar) -10		/* Black Jester    */
X#define BH  (schar) -11		/* White Maharajah */
X
X#define XX  (schar) 99		/* Goofy piece used as place holder */
X
X#define PIECES 11
X
X/* Definition of options in "option" array */
X
X#define OP_COLOR	 0			/* Is first player white? */
X#define Firstwhite	option[OP_COLOR]
X#define HI_COLOR	TRUE
X
X#define OP_PRIVATE	 1			/* Is game Private? */
X#define Private		option[OP_PRIVATE]
X#define HI_PRIVATE	TRUE
X
X#define OP_KIBITZ	 2			/* Computer Kibitzing */
X#define Help_me		option[OP_KIBITZ]
X#define HI_KIBITZ	TRUE
X
X#define OP_GAME		 3			/* Major Variant */
X#define Game_type	option[OP_GAME]
X#define TY_MIXED	 0
X#define TY_CHESS	 1
X#define TY_KRIEGSPIEL	 2
X#define TY_SHATRANJ	 3
X#define TY_COURIER	 4
X#define TY_HALFBOARD	 5
X#define TY_KARMA	 6
X#define TY_RIFLE	 7
X#define TY_KAMIKAZI	 8
X#define TY_DOUBLE	 9
X#define TY_STEAMROLLER	10
X#define TY_PROGRESSIVE	11
X#define TY_MAHARAJAH	12
X#define TY_LOSING	13
X#define TY_CONVERSION	14
X#define HI_GAME		14
X
X#define OP_ROWS		 4			/* Board Rows minus 1 */
X#define Rows		option[OP_ROWS]
X#define HI_ROWS		 7
X
X#define OP_COLS		 5			/* Board Columns minus 1 */
X#define Cols		option[OP_COLS]
X#define HI_COLS		11
X
X#define OP_BOARD	 6			/* Is board uncheckered? */
X#define Plain		option[OP_BOARD]
X#define HI_BOARD	TRUE
X
X#define OP_NAMES	 7			/* Which names for pieces */
X#define Language	option[OP_NAMES]
X#define LG_ENGLISH	 0			/* English */
X#define LG_PERSIAN	 1			/* Persian */
X#define LG_FRENCH	 2			/* French  */
X#define LG_GERMAN	 3			/* German  */
X#define HI_NAMES	 3
X
X#define OP_VISIB	 8			/* Kriegspiel? */
X#define Kriegspiel	option[OP_VISIB]
X#define HI_VISIB	TRUE
X
X#define OP_CASTLE	 9			/* Is castling illegal? */
X#define Oldcastle	option[OP_CASTLE]
X#define HI_CASTLE	 9
X
X#define OP_DPAWN	10			/* Double pawn move illegal? */
X#define Oldpawn		option[OP_DPAWN]
X#define HI_DPAWN	TRUE
X
X#define OP_STRIP	11			/* Result if king is stripped */
X#define Stripresult	option[OP_STRIP]	/*   of all his forces: */
X#define RE_DRAW		 0			/* Game is a draw */
X#define RE_WIN		 1			/* Stripped side wins */
X#define RE_LOSE		 2			/* Stripped side loses */
X#define RE_NONE		 3			/* Game Continues */
X#define RE_CANCEL	 4			/* Game Cancelled */
X#define flip(x)	(((x) == RE_WIN) ? RE_LOSE : (((x) == RE_LOSE) ? RE_WIN : x))
X#define HI_STRIP	 3
X
X#define OP_STALE	12			/* Result of Stalemate */
X#define Staleresult	option[OP_STALE]
X#define HI_STALE	 2
X
X#define OP_CAPTURE	13			/* How do pieces capture? */
X#define Capture		option[OP_CAPTURE]
X#define CA_NORMAL	 0			/* The usual way */
X#define CA_NONE		 1			/* Capture not allowed */
X#define CA_RIFLE	 2			/* Rifle Chess */
X#define CA_CONVERSION	 3			/* Conversion Chess */
X#define CA_KARMA	 4			/* Karma Chess */
X#define CA_KAMIKAZI	 5			/* Kamikazi Chess */
X#define HI_CAPTURE	 5
X
X#define OP_KCAPTURE	14			/* How do kings capture? */
X#define Kcapture	option[OP_KCAPTURE]
X#define HI_KCAPTURE	 3
X
X#define OP_PROMOTE	15			/* What can you promote to? */
X#define Promotion	option[OP_PROMOTE]
X#define PR_QRBN		 0			/* Queen/Rook/Bishop/Knight */
X#define PR_MINISTER	 1			/* Minister Only */
X#define PR_NONE		 2			/* Stays as Pawn */
X#define HI_PROMOTE	 2
X
X#define OP_WIMOVES	16			/* Number of pieces moved on */
X#define Winitmoves	option[OP_WIMOVES]	/*   white's first turn      */
X#define HI_WIMOVES	127
X
X#define OP_BIMOVES	17			/* Number of pieces moved on */
X#define Binitmoves	option[OP_BIMOVES]	/*   black's first turn      */
X#define HI_BIMOVES	127
X
X#define OP_WMOVES	18			/* Number of pieces moved on */
X#define Whitemoves	option[OP_WMOVES]	/*   white's later turns     */
X#define MO_PROGRESS	0			/* Move one more than before */
X#define HI_WMOVES	127
X
X#define OP_BMOVES	19			/* Number of pieces moved on */
X#define Blackmoves	option[OP_BMOVES]	/*   black's later turns     */
X#define HI_BMOVES	127
X
X#define OP_THRUCHECK	20			/* Can king move thru check? */
X#define Thrucheck	option[OP_THRUCHECK]	/*    (relevant in multimove */
X#define HI_THRUCHECK	TRUE			/*     games only)	     */
X
X#define OP_WHITEKING	21			/* Piece which can be checked*/
X#define Whiteking	option[OP_WHITEKING]	/*  (must be a unique piece) */
X#define HI_WHITEKING	PIECES
X
X#define OP_BLACKKING	22			/* Piece which can be checked*/
X#define Blackking	option[OP_BLACKKING]	/*  (must be a unique piece) */
X#define HI_BLACKKING	PIECES
X
X#define OP_MUSTTAKE	23			/* Are captures required?    */
X#define Musttake	option[OP_MUSTTAKE]
X#define HI_MUSTTAKE	TRUE
X
X#define OP_TABIYAT	24			/* Must pieces stay own side */
X#define Tabiyat		option[OP_TABIYAT]	/*   on first turn?	     */
X#define HI_TABIYAT	TRUE
X
X#define OPTIONS		25			/* Number of options defined */
X
X/* King of color c */
X#define Kingtype(c)	((c == WHITE) ? Whiteking : Blackking)
X#define Kingpiece(c)	((c == WHITE) ? Whiteking : -Blackking)
X
X/* Reasons for winning or losing or drawing or cancelling */
X
X#define EV_NOTHING	 0	/* Nothing happened */
X#define EV_CHECKMATE	 1	/* Checkmate */
X#define EV_STALEMATE	 2	/* Stalemate */
X#define EV_FORCES	 3	/* Player lost forces */
X#define EV_AGREEMENT	 4	/* Players agreed to result */
X#define EV_FIFTYMOVES	 5	/* Fifty tame moves */
X#define EV_REPEATED	 6	/* Three times repeated position */
X#define EV_FORFIET	 7	/* Player forfieted */
X
X/* Maximum size of board - actual size is given by variabls Rows and Cols */
X#define R_SIZE HI_ROWS + 1
X#define C_SIZE HI_COLS + 1
X
X/* Macros to find left, right, top and bottom of board */
X#define lside(c) (((c)==BLACK) ? Cols : 0)
X#define rside(c) (((c)==WHITE) ? Cols : 0)
X#define bside(c) (((c)==BLACK) ? Rows : 0)
X#define tside(c) (((c)==WHITE) ? Rows : 0)
X
X/* Macro to decide if piece p is color c, or if p and c are same color (sign) */
X/* #define coloris(p,c) ((p ^ c) & 0200)     not used... */
X
X/* A string of n blanks, n between 0 and BLANK_LEN */
X#define BLANK_LEN 70
X#define blanks(n) (blankstr+BLANK_LEN-(n))
X
X/* Error Codes for bad moves */
X
X#define E_OK	0000	/* no error */
X#define E_MT	0001	/* move from empty square */
X#define E_AF	0002	/* attack on friendly piece */
X#define E_EQ	0003	/* source and destination square are equal */
X#define E_SY	0004	/* Move syntax error */
X#define E_MC	0005	/* Move into Check */
X#define E_NC	0006	/* Pieces in not allowed to capture */
X#define E_MM	0007	/* Check during multiple move */
X#define E_CR	0010	/* A capture was required */
X#define E_CC	0011	/* May not cross center on first move */
X
X#define E_IL	0100	/* Illegal Move */
X#define E_KI	0101	/* Illegal move of King */
X#define E_QI	0102	/* Illegal move of Queen */
X#define E_BI	0103	/* Illegal move of Bishop */
X#define E_NI	0104	/* Illegal move of Knight */
X#define E_RI	0105	/* Illegal move of Rook */
X#define E_PI	0106	/* Illegal move of Pawn */
X#define E_MI	0107	/* Illegal move of Minister */
X#define E_EI	0110	/* Illegal move of Elephant */
X#define E_DI	0111	/* Illegal move of Duke */
X#define E_JI	0112	/* Illegal move of Jester */
X#define E_HI	0113	/* Illegal move of Maharajah */
X
X#define E_CP	0200	/* Illegal castling position */
X#define E_CM	0201	/* Castled moved piece */
X#define E_CT	0202	/* Castled through check */
X
X#define E_MB	0300	/* Blocked move */
X#define E_KB	0301	/* Blocked move of Kamikazi King */
X#define E_QB	0302	/* Blocked move of Queen */
X#define E_BB	0303	/* Blocked move of Bishop */
X#define E_BR	0305	/* Blocked move of Rook */
X#define E_BH	0313	/* Illegal move of Maharajah */
X
X/* Lengths for game transcript file io buffer */
X#define CB_LEN	160		/* Comment buffer length */
X#define MB_LEN	CB_LEN+28	/* Move buffer length */
X
X/* Column positions of things inside game transcript files */
X#define C_DAY	0	/* Day of the year that the line was entered */
X#define C_CMD	6	/* Command letter (Move,Draw,Challenge,etc) */
X#define C_MAT	7	/* Check, Stalemate or Mate */
X#define C_MOV	8	/* Move made */
X#define C_FLG  13	/* Is there a comment? */
X#define C_COM  14	/* Comment text */
X
X/*
X * Number of moves after which to apply the fifty move rule.  This is set up
X * so it is easy to change to some small number for debugging.
X */
X
X#ifndef MAXTAME
X#define MAXTAME 100
X#endif
X
X/* System 3 and System 5 and everything else uses the signal library */
X
X#define LSIGNAL
X
X/* 4.2bsd uses the sigvec library */
X
X#ifdef U42BSD
X#  define UBERK
X#  define LSIGVEC
X#  undef LSIGSYS
X#  undef LSIGNAL
X#endif
X
X/* 4.1bsd uses the sigsys library */
X
X#ifdef U41BSD
X#  define UBERK
X#  define LSIGSYS
X#  undef LSIGVEC
X#  undef LSIGNAL
X#endif
END_OF_def.h
if test 10411 -ne `wc -c <def.h`; then
    echo shar: \"def.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f reap.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"reap.c\"
else
echo shar: Extracting \"reap.c\" \(9189 characters\)
sed "s/^X//" >reap.c <<'END_OF_reap.c'
X/* CCHESS GAME REAPER					Version 1.00 */
X
X/* Note: this reaper is still somewhat experimental */
X
X#include <stdio.h>
X#include <sys/types.h>
X#ifdef U42BSD
X#  include <sys/time.h>
X#else
Xlong time();
X#endif
X#include <pwd.h>
X#include <sys/dir.h>
X
X#include "def.h"
Xstruct direct *readdir();
XFILE *upopen();
X
X/* The following determine the reminder schedule:
X *    at least sched[0] days after a move was made, the player whose turn
X *         it is to move is sent a reminder message.
X *    at least sched[n] (n < MAXREM-2) days after a the last reminder,
X *         the player whose turn it is to move is sent another reminder.
X *    at least sched[MAXREM-2] days after that, both players are sent
X *         mail that the game will be deleted within sched[MAXREM-1]
X *         days.
X *    at least sched[MAXREM-1] days after that, the game is deleted,
X *         and both players are informed of the fact.
X *
X * If the second player has not responded to the initial challenge, he is
X * not sent reminders.  The game is deleted after SNUBKILL days.
X */
X
X#define MAXREM  4
Xint sched[MAXREM] = {4, 7, 7, 5};
X#define SNUBKILL 7
X
X/* EXAMPLES:
X * To delete games without warning after no moves for a week:
X *    #define MAXREM 1
X *    int sched[MEXREM] = {7};
X * To warn of deletion after two weeks, and delete 3 days later:
X *    #define MAXREM 2
X *    int sched[MEXREM] = {14, 3};
X * To remind players once a week for three months and never delete it:
X *    #define MAXREM 14
X *    int sched[MAXREM] = {7,7,7,7, 7,7,7,7, 7,7,7,7, 15000, 1};
X */
X
Xchar rem_msg[] = "Cchess Reminder";
X
Xlong today, day();
Xchar ids[2][9];
Xint toplay;
Xchar *hisid, *myid;
XFILE *fopen();
Xstruct passwd *getpwuid();
X
Xmain()
X{
XDIR *dfp;
Xstruct direct *dirent;
X
X	today = day();
X
X	if ((dfp = opendir(CCDIR)) == NULL)
X		return(0);
X
X	chdir(CCDIR);
X	while((dirent = readdir(dfp)) != NULL)
X	{
X		dofile(dirent->d_name);
X	}
X}
X
Xdofile(name)
Xchar *name;
X{
XFILE *fp;
Xchar buf[512];
Xint code,flag=0;
Xint uid1,uid2;
Xstruct passwd *pwbuf;
X
X	/* Get the uid's of the players */
X	if (sscanf(name,"%d.%d",&uid1,&uid2) != 2)
X		return;
X
X	/* Read the board to see if a reminder is needed */
X	if ((code = readboard(name))==0)
X		return;
X
X	/* Kill one player games first chance we get */
X	if (uid1 == uid2)
X	{
X		killfile(name);
X		return;
X	}
X
X	/* Look up the login names of the players */
X	if ((pwbuf = getpwuid(uid1)) != NULL)
X		strcpy(ids[toplay],pwbuf->pw_name);
X	else
X		flag |= 1;
X
X	if ((pwbuf = getpwuid(uid2)) != NULL)
X		strcpy(ids[1-toplay],pwbuf->pw_name);
X	else
X		flag |= 2;
X
X	/* If either player's account is gone, kill the game */
X	if (flag != 0)
X	{
X		/* Do something nicer here someday */
X		killfile(name);
X		return;
X	}
X
X	hisid = ids[0]; myid = ids[1];
X
X	if (code < MAXREM - 1)
X	{
X		/* Remind the player whose turn it is to move */
X		markfile(name);
X		sprintf(buf,"It's your turn to move in the cchess game between you and %s.\n",myid);
X		mesg(rem_msg,buf);
X	}
X	else if (code == MAXREM - 1)
X	{
X		/* Warn both players that time is short */
X		markfile(name);
X		sprintf(buf,"It's your turn to move in the cchess game between you and %s.\nThe game will be deleted in %d days if no move is made\n",myid,sched[MAXREM-1]);
X		mesg(rem_msg,buf);
X
X		hisid = ids[1]; myid = ids[0];
X
X		sprintf(buf,"%s has not been moving in your cchess game\nThe game will be deleted in %d days if no move is made\n",myid,sched[MAXREM-1]);
X		mesg(rem_msg,buf);
X	}
X	else
X	{
X	    /* Delete the game */
X	    killfile(name);
X	    if (code == MAXREM)
X		sprintf(buf,
X		   "The cchess game between you and %s has been deleted.\n",
X		    myid);
X	    else
X		sprintf(buf,
X		   "The cchess game %s challenged you to has been deleted.\n",
X		    myid);
X	    mesg(rem_msg,buf);
X
X	    hisid = ids[1]; myid = ids[0];
X
X	    if (code == MAXREM)
X		sprintf(buf,
X		   "The cchess game between you and %s has been deleted.\n",
X		   myid);
X	    else
X		sprintf(buf,
X		   "The cchess game you challenged %s to has been deleted.\n",
X		   myid);
X	    mesg(rem_msg,buf);
X	}
X}
X
X/* READBOARD
X *
X *   Read in the file "name" and toplay=0 if the first named player is the
X *   next player, and toplay=1 if the last named player is the next player.
X *   It returns the reminder number if a reminder is due, or 0 if not.  It
X *   returns MAXREM+1 for snubbed games.
X */
X
Xint readboard(name)
Xchar *name;
X{
Xint fw,snubbed;
XFILE *rfp;
Xint reminder;
Xlong date;
Xchar mbuffer[MB_LEN+1];
X
X	if ((rfp = fopen(name,"r")) == NULL)
X		return(0);
X
X	snubbed = 2;
X	reminder = 1;
X	toplay = 0;	/* First player, by definition, does first challenge */
X
X	for (;;)
X	{
X		if (fgets(mbuffer,MB_LEN,rfp)==NULL)
X			break;
X		date = atol(mbuffer+C_DAY);
X
X		switch (mbuffer[C_CMD])
X		{
X		case 'R':
X			reminder++;
X			break;
X		case 'A':
X			/* My move first if Firstwhite */
X			toplay = !fw;
X			reminder=1;
X			snubbed = 0;
X			break;
X		case 'C': /* players alternate counterchallenges */
X			fw = (mbuffer[C_MOV+OP_COLOR] == '1');
X			if (snubbed) snubbed--;
X			toplay = 1-toplay;
X			reminder=1;
X			break;
X		case 'M': case 'D': case 'K': case 'N': case 'Y': case 'F':
X			toplay = 1-toplay;
X		case 'P': case 'm': case 'I': case 'V':
X			reminder=1;
X			break;
X		default:
X			printf("ccreap: strange code in file %s\n",name);
X			fclose(rfp);
X			return(0);
X		}
X	}
X	fclose(rfp);
X
X	if (snubbed)
X		return((today - date > SNUBKILL) ? MAXREM+1 : 0);
X
X	if (reminder > MAXREM)
X		reminder = MAXREM;
X	if (today - date > sched[reminder-1])
X		return(reminder);
X	else
X		return(0);
X}
X
X/* KILLFILE
X *
X *  Delete the named game file.  If debug, just print a message.
X */
Xkillfile(name)
Xchar *name;
X{
X#ifdef DEBUG
X	printf("Delete %s\n",name);
X#else
X	unlink(name);
X#endif DEBUG
X}
X
X/* MARKFILE
X *
X *  Make a note in the game file that a reminder has been sent.
X */
X
Xmarkfile(name)
Xchar *name;
X{
XFILE *wfp;
X
X	if ((wfp = fopen(name,"a")) == NULL)
X		return(0);
X	fprintf(wfp,"%5ld:R\n",today);
X	fclose(wfp);
X}
X
X/**************************************************************************/
X/*	The following routines are mostly stolen from cchess              */
X/**************************************************************************/
X
X/* DAY()
X *
X * Return today's date, in the form of the number of days since Jan 1, 1970.
X * Actually, the 4.2bsd could use the time() call too, but gettimeofday()
X * seems to be prefered.
X */
X
Xlong day()
X{
X#define SECSPERDAY 86400L
X#ifdef U42BSD
Xstruct timeval tp;
Xstruct timezone tzp;
X	gettimeofday(&tp,&tzp);
X	return(tp.tv_sec/SECSPERDAY);
X#else
X	return(time((long *)0)/SECSPERDAY);
X#endif
X}
X
X/* MESG()
X *
X *   Send Mail to the other player.  Use the the given text and subject
X *   heading.  Making this come out right may take some fooling around on
X *   any given system.
X */
X
X/* Choose default mailer */
X#ifndef MAILER
X#  ifdef U41BSD
X#    define MAILER "/etc/delivermail"
X#  else
X#    ifdef U42BSD
X#      define MAILER "/usr/lib/sendmail"
X#    else
X#      define MAILER "/bin/mail"
X#    endif U42BSD
X#  endif U41BSD
X#endif MAILER
X
Xmesg(subj,text)
Xchar *subj, *text;
X{
X#ifdef DEBUG
Xprintf("message to %d: %s\n",hisid, text);
X#else
Xchar cmd[60];
XFILE *cmdfd;
X	
X	sprintf(cmd,"%s %s",MAILER,hisid);
X	cmdfd = upopen(cmd,"w");
X
X#ifdef UBERK
X	fprintf(cmdfd,"To: %s\n",hisid);
X#endif UBERK
X
X	fprintf(cmdfd,"Subject: %s\n\n",subj);
X	fprintf(cmdfd,"%s",text);
X
X	fclose(cmdfd);		/* Don't use pclose -- don't want to wait */
X#endif DEBUG
X}
X
X
X#ifndef U42BSD
X/* READDIR
X *
X *	Here we fake 4.2bsd's readdir() command for older bsd's and at&t
X *	unixs.  The "direct" structure on those systems returned isn't the
X *	same the bsd one, but we do ensure that the file name is null
X *	terminated.  It would be easy enough to add the d_namlen and d_reclen
X *	records and extend d_ino to a long named d_fileno, but I don't
X *	really need that here.
X */
X
Xstruct direct *readdir(fp)
XDIR *fp;
X{
X/* We allocate one extra byte on the end of the structure for the null */
Xstatic char dent[ sizeof(struct direct) + 1 ];
X
X	do
X		if (fread(dent,sizeof(struct direct),1,fp) == 0)
X			return(NULL);
X	while (((struct direct *)dent)->d_ino == 0);
X	((struct direct *)dent)->d_name[DIRSIZ] = '\0';
X	return((struct direct *)dent);
X}
X#endif U42BSD
X
X
X/* UPOPEN - Run command on a pipe
X *
X *    This is just like the Unix popen() call, except it runs the command
X *    with the original user id.  This is done for the same reasons mentioned
X *    in the usystem routine.
X */
X
XFILE *upopen(cmd,mode)
Xchar *cmd;
XREGISTER char *mode;
X{
Xint p[2];
Xregister int chd_pipe,par_pipe;
XFILE *fdopen();
X#ifdef NODUP2
Xint t;
X#endif NODUP2
X
X	/* Make a pipe */
X	if (pipe(p)) return((FILE *)0);
X
X	/* Choose ends */
X	par_pipe = (*mode == 'r') ? p[0] : p[1];
X	chd_pipe = (*mode == 'r') ? p[1] : p[0];
X
X	switch (fork())
X	{
X	case 0:
X		/* Child - run command */
X		close(par_pipe);
X		if (chd_pipe != (*mode == 'r'?1:0))
X		{
X#ifdef NODUP2
X			close(t = (*mode == 'r'?1:0));
X			if (fcntl(chd_pipe,F_DUPFD,t) != t)
X			{
X				printf("Panic: can dup pipe\n");
X				exit(1);
X			}
X#else
X			dup2(chd_pipe,(*mode == 'r'?1:0));
X#endif NODUP2
X			close(chd_pipe);
X		}
X		setuid(getuid());
X		setgid(getgid());
X		execl("/bin/sh","sh","-c",cmd,NULL);
X		exit(1);
X	case -1:
X		close(chd_pipe);
X		close(par_pipe);
X		return((FILE *)0);
X	default:
X		close(chd_pipe);
X		return(fdopen(par_pipe,mode));
X	}
X}
END_OF_reap.c
if test 9189 -ne `wc -c <reap.c`; then
    echo shar: \"reap.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 5 \(of 5\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 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