DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T r

⟦f9a793db6⟧ TextFile

    Length: 9189 (0x23e5)
    Types: TextFile
    Names: »reap.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/General/Cchess/reap.c« 

TextFile

/* CCHESS GAME REAPER					Version 1.00 */

/* Note: this reaper is still somewhat experimental */

#include <stdio.h>
#include <sys/types.h>
#ifdef U42BSD
#  include <sys/time.h>
#else
long time();
#endif
#include <pwd.h>
#include <sys/dir.h>

#include "def.h"
struct direct *readdir();
FILE *upopen();

/* The following determine the reminder schedule:
 *    at least sched[0] days after a move was made, the player whose turn
 *         it is to move is sent a reminder message.
 *    at least sched[n] (n < MAXREM-2) days after a the last reminder,
 *         the player whose turn it is to move is sent another reminder.
 *    at least sched[MAXREM-2] days after that, both players are sent
 *         mail that the game will be deleted within sched[MAXREM-1]
 *         days.
 *    at least sched[MAXREM-1] days after that, the game is deleted,
 *         and both players are informed of the fact.
 *
 * If the second player has not responded to the initial challenge, he is
 * not sent reminders.  The game is deleted after SNUBKILL days.
 */

#define MAXREM  4
int sched[MAXREM] = {4, 7, 7, 5};
#define SNUBKILL 7

/* EXAMPLES:
 * To delete games without warning after no moves for a week:
 *    #define MAXREM 1
 *    int sched[MEXREM] = {7};
 * To warn of deletion after two weeks, and delete 3 days later:
 *    #define MAXREM 2
 *    int sched[MEXREM] = {14, 3};
 * To remind players once a week for three months and never delete it:
 *    #define MAXREM 14
 *    int sched[MAXREM] = {7,7,7,7, 7,7,7,7, 7,7,7,7, 15000, 1};
 */

char rem_msg[] = "Cchess Reminder";

long today, day();
char ids[2][9];
int toplay;
char *hisid, *myid;
FILE *fopen();
struct passwd *getpwuid();

main()
{
DIR *dfp;
struct direct *dirent;

	today = day();

	if ((dfp = opendir(CCDIR)) == NULL)
		return(0);

	chdir(CCDIR);
	while((dirent = readdir(dfp)) != NULL)
	{
		dofile(dirent->d_name);
	}
}

dofile(name)
char *name;
{
FILE *fp;
char buf[512];
int code,flag=0;
int uid1,uid2;
struct passwd *pwbuf;

	/* Get the uid's of the players */
	if (sscanf(name,"%d.%d",&uid1,&uid2) != 2)
		return;

	/* Read the board to see if a reminder is needed */
	if ((code = readboard(name))==0)
		return;

	/* Kill one player games first chance we get */
	if (uid1 == uid2)
	{
		killfile(name);
		return;
	}

	/* Look up the login names of the players */
	if ((pwbuf = getpwuid(uid1)) != NULL)
		strcpy(ids[toplay],pwbuf->pw_name);
	else
		flag |= 1;

	if ((pwbuf = getpwuid(uid2)) != NULL)
		strcpy(ids[1-toplay],pwbuf->pw_name);
	else
		flag |= 2;

	/* If either player's account is gone, kill the game */
	if (flag != 0)
	{
		/* Do something nicer here someday */
		killfile(name);
		return;
	}

	hisid = ids[0]; myid = ids[1];

	if (code < MAXREM - 1)
	{
		/* Remind the player whose turn it is to move */
		markfile(name);
		sprintf(buf,"It's your turn to move in the cchess game between you and %s.\n",myid);
		mesg(rem_msg,buf);
	}
	else if (code == MAXREM - 1)
	{
		/* Warn both players that time is short */
		markfile(name);
		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]);
		mesg(rem_msg,buf);

		hisid = ids[1]; myid = ids[0];

		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]);
		mesg(rem_msg,buf);
	}
	else
	{
	    /* Delete the game */
	    killfile(name);
	    if (code == MAXREM)
		sprintf(buf,
		   "The cchess game between you and %s has been deleted.\n",
		    myid);
	    else
		sprintf(buf,
		   "The cchess game %s challenged you to has been deleted.\n",
		    myid);
	    mesg(rem_msg,buf);

	    hisid = ids[1]; myid = ids[0];

	    if (code == MAXREM)
		sprintf(buf,
		   "The cchess game between you and %s has been deleted.\n",
		   myid);
	    else
		sprintf(buf,
		   "The cchess game you challenged %s to has been deleted.\n",
		   myid);
	    mesg(rem_msg,buf);
	}
}

/* READBOARD
 *
 *   Read in the file "name" and toplay=0 if the first named player is the
 *   next player, and toplay=1 if the last named player is the next player.
 *   It returns the reminder number if a reminder is due, or 0 if not.  It
 *   returns MAXREM+1 for snubbed games.
 */

int readboard(name)
char *name;
{
int fw,snubbed;
FILE *rfp;
int reminder;
long date;
char mbuffer[MB_LEN+1];

	if ((rfp = fopen(name,"r")) == NULL)
		return(0);

	snubbed = 2;
	reminder = 1;
	toplay = 0;	/* First player, by definition, does first challenge */

	for (;;)
	{
		if (fgets(mbuffer,MB_LEN,rfp)==NULL)
			break;
		date = atol(mbuffer+C_DAY);

		switch (mbuffer[C_CMD])
		{
		case 'R':
			reminder++;
			break;
		case 'A':
			/* My move first if Firstwhite */
			toplay = !fw;
			reminder=1;
			snubbed = 0;
			break;
		case 'C': /* players alternate counterchallenges */
			fw = (mbuffer[C_MOV+OP_COLOR] == '1');
			if (snubbed) snubbed--;
			toplay = 1-toplay;
			reminder=1;
			break;
		case 'M': case 'D': case 'K': case 'N': case 'Y': case 'F':
			toplay = 1-toplay;
		case 'P': case 'm': case 'I': case 'V':
			reminder=1;
			break;
		default:
			printf("ccreap: strange code in file %s\n",name);
			fclose(rfp);
			return(0);
		}
	}
	fclose(rfp);

	if (snubbed)
		return((today - date > SNUBKILL) ? MAXREM+1 : 0);

	if (reminder > MAXREM)
		reminder = MAXREM;
	if (today - date > sched[reminder-1])
		return(reminder);
	else
		return(0);
}

/* KILLFILE
 *
 *  Delete the named game file.  If debug, just print a message.
 */
killfile(name)
char *name;
{
#ifdef DEBUG
	printf("Delete %s\n",name);
#else
	unlink(name);
#endif DEBUG
}

/* MARKFILE
 *
 *  Make a note in the game file that a reminder has been sent.
 */

markfile(name)
char *name;
{
FILE *wfp;

	if ((wfp = fopen(name,"a")) == NULL)
		return(0);
	fprintf(wfp,"%5ld:R\n",today);
	fclose(wfp);
}

/**************************************************************************/
/*	The following routines are mostly stolen from cchess              */
/**************************************************************************/

/* DAY()
 *
 * Return today's date, in the form of the number of days since Jan 1, 1970.
 * Actually, the 4.2bsd could use the time() call too, but gettimeofday()
 * seems to be prefered.
 */

long day()
{
#define SECSPERDAY 86400L
#ifdef U42BSD
struct timeval tp;
struct timezone tzp;
	gettimeofday(&tp,&tzp);
	return(tp.tv_sec/SECSPERDAY);
#else
	return(time((long *)0)/SECSPERDAY);
#endif
}

/* MESG()
 *
 *   Send Mail to the other player.  Use the the given text and subject
 *   heading.  Making this come out right may take some fooling around on
 *   any given system.
 */

/* Choose default mailer */
#ifndef MAILER
#  ifdef U41BSD
#    define MAILER "/etc/delivermail"
#  else
#    ifdef U42BSD
#      define MAILER "/usr/lib/sendmail"
#    else
#      define MAILER "/bin/mail"
#    endif U42BSD
#  endif U41BSD
#endif MAILER

mesg(subj,text)
char *subj, *text;
{
#ifdef DEBUG
printf("message to %d: %s\n",hisid, text);
#else
char cmd[60];
FILE *cmdfd;
	
	sprintf(cmd,"%s %s",MAILER,hisid);
	cmdfd = upopen(cmd,"w");

#ifdef UBERK
	fprintf(cmdfd,"To: %s\n",hisid);
#endif UBERK

	fprintf(cmdfd,"Subject: %s\n\n",subj);
	fprintf(cmdfd,"%s",text);

	fclose(cmdfd);		/* Don't use pclose -- don't want to wait */
#endif DEBUG
}


#ifndef U42BSD
/* READDIR
 *
 *	Here we fake 4.2bsd's readdir() command for older bsd's and at&t
 *	unixs.  The "direct" structure on those systems returned isn't the
 *	same the bsd one, but we do ensure that the file name is null
 *	terminated.  It would be easy enough to add the d_namlen and d_reclen
 *	records and extend d_ino to a long named d_fileno, but I don't
 *	really need that here.
 */

struct direct *readdir(fp)
DIR *fp;
{
/* We allocate one extra byte on the end of the structure for the null */
static char dent[ sizeof(struct direct) + 1 ];

	do
		if (fread(dent,sizeof(struct direct),1,fp) == 0)
			return(NULL);
	while (((struct direct *)dent)->d_ino == 0);
	((struct direct *)dent)->d_name[DIRSIZ] = '\0';
	return((struct direct *)dent);
}
#endif U42BSD


/* UPOPEN - Run command on a pipe
 *
 *    This is just like the Unix popen() call, except it runs the command
 *    with the original user id.  This is done for the same reasons mentioned
 *    in the usystem routine.
 */

FILE *upopen(cmd,mode)
char *cmd;
REGISTER char *mode;
{
int p[2];
register int chd_pipe,par_pipe;
FILE *fdopen();
#ifdef NODUP2
int t;
#endif NODUP2

	/* Make a pipe */
	if (pipe(p)) return((FILE *)0);

	/* Choose ends */
	par_pipe = (*mode == 'r') ? p[0] : p[1];
	chd_pipe = (*mode == 'r') ? p[1] : p[0];

	switch (fork())
	{
	case 0:
		/* Child - run command */
		close(par_pipe);
		if (chd_pipe != (*mode == 'r'?1:0))
		{
#ifdef NODUP2
			close(t = (*mode == 'r'?1:0));
			if (fcntl(chd_pipe,F_DUPFD,t) != t)
			{
				printf("Panic: can dup pipe\n");
				exit(1);
			}
#else
			dup2(chd_pipe,(*mode == 'r'?1:0));
#endif NODUP2
			close(chd_pipe);
		}
		setuid(getuid());
		setgid(getgid());
		execl("/bin/sh","sh","-c",cmd,NULL);
		exit(1);
	case -1:
		close(chd_pipe);
		close(par_pipe);
		return((FILE *)0);
	default:
		close(chd_pipe);
		return(fdopen(par_pipe,mode));
	}
}