|
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)); } }