|
|
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 m
Length: 11978 (0x2eca)
Types: TextFile
Names: »mail.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Spacewar/mail.c«
/*
* Spacewar - mail subsystem
*
* Copyright 1984 obo Systems, Inc.
* Copyright 1984 Dan Rosenblatt
*/
#ifndef VMS
#include <sys/types.h>
#include <dbm.h>
#else /* BSD SYSIII SYSV */
#include <types.h>
#include "dbm.h"
#endif /* VMS */
#include <time.h>
#include "spacewar.h"
#include "universe.h"
#include "login.h"
#include "mlbx.h"
#include "plyr.h"
#define MAILPROMPT "player/O(ld)/N(ew)/D(elete)/.(quit)>"
struct mstat {
char ms_stat; /* D(isplay) or S(end) */
short ms_bgn; /* display begin */
short ms_cur; /* display current */
short ms_end; /* display end */
char ms_towho[8+1]; /* send to player */
struct mlst *ms_frst; /* send first line */
struct mlst *ms_lst; /* send last line */
};
struct mlst {
struct mlst *ml_nxt; /* next mail */
char *ml_lin; /* line of mail */
};
static VOID sndmail(),dspmail();
extern char *malloc();
mail(plogin)
register struct login *plogin;
{
register struct mstat *pmstat;
struct mlbxkey getmbkey;
struct plyrkey getplkey;
struct plyr getpldat;
datum dbmkey,dbmdata;
int i;
char buf[80+1],c;
#ifdef DEBUG
DBG("mail(#%d/%s)\n",plogin-loginlst,plogin->ln_name);
#endif
/********************************/
/* call subtask based on status */
/********************************/
if (pmstat = (struct mstat *)plogin->ln_substat)
switch(pmstat->ms_stat) {
case 'D':
dspmail(plogin,pmstat);
break;
case 'S':
sndmail(plogin,pmstat);
break;
default:
perror("mail: unknown ms_stat");
plogin->ln_stat = NULL;
plogin->ln_substat = NULL;
output(plogin,'C',0,PROMPT);
output(plogin,0,0,0);
break;
}
/*******************************************/
/* no status. figure based on input buffer */
/*******************************************/
/* nothing - send counts & subtask prompt */
else if (!plogin->ln_input[0]) {
/* get player */
binit((char *)&getplkey,sizeof(getplkey));
getplkey.pl_plyrkey = PLYR;
strcpy(getplkey.pl_name,plogin->ln_name);
dbmkey.dptr = (char *)&getplkey;
dbmkey.dsize = sizeof(getplkey);
dbmdata = fetch(dbmkey);
if (!dbmdata.dptr) { /* not found? */
perror("mail: can't find plyr");
plogin->ln_stat = NULL;
plogin->ln_substat = NULL;
output(plogin,'C',0,PROMPT);
#ifdef DEBUG
VDBG("mail return\n");
#endif
return;
}
bcopy((char *)&getpldat,dbmdata.dptr,sizeof(getpldat));
sprintf(buf,
"\nYou have %d line(s) of old mail, %d line(s) of new mail.\n",
getpldat.pl_seenml - getpldat.pl_frstml + 1,
getpldat.pl_lstml - getpldat.pl_seenml);
output(plogin,'C',0,buf);
output(plogin,'C',0,MAILPROMPT);
output(plogin,0,0,0);
/* one character - command */
} else if (!plogin->ln_input[1]) {
/* get player */
binit((char *)&getplkey,sizeof(getplkey));
getplkey.pl_plyrkey = PLYR;
strcpy(getplkey.pl_name,plogin->ln_name);
dbmkey.dptr = (char *)&getplkey;
dbmkey.dsize = sizeof(getplkey);
dbmdata = fetch(dbmkey);
if (!dbmdata.dptr) { /* not found? */
perror("mail: can't find plyr");
plogin->ln_stat = NULL;
plogin->ln_substat = NULL;
output(plogin,'C',0,PROMPT);
#ifdef DEBUG
VDBG("mail return\n");
#endif
return;
}
bcopy((char *)&getpldat,dbmdata.dptr,sizeof(getpldat));
switch(c=plogin->ln_input[0]) {
case 'D': /* delete all seen mail */
case 'd':
binit((char *)&getmbkey,sizeof(getmbkey));
getmbkey.mb_mlbxkey = MLBX;
strcpy(getmbkey.mb_plyr,plogin->ln_name);
dbmkey.dptr = (char *)&getmbkey;
dbmkey.dsize = sizeof(getmbkey);
i = 0;
while (getpldat.pl_frstml <= getpldat.pl_seenml) {
getmbkey.mb_mlbx = getpldat.pl_frstml++;
if (delete(dbmkey))
perror("mail: can't delete mlbx");
else
++i;
}
sprintf(buf,"\nDeleted %d line(s) of mail\n",i);
output(plogin,'C',0,buf);
/* update plyr */
dbmkey.dptr = (char *)&getplkey;
dbmkey.dsize = sizeof(getplkey);
dbmdata.dptr = (char *)&getpldat;
dbmdata.dsize = sizeof(getpldat);
if (store(dbmkey,dbmdata))
perror("mail: can't update plyr");
/* back to command prompt */
case '.': /* quit mail */
plogin->ln_stat = NULL;
output(plogin,'C',0,PROMPT);
output(plogin,0,0,0);
break;
case 'O': /* display old mail */
case 'o':
case 'N': /* display new mail */
case 'n':
/* allocate subtask status structure */
if (!(pmstat = (struct mstat *)
malloc(sizeof(struct mstat)))) {
perror("mail: out of memory for mstat");
plogin->ln_stat = NULL;
output(plogin,'C',0,PROMPT);
output(plogin,0,0,0);
break;
}
/* initialize subtask status structure */
pmstat->ms_stat = 'D';
if (c == 'O' || c == 'o') {
pmstat->ms_bgn = getpldat.pl_frstml;
pmstat->ms_end = getpldat.pl_seenml;
} else {
pmstat->ms_bgn = getpldat.pl_seenml + 1;
pmstat->ms_end = getpldat.pl_lstml;
}
pmstat->ms_cur = pmstat->ms_bgn - 1;
/* save subtask status structure and start subtask */
plogin->ln_substat = (char *) pmstat;
dspmail(plogin,pmstat);
break;
default:
output(plogin,'C',0,MAILPROMPT);
output(plogin,0,0,0);
break;
}
/* send to player */
} else {
/* allocate/initialize subtask status structure */
if (!(pmstat = (struct mstat *) malloc(sizeof(struct mstat)))) {
perror("mail: out of memory for mstat");
plogin->ln_stat = NULL;
output(plogin,'C',0,PROMPT);
output(plogin,0,0,0);
} else {
pmstat->ms_stat = 'S';
plogin->ln_input[sizeof(pmstat->ms_towho)-1] = NULL;
strcpy(pmstat->ms_towho,plogin->ln_input);
pmstat->ms_frst = pmstat->ms_lst = NULL;
plogin->ln_substat = (char *) pmstat;
sndmail(plogin,pmstat);
}
}
#ifdef DEBUG
VDBG("mail return\n");
#endif
}
static VOID dspmail(plogin,pmstat)
register struct login *plogin;
register struct mstat *pmstat;
{
struct mlbxkey getmbkey;
struct plyrkey getplkey;
struct plyr getpldat;
datum dbmkey,dbmdata;
char buf[80+1];
int nlines=6;
#ifdef DEBUG
DBG("dspmail(#%d/%s,{%d,%d,%d})\n",plogin-loginlst,plogin->ln_name,
pmstat->ms_bgn,pmstat->ms_cur,pmstat->ms_end);
#endif
/* first time */
if (pmstat->ms_cur < pmstat->ms_bgn) {
sprintf(buf,"\nThere are %d line(s) of mail\n",
pmstat->ms_end - pmstat->ms_bgn + 1);
output(plogin,'C',0,buf);
if (pmstat->ms_end >= pmstat->ms_bgn) {
sprintf(buf,"Output is in groups of %d lines. ",nlines);
output(plogin,'C',0,buf);
output(plogin,'C',0,"Hit return when ready for more.\n");
output(plogin,'C',0,
"A single dot (.) on a line by itself terminates Mail.\n\n");
plogin->ln_iomode = 'm';
}
}
/* display a group of lines */
binit((char *)&getmbkey,sizeof(getmbkey));
getmbkey.mb_mlbxkey = MLBX;
strcpy(getmbkey.mb_plyr,plogin->ln_name);
dbmkey.dptr = (char *)&getmbkey;
dbmkey.dsize = sizeof(getmbkey);
while (nlines-- > 0) {
/* terminate or no more - update plyr */
/* and go back to command level */
if (!strcmp(plogin->ln_input,".") ||
++pmstat->ms_cur > pmstat->ms_end) {
binit((char *)&getplkey,sizeof(getplkey));
getplkey.pl_plyrkey = PLYR;
strcpy(getplkey.pl_name,plogin->ln_name);
dbmkey.dptr = (char *)&getplkey;
dbmkey.dsize = sizeof(getplkey);
dbmdata = fetch(dbmkey);
if (!dbmdata.dptr) /* not found? */
perror("dspmail: can't find plyr");
else {
bcopy((char *)&getpldat,dbmdata.dptr,
sizeof(getpldat));
getpldat.pl_seenml =
(pmstat->ms_cur < pmstat->ms_end) ?
pmstat->ms_cur : pmstat->ms_end;
dbmdata.dptr = (char *)&getpldat;
dbmdata.dsize = sizeof(getpldat);
if (store(dbmkey,dbmdata))
perror("dspmail: can't update plyr");
}
free((char *)pmstat);
plogin->ln_iomode = NULL;
plogin->ln_stat = NULL;
plogin->ln_substat = NULL;
output(plogin,'C',0,PROMPT);
break;
/* get and put out the line of mail */
} else {
getmbkey.mb_mlbx = pmstat->ms_cur;
dbmdata = fetch(dbmkey);
if (!dbmdata.dptr) /* not found? */
perror("dspmail: can't find mlbx");
else {
output(plogin,'C',0,dbmdata.dptr);
output(plogin,'C',0,"\n");
}
}
}
output(plogin,0,0,0);
#ifdef DEBUG
VDBG("dspmail return\n");
#endif
}
static VOID sndmail(plogin,pmstat)
register struct login *plogin;
register struct mstat *pmstat;
{
time_t clock;
struct mlst *pmlst,*nxtmlst;
struct plyrkey getplkey;
struct plyr getpldat;
struct mlbxkey getmbkey;
datum dbmkey,dbmdata;
int mlost=0,nlines;
struct tm *localtime();
char *asctime(),*ctime(),buf[80+1];
#ifdef DEBUG
DBG("sndmail(#%d/%s,%s)\n",plogin-loginlst,plogin->ln_name,
pmstat->ms_towho);
#endif
/* first time or terminate */
if (!pmstat->ms_frst || !strcmp(plogin->ln_input,".")) {
/* verify existence of recipient */
binit((char *)&getplkey,sizeof(getplkey));
getplkey.pl_plyrkey = PLYR;
strcpy(getplkey.pl_name,pmstat->ms_towho);
dbmkey.dptr = (char *)&getplkey;
dbmkey.dsize = sizeof(getplkey);
dbmdata = fetch(dbmkey);
if (!dbmdata.dptr) { /* doesn't exist */
output(plogin,'C',0,pmstat->ms_towho);
output(plogin,'C',0," - no such player\n");
goto terminate; /* horrendous */
} else if (!pmstat->ms_frst) { /* first time */
time(&clock);
sprintf(plogin->ln_input,"From '%s' on %.24s",plogin->ln_name,
#ifdef VMS
ctime(&clock));
#else /* BSD SYSIII SYSV */
asctime(localtime(&clock)));
#endif /* VMS BSD SYSIII SYSV */
output(plogin,'C',0,
"Terminate your mail with a single dot (.) on a line by itself.\n\n");
output(plogin,0,0,0);
} else { /* terminate */
/* insert mlbx lines */
bcopy((char *)&getpldat,dbmdata.dptr,sizeof(getpldat));
binit((char *)&getmbkey,sizeof(getmbkey));
getmbkey.mb_mlbxkey = MLBX;
strcpy(getmbkey.mb_plyr,pmstat->ms_towho);
dbmkey.dptr = (char *)&getmbkey;
dbmkey.dsize = sizeof(getmbkey);
for (nlines=(-1),nxtmlst=pmlst=pmstat->ms_frst;pmlst;
++nlines,pmlst=nxtmlst) {
nxtmlst = nxtmlst->ml_nxt;
getmbkey.mb_mlbx = ++getpldat.pl_lstml;
dbmdata.dsize = strlen(dbmdata.dptr=pmlst->ml_lin) + 1;
if (!mlost && store(dbmkey,dbmdata)) {
++mlost;
output(plogin,'C',0,
"(sigh) database collision, your mail was lost\n");
}
free(pmlst->ml_lin);
free((char *)pmlst);
}
/* insert trailer, update recipient */
if (!mlost) {
getmbkey.mb_mlbx = ++getpldat.pl_lstml;
dbmdata.dsize = strlen(dbmdata.dptr=".") + 1;
if (store(dbmkey,dbmdata)) --getpldat.pl_lstml;
dbmkey.dptr = (char *)&getplkey;
dbmkey.dsize = sizeof(getplkey);
dbmdata.dptr = (char *)&getpldat;
dbmdata.dsize = sizeof(getpldat);
if (store(dbmkey,dbmdata)) {
perror("sndmail: can't update plyr");
output(plogin,'C',0,
"(sigh) database error, your mail was lost\n");
} else {
sprintf(buf,"Sent %d+2 line(s) of mail\n",nlines);
output(plogin,'C',0,buf);
}
}
/* back to command prompt */
terminate:
free((char *)pmstat);
plogin->ln_stat = NULL;
plogin->ln_substat = NULL;
output(plogin,'C',0,PROMPT);
output(plogin,0,0,0);
#ifdef DEBUG
VDBG("sndmail return\n");
#endif
return;
}
}
/*************************/
/* save the line of mail */
/*************************/
/* terminate early if no memory */
if (!(pmlst = (struct mlst *) malloc((unsigned)sizeof(struct mlst))))
perror("sndmail: out of memory for mlst");
if (!pmlst || !(pmlst->ml_lin = malloc(strlen(plogin->ln_input)+1))) {
if (pmlst) perror("sndmail: out of memory for ml_lin");
strcpy(plogin->ln_input,".");
sndmail(plogin,pmstat);
/* save text and link in to list */
} else {
pmlst->ml_nxt = NULL;
strcpy(pmlst->ml_lin,plogin->ln_input);
if (pmstat->ms_frst)
pmstat->ms_lst->ml_nxt = pmlst;
else
pmstat->ms_frst = pmlst;
pmstat->ms_lst = pmlst;
output(plogin,'C',0,">");
output(plogin,0,0,0);
}
#ifdef DEBUG
VDBG("sndmail return\n");
#endif
}