
/*
 *	MAILCHK.C
 *
 *	DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
 *
 *	Check the mailbox and reports if new mail
 *	has arrived.
 *
 *	Written by S. Laroche.
 *
 *	Usage:	mailchk -N(host) -q -d -t(time)
 *		-d:  Display old mail on startup, if it exists
 *		-q:  Quiet, don't display old mail on startup
 *		Default:  -d
 *
 *		-t:  (time) is the number of seconds between checks.
 *		Default:  40 seconds
 *
 *		-h:  help message
 *
 *	Arp.library is needed... (Version 39.1)
 */

#include <stdio.h>
#include <local/typedefs.h>
#include <libraries/arpbase.h>
#include "/dnet/channel.h"
#include "/server/servers.h"
#include <local/deemu.h>
#include "mailmenu.h"

short Deemu[] = {
    DMSTRT, 0, 0,
    DMNW  , 0, 10, 2, 2, -80, 40, 0xFFFF,
    DMEND , 0, 0
};

#define DMNWOFF 4

#define NA	     0
#define MAILLENGTH 256
#define BUFLENGTH  512
#define MENUSTRIP(n) (SHIFTMENU(n)|SHIFTITEM(NOITEM))
ubyte Title[128];

NW Nw = {
    0, 0, 320, 50, -1, -1,
    NEWSIZE|MENUPICK|CLOSEWINDOW|MOUSEBUTTONS,
    WINSTD|NOCAREREFRESH,
    NULL, NULL, Title, NULL, NULL,
    32, 18, -1, -1, WBENCHSCREEN
};

struct MailMsg {
  char msg[MAILLENGTH];
  struct MailMsg *next;
};

struct mailmsg {
  struct Message ml_msg;
  unsigned long secs;
  BYTE quit, speak, win;
};

struct MailMsg *MailP=NULL;

WIN *Win = NULL;
RP  *Rp;

char DefaultSpeaker[] = "SPEAK:";

/* int Enable_Abort; */

long IntuitionBase;
long GfxBase;
long ArpBase;

struct FileRequester *FileReq = NULL;
PORT *MailPort = NULL;

BYTE SpeakPlease = 2, WindowPlease = 2;

main(ac,av)
char *av[];
{
    long chan = NULL;
    unsigned long numsecs = 0L;
    BYTE firstrun = 1, quit = 0;
    char *host = NULL;

    ArpBase = (long)OpenLibrary(ArpName,39L);
    if (ArpBase == NULL) exit(1);

    if (!param(ac,av,&numsecs,&firstrun,&quit,&host)) {
       CloseLibrary(ArpBase);
       exit(0);
    }
    {
      char buf[64];
      PORT *pr;

      sprintf(buf, "MailChkV%s%s", VERSION, MAILCHK_VERSION);
      Enable_Abort = 0;
      if (pr = FindPort(buf)) {
	  PORT *mailrp;
	  struct mailmsg *mailmsg;

	  if (!(mailrp = CreatePort(NULL,0))) goto fail;
	  if (!(mailmsg = (struct mailmsg *) AllocMem(sizeof(struct mailmsg),
						MEMF_PUBLIC))) {
		DeletePort(mailrp);
		goto fail;
	  }
	  mailmsg->ml_msg.mn_Node.ln_Type = NT_MESSAGE;
	  mailmsg->ml_msg.mn_Length = sizeof(struct mailmsg);
	  mailmsg->ml_msg.mn_ReplyPort = mailrp;
	  mailmsg->secs = numsecs;
	  mailmsg->quit = quit;
	  mailmsg->speak = SpeakPlease;
	  mailmsg->win = WindowPlease;
	  PutMsg(pr,mailmsg);
	  Wait(1 << mailrp->mp_SigBit | SIGBREAKF_CTRL_C);
	  DeletePort(mailrp);
	  FreeMem(mailmsg,sizeof(struct mailmsg));
	  if (quit) Printf("Mailchk, removed\n");
	  else Printf("Mailchk, changed parameters\n");
	  goto fail;
      }
      else if (!(MailPort = CreatePort(buf,0))) goto fail;
    }
    Printf("\nMailChk V%s%s - S. Laroche 1990\n", VERSION, MAILCHK_VERSION);
    if (numsecs == 0) numsecs = 40L;
    if (SpeakPlease == 2) SpeakPlease = 1;
    if (WindowPlease == 2) WindowPlease = 1;
    IntuitionBase = (long)OpenLibrary("intuition.library", 0);
    GfxBase = (long)OpenLibrary("graphics.library", 0);
    chan = DOpen(host, PORT_MAILCHK, 0, 0);
    if (chan == NULL) {
	Puts("no connect");
	goto fail;
    }

    if ((FileReq = ArpAllocFreq()) == NULL) goto fail;
    FileReq->fr_Hail = "Save message to which file?";
    FileReq->fr_Dir = "MAIL:";
    InitDeemuNW(Deemu+DMNWOFF, &Nw);
    if (initmailserver(chan,numsecs,firstrun))
	 checkmail(chan,numsecs);

fail:
    if (Win)
	CloseWindow(Win);
    if (MailPort)
	DeletePort(MailPort);
    if (chan)
	DClose(chan);
    if (IntuitionBase)
	CloseLibrary(IntuitionBase);
    if (GfxBase)
	CloseLibrary(GfxBase);
    if (ArpBase)
	CloseLibrary(ArpBase);
}

int param(ac,av,numsecs,firstrun,quit,host)

char *av[];
BYTE *firstrun, *quit;
unsigned long *numsecs;
ULONG *host;

{
      register short i;
      for (i = 1; i < ac; ++i) {
	if (strncmp(av[i],"-h",2) == 0) {
	    Printf("DNET    - (C) Matthew Dillon 1988\n");
	    Printf("\nUsage:  -t(time) Interval between checks in seconds [DEFAULT = 40 seconds]\n");
	    Printf("        -N(network id) Dnet network number\n");
	    Printf("        -s(flag) 0 = do not speak, 1 = speak [DEFAULT]\n");
	    Printf("        -w(flag) 0 = no window, 1 = window [DEFAULT]\n");
	    Printf("        -d Display mailbox on start-up [Default]\n");
	    Printf("        -n Don't display mailbox on start-up\n");
	    Printf("        -q Remove the MailChk client, if it is running\n");
	    Printf("        -h This message...\n");
	    return(0);
	}
	if (strncmp(av[i], "-N", 2) == 0) {
	    *host = (ULONG) av[i]+2;
	    continue;
	}
	if (strncmp(av[i],"-d",2) == 0) {
	    *firstrun = 1;
	    continue;
	}
	if (strncmp(av[i],"-n",2) == 0) {
	    *firstrun = 0;
	    continue;
	}
	if (strncmp(av[i],"-t",2) == 0) {
	    *numsecs = atoi(av[i]+2);
	    continue;
	}
	if (strncmp(av[i],"-q",2) == 0) {
	    *quit = 1;
	    break;
	}
	if (strncmp(av[i],"-s",2) == 0) {
	    SpeakPlease = (BYTE) atoi(av[i]+2);
	    continue;
	}
	if (strncmp(av[i],"-w",2) == 0) {
	    WindowPlease = (BYTE) atoi(av[i]+2);
	    continue;
	}
      }
      return(1);
}

initmailserver(chan,numsecs,firstrun)

long chan, numsecs;
char firstrun;

{
  char init = 4;

    if ((DWrite(chan,&init,1) == 1) && (DWrite(chan,&numsecs,4) == 4)
	 && (DWrite(chan,&firstrun,1) == 1)) return(1);
    return(0);

}

checkmail(chan,numsecs)

long chan, numsecs;

{
    long imask=0, dmask, omask, mask;
    char notdone = 1, nowindow = 0;
    ULONG prsec = 0, prmic = 0;
    BYTE pos = 0, oldpos = 0;

    dmask   = 1 << ((PORT *) chan)->mp_SigBit;
    omask   = 1 << MailPort->mp_SigBit;
    imask   = 0;
    while (notdone) {
	if (Win) {
	    OnMenu(Win,MENUSTRIP(0));
	    OnMenu(Win,MENUSTRIP(1));
	}
	mask = Wait(imask|dmask|omask|SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_E);
	if (Win) {
	    OffMenu(Win,MENUSTRIP(0));
	    OffMenu(Win,MENUSTRIP(1));
	}
	if (mask & SIGBREAKF_CTRL_C) {
	    notdone = 0; break; }
	if (mask & omask) {
	    struct mailmsg *msg;
	    BYTE quit = 0;

	    while (msg = (struct mailmsg *) GetMsg(MailPort)) {
	      if (msg->secs > 0) numsecs = msg->secs;
	      quit |= msg->quit;
	      if (msg->speak < 2) SpeakPlease = msg->speak;
	      if (msg->win < 2) WindowPlease = msg->win;
	      ReplyMsg(msg);
	      if (msg->win == 1 || msg->speak == 1 || msg->secs > 0 || Win == NULL)
		  initmailserver(chan,numsecs,2);
	    }
	    if (quit) { notdone = 0; break; }
	}
	if (mask & SIGBREAKF_CTRL_E) {
	    initmailserver(chan,numsecs,2);
	    continue;
	}
	if (mask & imask) {
	    IMESS *im;
	    ULONG class, code;

	    while (im = (IMESS *) GetMsg(Win->UserPort)) {
		class = im->Class;
		switch(class) {
		case NEWSIZE:
		    dispnewmail(pos,0,1);
		    break;
		case MOUSEBUTTONS:
		    if (im->Code == SELECTUP) {
		      if (DoubleClick(prsec,prmic,im->Seconds,im->Micros)
			  && pos == oldpos) {
			if (pos > 0) {
			    getmailmsg(chan,pos,0);
			}
		      }
		      else {
			  prsec = im->Seconds;
			  prmic = im->Micros;
			    }
		      if (pos == 0) dispnewmail(0,oldpos,0);
		      else oldpos = pos;
		    }
		    else if (im->Code == SELECTDOWN) {
			     register short i=1;
			     short temp;
			     struct MailMsg *p = MailP;

			     temp = (im->MouseY - Win->BorderTop) / Rp->TxHeight + 1;
			     while ( i != temp && p != NULL) {
				i++;
				p = p->next;
			     }
			     if (p == NULL) { oldpos = pos; pos = 0;}
			     else { pos = temp;
				    dispnewmail(pos,oldpos,0);
				  }
			 }
		    break;
		case CLOSEWINDOW:
		    nowindow = 1;
		    break;
		case MENUPICK:
		    code = im->Code;
		    ReplyMsg(im);
		    switch((uword)((MENUNUM(code)<<8)|ITEMNUM(code))) {
		    case 0x0100:    /*	View	*/
			getmailmsg(chan,pos,0);
			break;
		    case 0x0101:    /*	Print	*/
			getmailmsg(chan,pos,1);
			break;
		    case 0x0102:    /*	Delete	*/
			delmailmsg(chan,pos);
			break;
		    case 0x0103:    /*	Save	*/
			getmailmsg(chan,pos,2);
			break;
		    case 0x0104:    /*	Speak	*/
			getmailmsg(chan,pos,3);
			break;
		    case 0x0105:    /*	Reply	*/
			editmessage(chan,pos);
			break;
		    case 0x0106:    /*	Send	*/
			break;
		    case 0x0000:
			sprintf(Title, "MailChk V%s%s - S. Laroche 1990", VERSION, MAILCHK_VERSION);
			SetWindowTitles(Win,Title,-1);
			break;
		    case 0x0001:    /*	Close	*/
			nowindow = 1;
			break;
		    case 0x0002:    /*	Talk	*/
			SpeakPlease = 1 - SpeakPlease;
			break;
		    case 0x0003:    /*	Window	*/
			WindowPlease = 1 - WindowPlease;
			break;
		    case 0x0004:    /*	Frequency */
			break;
		    case 0x0005:    /*	Remove	*/
			notdone = 0;
			break;
		    }
		}
		if (class != MENUPICK) ReplyMsg(im);
	    }
	}
	if (mask & dmask) {
	    char len = 0;

	    if (DNRead(chan, &len, 1) != 0) {
		if (len < sizeof(Title) && DRead(chan, Title, len) == len) {
		    Title[len-1] = 0;
		    if (strncmp(Title,"No mail",7) == 0) nowindow = 1;
		    else { if (strncmp(Title,"New mail",8) == 0) {
			       DisplayBeep(NULL);
			   }
			   if (Win == NULL && WindowPlease) {
			       Win = OpenWindow(&Nw);
			       if (Win != NULL) {
				   struct MenuItem *mn_ad;
				   Rp = Win->RPort;
				   refreshmenu();
				   SetMenuStrip(Win,Menu);
				   OffMenu(Win,MENUSTRIP(0));
				   OffMenu(Win,MENUSTRIP(1));
				   imask   = 1 << Win->UserPort->mp_SigBit;
			       }
			   }
			   if (SpeakPlease) {
			       char *Speaker;
			       struct FileHandle *fh;

			       Speaker = GetDEnv("SPEAKER");
			       if (Speaker == NULL) Speaker = DefaultSpeaker;
			       fh = Open(Speaker,1006);
			       if (fh) {
				   if (strncmp(Title,"New",3) == 0)
				       Write(fh,"You have new mail.",18);
				   else Write(fh,"You have mail.",14);
				   Close(fh);
			       }
			   }
			   if (Win) {
			     short temp=0;
			     char buf[25], buf2[9];

			     WindowToFront(Win);
			     getnewmail(chan,&temp);
			     if (temp > 1) strcpy(buf2,"messages");
			     else strcpy(buf2,"message");
			     sprintf(buf," (%d %s)",temp,buf2);
			     strcat(Title,buf);
			     dispnewmail(0,0,1);
			   }
			   if (Win != NULL) SetWindowTitles(Win, Title, -1);
			   else if (!SpeakPlease) {
				    short dummy =0;
				    Puts(Title);
				    getnewmail(chan,&dummy);
				    dispnewmail(0,0,1);
				}
		    }
		}
	    }
	    else if (DCheckEof(chan)) notdone = 0;
	}
	if (nowindow && Win) {
	    ClearMenuStrip(Win);
	    Nw.LeftEdge = Win->LeftEdge;
	    Nw.TopEdge = Win->TopEdge;
	    Nw.Width = Win->Width;
	    Nw.Height = Win->Height;
	    CloseWindow(Win);
	    Win = NULL;
	    imask = 0;
	}
	nowindow = 0;
    }

    freemail(MailP);
    if (Win) {
	ClearMenuStrip(Win);
	CloseWindow(Win);
	Win = NULL;
    }
}

/*
 *  Utility routines.	************************************************
 */

refreshmenu()

{
   struct MenuItem *mn_ad;

   mn_ad = (struct MenuItem *) ItemAddress(Menu,SHIFTMENU(0)|SHIFTITEM(2));
   if (SpeakPlease) mn_ad->Flags |= CHECKED;
   else mn_ad->Flags &= ~(CHECKED);
   mn_ad = (struct MenuItem *) ItemAddress(Menu,SHIFTMENU(0)|SHIFTITEM(3));
   if (WindowPlease) mn_ad->Flags |= CHECKED;
   else mn_ad->Flags &= ~(CHECKED);
}

getnewmail(chan,count)

long chan;
register short *count;

{
  unsigned char len = 1;
  struct MailMsg *p;

  freemail(MailP);
  if (DWrite(chan, &len, 1) == 1 && DRead(chan, &len, 1) == 1) {
      while (len > 0) {
	if (MailP) {
	    p->next = AllocMem(sizeof(*p),0);
	    p = p->next;
	}
	else {
	    MailP = AllocMem(sizeof(*p),0);
	    p = MailP;
	}
	if (p == NULL) break;
	else p->next = NULL;
	if (len < MAILLENGTH && (DRead(chan, p->msg, len) == len)) {
	    p->msg[len-1] = '\0';
	    DRead(chan,&len,1);
	    (*count)++;
	}
	else break;

      }
  }
}

dispnewmail(ONmsgno,OFFmsgno,flag)

BYTE ONmsgno, OFFmsgno, flag;

{
  char th, tb, tw;
  short y, Wh, Ww, WOx, WOy;
  int len;
  struct MailMsg *p;
  BYTE i=1;

  p = MailP;
  if (Win != NULL) {
      th = Rp->TxHeight;
      tb = Rp->TxBaseline;
      tw = Rp->TxWidth;
      y = Win->BorderTop;
      Ww = Win->Width - Win->BorderRight - Win->BorderLeft;
      Wh = Win->Height- Win->BorderTop - Win->BorderBottom;
      WOx = Win->BorderLeft;
      WOy = Win->BorderTop;
      if (flag) {
	  SetAPen(Rp, 0);
	  RectFill(Rp, WOx, WOy, Ww + WOx, Wh + WOy);
      }
  }
  while (p != NULL && ((Win == NULL) || ((y+tb) < Wh))) {
    short tl;

    if (! Win && flag) Puts(p->msg);
    else { if (flag || i == ONmsgno || i == OFFmsgno) {
	       if (ONmsgno == i) {
		   SetBPen(Rp,2);
		   SetAPen(Rp,0);
	       }
	       else {
		   SetAPen(Rp,2);
		   SetBPen(Rp,0);
	       }
	       len = strlen(p->msg);
	       tl = TextLength(Rp,p->msg,len);
	       if (tl > Ww) len = Ww / tw;
	       Move(Rp,Win->BorderLeft,y+tb);
	       Text(Rp,p->msg,len);
	       if (ONmsgno == i) SetAPen(Rp,2);
	       else if (OFFmsgno == i || flag) SetAPen(Rp,0);
	       RectFill(Rp,Rp->cp_x,y,Ww+WOx,y+th-1);
	   }
	   y += th;
	   i++;
    }
    p = p->next;
  }
}

delmailmsg(chan,msgno)

long chan;
BYTE msgno;

{
  register BYTE i=1;
  struct MailMsg *p = MailP;
  char dummy[32];
  BYTE dl = 3, ok;
  unsigned long stchar = 0,nochars;

  for (i=1; (i != msgno && p != NULL); i++) {
    getmailprm(p,&nochars,dummy);
    stchar += nochars;
    p = p->next;
  }
  if (p == NULL) return();
  getmailprm(p,&nochars,dummy);

  if ((DWrite(chan,&dl,1) == 1) &&
      (DWrite(chan,&stchar,4) == 4) &&
      (DWrite(chan,&nochars,4) == 4) &&
      (DRead(chan,&ok,1) == 1)) {
      if (ok) {
	  freemail(MailP);
	  strcpy(Title,"Delete successful, refreshing...");
	  SetWindowTitles(Win,Title,-1);
	  dispnewmail(0,0,1);
      }
  }
}

int getmailmsg(chan,msgno,flag)

long chan;
BYTE msgno, flag;

{
  struct MailMsg *p = MailP;
  BYTE i, ok=0, hd = 2, l, start = 0;
  unsigned long stchar=0L, nochars, len;
  long fh;
  ubyte *buf;
  char pname[128], vname[100], title[132], *tmp;
  int rcode = 1;
  struct NewShell *NS;
  if (NS = AllocMem(sizeof(*NS)+4096,MEMF_CLEAR)) {
      NS->nsh_StackSize = 4000;
      NS->nsh_Control = BACKGROUND_SHELL;
  }
  else return(rcode);
  strcpy(vname,"DPIPE:Mail");
  switch (flag) {
    case 0:
      if ((tmp = GetDEnv("PAGER")) == NULL) {
	  strcpy(pname,"sys:utilities/more");
      }
      else { strcpy(pname,tmp);
	     free(tmp);
      }
      strcat(pname," ");
      strcat(pname,vname);
      strcpy(title,"Viewing ");
      start = 1;
      break;
    case 1:
      strcpy(vname,"PRT:");
      strcpy(title,"Printing ");
      break;
    case 2:
      if (!(FileRequest(FileReq))) {
	    return(rcode);}
      strcpy(vname,FileReq->fr_Dir);
      TackOn(vname,FileReq->fr_File);
      strcpy(title,"Saving ");
      strcat(title,vname);
      break;
    case 3:
      tmp = GetDEnv("SPEAKER");
      if (tmp == NULL) tmp = DefaultSpeaker;
      strcpy(vname,tmp);
      strcpy(title,"Speaking ");
      break;
  }
  buf = (ubyte *) (NS + sizeof(*NS));
  l = strlen(title);
  for (i=1; (i != msgno && p != NULL); i++) {
    getmailprm(p,&nochars,&len);
    stchar += nochars;
    p = p->next;
  }
  if (p == NULL) return(rcode);
  getmailprm(p,&nochars,&len);
  if (flag == 3) {stchar += len; nochars -= len; }
  if (flag == 0) {
      strcat(title," using ");
      strcat(title,pname);
  }
  if (fh = Open(vname,1006)) {
      if (DWrite(chan, &hd, 1) == 1 && DWrite(chan, &stchar, 4) == 4
	  && DWrite(chan,&nochars,4) == 4) {
	  SetWindowTitles(Win, title, -1);
	  while (DRead(chan,&len,4) == 4 && len > 0) {
	    if (DRead(chan,buf,len) == len) {
		if (start) {
		    if (ASyncRun(pname,0L,NS) < 0) {
			ok = 1;
			DWrite(chan,&ok,1);
			rcode = 0;
			break;
		    }
		    start = 0;
		}
		if (Write(fh,buf,len) != len) {
		    ok = 1;
		    DWrite(chan,&ok,1);
		    rcode = 0;
		    break;
		}
		DWrite(chan,&ok,1);
	    }
	  }
      }
      Close(fh);
  }
  else {
	rcode = 0;
	Printf("\nCould not open %s\n",vname);
  }
  SetWindowTitles(Win,Title,-1);
  FreeMem(NS,sizeof(*NS)+4096);
  return(rcode);
}

int editmessage(chan,msgno)

long *chan;
UBYTE msgno;

{
  char *buf, fname[32];
  struct MailMsg *p = MailP;
  int ok = 0, test;
  struct FileInfoBlock *fileinfo;
  struct FileLock *lock;
  struct FileHandle *fh = NULL;
  LONG len;
  short count;
  BYTE hd = 5, i;

  if (!(fileinfo = AllocMem(sizeof(struct FileInfoBlock)+BUFLENGTH,0)))
      return(ok);
  buf = (char *) (fileinfo + sizeof(struct FileInfoBlock));
  strcpy(fname,"T:MailChk");
  strcpy(Title,"Replying...");
  SetWindowTitles(Win,Title,-1);
  if (GetDEnv("EDITOR") != NULL) strcpy(buf,GetDEnv("EDITOR"));
  else strcpy(buf,"ed");
  if (SyncRun(buf,fname,0,0) >= 0) {
      if (((lock = Lock(fname,ACCESS_READ)) != 0) &&
	Examine(lock,fileinfo)) {
	len = fileinfo->fib_Size;
	UnLock(lock);
	strcpy(Title,"Could not open tmp file");
	if (!(fh = Open(fname,1005))) goto fin;
	strcpy(Title,"Inconsistency error");
	for (i=1; (i != msgno && p != NULL); i++)
	     p = p->next;
	if (p == NULL) goto fin;
	sscanf(p->msg+1,"%d %s",&test,buf);
	if (test != msgno) goto fin;
	strcpy(Title,"Transmission error");
	if (DWrite(chan,&hd,1) != 1) goto fin;
	count = strlen(buf);
	if (DWrite(chan,&count,2) != 2) goto fin;
	if (DWrite(chan,buf,count) != count) goto fin;
	if (DWrite(chan,&len,4) != 4) goto fin;
	do {
	  count = Read(fh,buf,BUFLENGTH);
	  if (count > 0 && DWrite(chan,buf,count) != count) goto fin;
	} while (count == BUFLENGTH);
	strcpy(Title,"Remote error");
	if (DRead(chan,&ok,1) != 1) ok = 0;
      }
      else {
	  strcpy(Title,"Reply function cancelled");
	  goto fin2;
      }
  }
  else { sprintf(Title,"Editor %s not found",buf);
	 goto fin2;
  }
fin:
  if (fh) Close(fh);
  if (ok) {
      DeleteFile(fname);
      strcpy(Title,"Reply was suscessful");
  }
  else {
      DeleteFile("T:dead.letter");
      Rename(fname,"T:dead.letter");
      strcat(Title," - Letter is in T:dead.letter");
  }
fin2:
  SetWindowTitles(Win,Title,-1);
  FreeMem(fileinfo,sizeof(struct FileInfoBlock)+BUFLENGTH);
  return(ok);
}

getmailprm(p,nochars,len)

struct MailMsg *p;
unsigned long *nochars, *len;

{
  char *str;

  if (str = rindex(p->msg,'/')) {
      sscanf(++str,"%ld %ld",nochars,len);
  }
  else *nochars = 0;
}

freemail(p)

struct MailMsg *p;

{
  while (p != NULL) {
    FreeMem(p,sizeof(*p));
    p = p->next;
  }
  MailP = NULL;
}


