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 m

⟦e06f3afcb⟧ TextFile

    Length: 11978 (0x2eca)
    Types: TextFile
    Names: »mail.c«

Derivation

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

TextFile

/*
 * 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
}