|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T r
Length: 9189 (0x23e5)
Types: TextFile
Names: »reap.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Cchess/reap.c«
/* 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));
}
}