[comp.sources.amiga] v90i193: mailchk 05 - mail client+server for DNet, Part02/03

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (07/03/90)

Submitted-by: <lobster@quiche.cs.mcgill.ca>
Posting-number: Volume 90, Issue 193
Archive-name: comm/dnet/mailchk-05/part02

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 3)."
# Contents:  amiga/client/mailchk.c
# Wrapped by tadguy@xanth on Mon Jul  2 19:53:59 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'amiga/client/mailchk.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'amiga/client/mailchk.c'\"
else
echo shar: Extracting \"'amiga/client/mailchk.c'\" \(23145 characters\)
sed "s/^X//" >'amiga/client/mailchk.c' <<'END_OF_FILE'
X/*
X *	MAILCHK.C
X *
X *	DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
X *
X *	Check the mailbox and reports if new mail
X *	has arrived.
X *
X *	Written by S. Laroche.
X *	April 19, 1990
X *
X *	Usage:	mailchk [-N(host) -s(flag) -w(flag) -t(time) -q
X *		-h:  Help message
X *		-s:  flag=0: Don't talk; otherwise talk
X *		-w:  flag=0: No window; other open a window
X *		-t:  (time) is the number of seconds between checks.
X *		     Default:  40 seconds
X *		-q:  Remove mailchk
X *		-h:  help message
X *
X *	Arp.library is needed... (Version 39.1)
X */
X
X#include <stdio.h>
X#include <local/typedefs.h>
X#include <libraries/arpbase.h>
X#include "/dnet/channel.h"
X#include "/server/servers.h"
X#include <local/deemu.h>
X#include "mailmenu.h"          /* menu definitions */
X
X/* Icon images */
X#define YOUHAVEMAIL 0
X#define NEWMAIL     1
X#define NOMAIL	    2
X
X/* Server commands */
X#define GETNEWMAIL  1
X#define GETMAILMSG  2
X#define DELMAILMSG  3
X#define INITSERVER  4
X#define EDITMESSAGE 5
X
X/* For use with Matt Dillon's config utility */
Xshort Deemu[] = {
X    DMSTRT, 0, 0,
X    DMNW  , 0, 4,  0, 10,
X/*    DMNW  , 0, 10, 2, 2, -80, 40, 0xFFFF, */
X    DMEND , 0, 0
X};
X
X#define DMICONNWOFF  4
X/* #define DMNWOFF     14 */
X
X/* Buffer lengths */
X#define MAILLENGTH 256	  /* Max. number of characters in 1 msg header */
X#define BUFLENGTH  512	  /* Length of buffer used for communication */
X
X/* Intuition shortcuts */
X#define MENUSTRIP(n) (SHIFTMENU(n)|SHIFTITEM(NOITEM))
X#define BUSYPOINTER(n) (SetPointer(n, BusyPointer, 22, 16, 0, 0))
X#define IDCMPFLAGS NEWSIZE|MENUPICK|CLOSEWINDOW|MOUSEBUTTONS
X
X/* Storage defined in mailchk_chip.c */
Xextern USHORT BusyPointer[];	       /* Busy pointer image	  */
Xextern struct Image MbImage;	       /* Mailbox icon		  */
Xextern USHORT MbBitMap[3][48*36];      /* Images for mailbox icon */
X
X/* Globals */
Xubyte Title[128];	/* Window title */
Xubyte MailVersion[80];	/* Version number, formatted for Title */
X
X/* Windows and gadgets */
XNW Nw = {
X    0, 20, 640, 100, -1, -1,
X    NULL,
X    WINSTD|NOCAREREFRESH,
X    NULL, NULL, Title, NULL, NULL,
X    32, 18, -1, -1, WBENCHSCREEN
X};  /* Headers window */
X
Xstatic struct Gadget gadget =		/* Used to display the mailbox */
X{ NULL,
X  0, 0, 0, 0,
X  GADGHNONE|GRELWIDTH|GRELHEIGHT|GADGIMAGE,
X  GADGIMMEDIATE|RELVERIFY,
X  WDRAGGING,
X  (APTR) &MbImage,
X  NULL,
X  NULL,
X  NULL,
X  NULL,
X  0, 0
X};  /* Mailbox icon */
X
Xstatic NW IconNW =	  /* The mailbox window */
X{ 0, 11,
X  48, 36,
X  -1, -1,
X  GADGETDOWN|MENUPICK,
X  BORDERLESS|SMART_REFRESH|NOCAREREFRESH,
X  &gadget,
X  NULL,
X  NULL,
X  NULL,
X  NULL,
X  0, 0, 0, 0,
X  WBENCHSCREEN
X}; /* Window for icon */
X
X/* linked lists of headers */
Xstruct MailMsg {
X  char msg[MAILLENGTH];
X  struct MailMsg *next;
X};
X
Xstruct MailMsg *MailP=NULL;  /* 1st pointer of linked list	  */
XUSHORT NumMsg = 0;	     /* Number of messages in linked list */
X
X/* Message struct to communicate between two running mailchk */
Xstruct mailmsg {
X  struct Message ml_msg;
X  unsigned long secs;
X  BYTE quit, speak, win;
X};
X
X
XWIN *Win = NULL, *MbWin = NULL;
XRP  *Rp;
X
Xchar DefaultSpeaker[] = "SPEAK:";  /* Used when env. var. SPEAKER isn't set */
X
Xlong IntuitionBase;
Xlong GfxBase;
Xlong ArpBase;
X
Xstruct FileRequester *FileReq = NULL;
XPORT *MailPort = NULL;
X
XBYTE SpeakPlease = 2, WindowPlease = 2;
X
Xmain(ac,av)
X
Xchar *av[];
X
X{
X    long chan = NULL;
X    unsigned long numsecs = 0L;
X    BYTE firstrun = 1, quit = 0;
X    char *host = NULL;
X    int i;
X
X    ArpBase = (long)OpenLibrary(ArpName,39L);
X    if (ArpBase == NULL) exit(1);
X
X    if (!param(ac,av,&numsecs,&quit,&host)) {
X       CloseLibrary(ArpBase);
X       exit(0);
X    }
X    {
X      char buf[64];
X      PORT *pr;
X
X      sprintf(MailVersion, "MailChkV%s%s ", VERSION, MAILCHK_VERSION);
X      strncpy(buf,MailVersion,7);
X      buf[7] = '\0';
X      strcat(MailVersion, " - April 25 1990");
X      Enable_Abort = 0;
X      if (pr = FindPort(buf)) {
X	  PORT *mailrp;
X	  struct mailmsg *mailmsg;
X
X	  if (!(mailrp = CreatePort(NULL,0))) goto fail;
X	  if (!(mailmsg = (struct mailmsg *) AllocMem(sizeof(struct mailmsg),
X						MEMF_PUBLIC))) {
X		DeletePort(mailrp);
X		goto fail;
X	  }
X	  mailmsg->ml_msg.mn_Node.ln_Type = NT_MESSAGE;
X	  mailmsg->ml_msg.mn_Length = sizeof(struct mailmsg);
X	  mailmsg->ml_msg.mn_ReplyPort = mailrp;
X	  mailmsg->secs = numsecs;
X	  mailmsg->quit = quit;
X	  mailmsg->speak = SpeakPlease;
X	  mailmsg->win = WindowPlease;
X	  PutMsg(pr,mailmsg);
X	  Wait(1 << mailrp->mp_SigBit | SIGBREAKF_CTRL_C);
X	  DeletePort(mailrp);
X	  FreeMem(mailmsg,sizeof(struct mailmsg));
X	  if (quit) Printf("Mailchk, removed\n");
X	  else Printf("Mailchk, changed parameters\n");
X	  goto fail;
X      }
X      else if (!(MailPort = CreatePort(buf,0))) goto fail;
X    }
X    if (numsecs == 0) numsecs = 40L;
X    if (SpeakPlease == 2) SpeakPlease = 1;
X    if (WindowPlease == 2) WindowPlease = 1;
X    IntuitionBase = (long)OpenLibrary("intuition.library", 0);
X    GfxBase = (long)OpenLibrary("graphics.library", 0);
X    chan = DOpen(host, PORT_MAILCHK, 0, 0);
X    if (chan == NULL) {
X	Puts("no connect");
X	goto fail;
X    }
X
X    if ((FileReq = ArpAllocFreq()) == NULL) goto fail;
X    FileReq->fr_Hail = "Save message to which file?";
X    FileReq->fr_Dir = "MAIL:";
X/*    InitDeemuNW(Deemu+DMNWOFF, &Nw); */
X    InitDeemuNW(Deemu+DMICONNWOFF, &IconNW);
X    if ((MbWin = OpenWindow(&IconNW)) == NULL) goto fail;
X    refreshmenu();
X    SetMenuStrip(MbWin,Menu);
X    OffMenu(MbWin,MENUSTRIP(1));
X    if (initmailserver(chan,numsecs,firstrun))
X	 checkmail(chan,numsecs);
X
Xfail:
X    if (Win)
X	CloseWinSafely(Win);
X    if (MbWin)
X	CloseWindow(MbWin);
X    if (MailPort)
X	DeletePort(MailPort);
X    if (chan)
X	DClose(chan);
X    if (IntuitionBase)
X	CloseLibrary(IntuitionBase);
X    if (GfxBase)
X	CloseLibrary(GfxBase);
X    if (ArpBase)
X	CloseLibrary(ArpBase);
X}
X
Xint param(ac,av,numsecs,quit,host)
X
Xchar *av[];
XBYTE *quit;
Xunsigned long *numsecs;
XULONG *host;
X
X{
X      register short i;
X      for (i = 1; i < ac; ++i) {
X	if (strncmp(av[i], "-N", 2) == 0) {
X	    *host = (ULONG) av[i]+2;
X	    continue;
X	}
X	if (strncmp(av[i],"-d",2) == 0) {
X	    continue;
X	}
X	if (strncmp(av[i],"-n",2) == 0) {
X	    continue;
X	}
X	if (strncmp(av[i],"-t",2) == 0) {
X	    *numsecs = atoi(av[i]+2);
X	    continue;
X	}
X	if (strncmp(av[i],"-q",2) == 0) {
X	    *quit = 1;
X	    break;
X	}
X	if (strncmp(av[i],"-s",2) == 0) {
X	    SpeakPlease = (BYTE) atoi(av[i]+2);
X	    continue;
X	}
X	if (strncmp(av[i],"-w",2) == 0) {
X	    WindowPlease = (BYTE) atoi(av[i]+2);
X	    continue;
X	}
X	if (strncmp(av[i],"-h",2) != 0) {
X	    Printf("Illegal switch:  %s\n",av[i]);
X	}
X	Printf("DNET    - (C) Matthew Dillon 1988\n");
X	Printf("%s\n",MailVersion);
X	Printf("\nUsage:  run mailchk [-N(host) -t(time) -s(flag) -w(flag) q|h]\n");
X	Printf("        -t(time) Interval between checks in seconds [DEFAULT = 40 seconds]\n");
X	Printf("        -N(network id) Dnet network number\n");
X	Printf("        -s(flag) 0 = do not speak, 1 = speak [DEFAULT]\n");
X	Printf("        -w(flag) 0 = no window, 1 = window [DEFAULT]\n");
X	Printf("        -q Remove the MailChk client, if it is running\n");
X	Printf("        -h This message...\n");
X	return(0);
X      }
X      return(1);
X}
X
Xinitmailserver(chan,numsecs,firstrun)
X
Xlong chan, numsecs;
Xchar firstrun;
X
X{
X  char init = INITSERVER;
X
X    if ((DWrite(chan,&init,1) == 1) && (DWrite(chan,&numsecs,4) == 4)
X	 && (DWrite(chan,&firstrun,1) == 1)) return(1);
X    return(0);
X
X}
X
Xcheckmail(chan,numsecs)
X
Xlong chan, numsecs;
X
X{
X    long imask, dmask, omask, mask;
X    char notdone = 1, nowindow = 0;
X    ULONG prsec = 0, prmic = 0, prsec2 = 0, prmic2 = 0;
X    BYTE pos = 0, oldpos = 0;
X
X    dmask   = 1 << ((PORT *) chan)->mp_SigBit;
X    omask   = 1 << MailPort->mp_SigBit;
X    imask   = 1 << MbWin->UserPort->mp_SigBit;
X    while (notdone) {
X	if (Win) {
X	    OnMenu(Win,MENUSTRIP(0));
X	    OnMenu(Win,MENUSTRIP(1));
X	}
X	OnMenu(MbWin,MENUSTRIP(0));
X	mask = Wait(imask|dmask|omask|SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_E);
X	OffMenu(MbWin,MENUSTRIP(0));
X	if (Win) {
X	    OffMenu(Win,MENUSTRIP(0));
X	    OffMenu(Win,MENUSTRIP(1));
X	}
X	if (mask & SIGBREAKF_CTRL_C) {
X	    notdone = 0; break; }
X	if (mask & omask) {
X	    struct mailmsg *msg;
X	    BYTE quit = 0;
X
X	    while (msg = (struct mailmsg *) GetMsg(MailPort)) {
X	      if (msg->secs > 0) numsecs = msg->secs;
X	      quit |= msg->quit;
X	      if (msg->speak < 2) SpeakPlease = msg->speak;
X	      if (msg->win < 2) WindowPlease = msg->win;
X	      if (msg->secs > 0)
X		  initmailserver(chan,numsecs,2);
X	      ReplyMsg(msg);
X	    }
X	    if (quit) { notdone = 0; break; }
X	}
X	if (mask & SIGBREAKF_CTRL_E) {
X	    initmailserver(chan,numsecs,2);
X	    continue;
X	}
X	if (mask & imask) {
X	    IMESS *im;
X	    ULONG class, code;
X
X	    while (im = (IMESS *) GetMsg(MbWin->UserPort)) {
X		class = im->Class;
X		switch(class) {
X		case GADGETDOWN:
X		    if (im->IDCMPWindow != MbWin || NumMsg == 0) {
X			ReplyMsg(im);
X			break;
X		    }
X		    if (DoubleClick(prsec2,prmic2,im->Seconds,im->Micros)) {
X			ReplyMsg(im);
X			if (Win) {
X			    WindowToFront(Win);
X			    break;
X			}
X			else if (WindowPlease) {
X				 Win = OpenWindow(&Nw);
X				 if (Win != NULL) {
X				     Rp = Win->RPort;
X				     Win->UserPort = MbWin->UserPort;
X				     ModifyIDCMP(Win,IDCMPFLAGS);
X				     refreshmenu();
X				     SetMenuStrip(Win,Menu);
X				     OffMenu(Win,MENUSTRIP(0));
X				     OffMenu(Win,MENUSTRIP(1));
X				 }
X			     }
X			newimage(YOUHAVEMAIL);
X			if (NumMsg == 65535) getnewmail(chan);
X			else {
X			    strcpy(Title,MailVersion);
X			    dispnewmail(0,0,1);
X			}
X		    }
X		    else {
X			  prsec2 = im->Seconds;
X			  prmic2 = im->Micros;
X			  ReplyMsg(im);
X		    }
X		    break;
X		case NEWSIZE:
X		    dispnewmail(pos,0,1);
X		    break;
X		case MOUSEBUTTONS:
X		    if (im->Code == SELECTUP) {
X		      if (DoubleClick(prsec,prmic,im->Seconds,im->Micros)
X			  && pos == oldpos) {
X			if (pos > 0) {
X			    getmailmsg(chan,pos,0);
X			}
X		      }
X		      else {
X			  prsec = im->Seconds;
X			  prmic = im->Micros;
X			    }
X		      if (pos == 0) dispnewmail(0,oldpos,0);
X		      else oldpos = pos;
X		    }
X		    else if (im->Code == SELECTDOWN) {
X			     register short i=1;
X			     short temp;
X			     struct MailMsg *p = MailP;
X
X			     temp = (im->MouseY - Win->BorderTop) / Rp->TxHeight + 1;
X			     while ( i != temp && p != NULL) {
X				i++;
X				p = p->next;
X			     }
X			     if (p == NULL) { oldpos = pos; pos = 0;}
X			     else { pos = temp;
X				    dispnewmail(pos,oldpos,0);
X				  }
X			 }
X		    break;
X		case CLOSEWINDOW:
X		    nowindow = 1;
X		    break;
X		case MENUPICK:
X		    code = im->Code;
X		    ReplyMsg(im);
X		    switch((uword)((MENUNUM(code)<<8)|ITEMNUM(code))) {
X		    case 0x0100:    /*	View	*/
X			getmailmsg(chan,pos,0);
X			break;
X		    case 0x0101:    /*	Print	*/
X			getmailmsg(chan,pos,1);
X			break;
X		    case 0x0102:    /*	Delete	*/
X			delmailmsg(chan,pos);
X			break;
X		    case 0x0103:    /*	Save	*/
X			getmailmsg(chan,pos,2);
X			break;
X		    case 0x0104:    /*	Speak	*/
X			getmailmsg(chan,pos,3);
X			break;
X		    case 0x0105:    /*	Reply	*/
X			editmessage(chan,pos);
X			break;
X		    case 0x0000:    /*	Talk	*/
X			SpeakPlease = 1 - SpeakPlease;
X			break;
X		    case 0x0001:    /*	Window	*/
X			WindowPlease = 1 - WindowPlease;
X			break;
X		    case 0x0002:    /*	Remove	*/
X			notdone = 0;
X			break;
X		    }
X		}
X		if (class != MENUPICK && class != GADGETDOWN) ReplyMsg(im);
X	    }
X	}
X	if (mask & dmask) {
X	    char len = 0;
X	    short temp = 0;
X
X	    if (DNRead(chan, &len, 1) != 0) {
X		if (len < sizeof(Title) && DRead(chan, Title, len) == len) {
X		    Title[len-1] = 0;
X		    if (strncmp(Title,"No mail",7) == 0) {
X			nowindow = 1;
X			freemail(MailP);
X			newimage(NOMAIL);
X		    }
X		    else { if (strncmp(Title,"New mail",8) == 0) {
X			       DisplayBeep(NULL);
X			       newimage(NEWMAIL);
X			       Delay(50);
X			       DisplayBeep(NULL);
X			   }
X			   else newimage(YOUHAVEMAIL);
X			   if (SpeakPlease) {
X			       char *Speaker;
X			       struct FileHandle *fh;
X
X			       Speaker = GetDEnv("SPEAKER");
X			       if (Speaker == NULL) Speaker = DefaultSpeaker;
X			       fh = Open(Speaker,1006);
X			       if (fh) {
X				   if (strncmp(Title,"New",3) == 0)
X				       Write(fh,"You have new mail.",18);
X				   else Write(fh,"You have mail.",14);
X				   Close(fh);
X			       }
X			   }
X			   NumMsg = -1;
X			   if (Win) {
X			       WindowToFront(Win);
X			       getnewmail(chan);
X			       newimage(YOUHAVEMAIL);
X			   }
X			   if (!SpeakPlease && !WindowPlease) {
X			       Puts(Title);
X			       getnewmail(chan);
X			   }
X		    }
X		}
X	    }
X	    else if (DCheckEof(chan)) notdone = 0;
X	}
X	if (nowindow && Win) {
X	    ClearMenuStrip(Win);
X	    Nw.LeftEdge = Win->LeftEdge;
X	    Nw.TopEdge = Win->TopEdge;
X	    Nw.Width = Win->Width;
X	    Nw.Height = Win->Height;
X	    CloseWinSafely(Win);
X	    Win = NULL;
X	}
X	nowindow = 0;
X    }
X
X    freemail(MailP);
X    if (Win) {
X	ClearMenuStrip(Win);
X	CloseWinSafely(Win);
X	Win = NULL;
X    }
X}
X
X/*
X *  Utility routines.	************************************************
X */
X
Xrefreshmenu()
X
X/* Refresh the two toggle menus(Talk, Window) in the Project strip
X * according to the flags SpeakPlease and WindowPlease.
X */
X
X{
X   struct MenuItem *mn_ad;
X
X   mn_ad = (struct MenuItem *) ItemAddress(Menu,SHIFTMENU(0)|SHIFTITEM(0));
X   if (SpeakPlease) mn_ad->Flags |= CHECKED;
X   else mn_ad->Flags &= ~(CHECKED);
X   mn_ad = (struct MenuItem *) ItemAddress(Menu,SHIFTMENU(0)|SHIFTITEM(1));
X   if (WindowPlease) mn_ad->Flags |= CHECKED;
X   else mn_ad->Flags &= ~(CHECKED);
X}
X
Xnewimage(index)
X
X/* Change the mailbox icon.
X * Values of index:
X * 0 -> "You have mail", 1-> "New mail", 2-> "No mail"
X */
X
X{
X  MbImage.ImageData = &MbBitMap[index][0];
X  RefreshGList(&gadget,MbWin,NULL,1);
X}
X
X
Xgetnewmail(chan)
X
Xlong chan;
X
X/* Get all messages (headers only) from the host.
X * It will also display thoses headers using dispnewmail().
X * The magic number 1 is used to tell the server what we want.
X */
X
X{
X  unsigned char len = GETNEWMAIL;
X  struct MailMsg *p;
X  register USHORT count = 0;
X
X  if (Win) {
X      BUSYPOINTER(Win);
X      SetWindowTitles(Win,MailVersion,-1);
X  }
X  freemail(MailP);
X  if (DWrite(chan, &len, 1) == 1 && DRead(chan, &len, 1) == 1) {
X      while (len > 0) {
X	if (MailP) {
X	    p->next = AllocMem(sizeof(*p),0);
X	    p = p->next;
X	}
X	else {
X	    MailP = AllocMem(sizeof(*p),0);
X	    p = MailP;
X	}
X	if (p == NULL) break;
X	else p->next = NULL;
X	if (len < MAILLENGTH && (DRead(chan, p->msg, len) == len)) {
X	    p->msg[len-1] = '\0';
X	    DRead(chan,&len,1);
X	    count++;
X	}
X	else break;
X
X      }
X  }
X  NumMsg = count;
X  if (Win) ClearPointer(Win);
X  dispnewmail(0,0,1);
X}
X
Xdispnewmail(ONmsgno,OFFmsgno,flag)
X
XBYTE ONmsgno, OFFmsgno, flag;
X
X/* Display mail headers in a window if one is opened or on stdout otherwise.
X * ONmsgno :  msg no to be output in reverse ( 0 = none)
X * OFFmsgno:  msg no to be output normally.
X * flag    :  1 -> It's a new window, 0 -> it's an old window
X */
X
X{
X  char th, tb, tw;
X  short y, Wh, Ww, WOx, WOy;
X  int len;
X  struct MailMsg *p;
X  BYTE i=1;
X
X  p = MailP;
X  if (Win != NULL) {
X      th = Rp->TxHeight;
X      tb = Rp->TxBaseline;
X      tw = Rp->TxWidth;
X      y = Win->BorderTop;
X      Ww = Win->Width - Win->BorderRight - Win->BorderLeft;
X      Wh = Win->Height- Win->BorderTop - Win->BorderBottom;
X      WOx = Win->BorderLeft;
X      WOy = Win->BorderTop;
X      if (flag) {
X	  char buf[25], buf2[9];
X
X	  SetAPen(Rp, 0);
X	  RectFill(Rp, WOx, WOy, Ww + WOx, Wh + WOy);
X	  WindowToFront(Win);
X	  strcpy(buf2,"message");
X	  if (NumMsg > 1) strcat(buf2,"s");
X	  sprintf(buf," (%d %s)",NumMsg,buf2);
X	  if (Title[strlen(Title)-1] != ')') strcat(Title,buf);
X	  SetWindowTitles(Win, Title, -1);
X      }
X  }
X  while (p != NULL && ((Win == NULL) || ((y+tb) < Wh))) {
X    short tl;
X
X    if (! Win && flag) Puts(p->msg);
X    else { if (flag || i == ONmsgno || i == OFFmsgno) {
X	       if (ONmsgno == i) {
X		   SetBPen(Rp,2);
X		   SetAPen(Rp,0);
X	       }
X	       else {
X		   SetAPen(Rp,2);
X		   SetBPen(Rp,0);
X	       }
X	       len = strlen(p->msg);
X	       tl = TextLength(Rp,p->msg,len);
X	       if (tl > Ww) len = Ww / tw;
X	       Move(Rp,Win->BorderLeft,y+tb);
X	       Text(Rp,p->msg,len);
X	       if (ONmsgno == i) SetAPen(Rp,2);
X	       else if (OFFmsgno == i || flag) SetAPen(Rp,0);
X	       RectFill(Rp,Rp->cp_x,y,Ww+WOx,y+th-1);
X	   }
X	   y += th;
X	   i++;
X    }
X    p = p->next;
X  }
X}
X
Xdelmailmsg(chan,msgno)
X
Xlong chan;
XBYTE msgno;
X
X/* Send a command to the server asking it to delete message number msgno.
X */
X
X{
X  register BYTE i=1;
X  struct MailMsg *p = MailP;
X  char dummy[32];
X  BYTE dl = DELMAILMSG, ok;
X  unsigned long stchar = 0,nochars;
X
X  BUSYPOINTER(Win);
X  for (i=1; (i != msgno && p != NULL); i++) {
X    getmailprm(p,&nochars,dummy);
X    stchar += nochars;
X    p = p->next;
X  }
X  if (p == NULL) return();
X  getmailprm(p,&nochars,dummy);
X
X  if ((DWrite(chan,&dl,1) == 1) &&
X      (DWrite(chan,&stchar,4) == 4) &&
X      (DWrite(chan,&nochars,4) == 4) &&
X      (DRead(chan,&ok,1) == 1)) {
X      if (ok) strcpy(Title,"Delete successful ");
X      else strcpy(Title,"Delete error ");
X      getnewmail(chan);
X  }
X  ClearPointer(Win);
X}
X
Xint getmailmsg(chan,msgno,flag)
X
Xlong chan;
XBYTE msgno, flag;
X
X/* Get message number msgno from the host and take the following action
X * according to the value of flag:
X *
X *    0 -> View the message on screen (using more or the env var PAGER)
X *    1 -> Print the message on PRT:
X *    2 -> Save the message in a file.
X *    3 -> Send the message to the SPEAK: device (without the headers)
X */
X
X{
X  struct MailMsg *p = MailP;
X  BYTE i, ok=0, hd = GETMAILMSG, l, start = 0;
X  unsigned long stchar=0L, nochars, len;
X  struct FileHandle *fh;
X  ubyte *buf;
X  char pname[128], vname[100], title[132], *tmp;
X  int rcode = 1;
X  struct NewShell *NS;
X  if (NS = AllocMem(sizeof(*NS)+4096,MEMF_CLEAR)) {
X      NS->nsh_StackSize = 4000;
X      NS->nsh_Control = BACKGROUND_SHELL;
X  }
X  else return(rcode);
X  strcpy(vname,"DPIPE:Mail");
X  switch (flag) {
X    case 0:			  /* View */
X      if ((tmp = GetDEnv("PAGER")) == NULL) {
X	  strcpy(pname,"sys:utilities/more");
X      }
X      else { strcpy(pname,tmp);
X	     free(tmp);
X      }
X      strcat(pname," ");
X      strcat(pname,vname);
X      strcpy(title,"Viewing ");
X      start = 1;
X      break;
X    case 1:			 /* Print */
X      strcpy(vname,"PRT:");
X      strcpy(title,"Printing ");
X      break;
X    case 2:			 /* Save */
X      if (!(FileRequest(FileReq))) {
X	    return(rcode);}
X      strcpy(vname,FileReq->fr_Dir);
X      TackOn(vname,FileReq->fr_File);
X      strcpy(title,"Saving ");
X      strcat(title,vname);
X      break;
X    case 3:			 /* Speak */
X      tmp = GetDEnv("SPEAKER");
X      if (tmp == NULL) tmp = DefaultSpeaker;
X      strcpy(vname,tmp);
X      strcpy(title,"Speaking ");
X      break;
X  }
X  buf = (ubyte *) (NS + sizeof(*NS));
X  l = strlen(title);
X  for (i=1; (i != msgno && p != NULL); i++) {
X    getmailprm(p,&nochars,&len);
X    stchar += nochars;
X    p = p->next;
X  }
X  if (p == NULL) return(rcode);
X  getmailprm(p,&nochars,&len);
X  if (flag == 3) {stchar += len; nochars -= len; }
X  if (flag == 0) {
X      strcat(title," using ");
X      strcat(title,pname);
X  }
X  BUSYPOINTER(Win);
X  if (fh = Open(vname,1006)) {
X      if (DWrite(chan, &hd, 1) == 1 && DWrite(chan, &stchar, 4) == 4
X	  && DWrite(chan,&nochars,4) == 4) {
X	  SetWindowTitles(Win, title, -1);
X	  while (DRead(chan,&len,4) == 4 && len > 0) {
X	    if (DRead(chan,buf,len) == len) {
X		if (start) {
X		    if (ASyncRun(pname,0L,NS) < 0) {
X			ok = 1;
X			DWrite(chan,&ok,1);
X			rcode = 0;
X			break;
X		    }
X		    start = 0;
X		}
X		if (Write(fh,buf,len) != len) {
X		    ok = 1;
X		    DWrite(chan,&ok,1);
X		    rcode = 0;
X		    break;
X		}
X		DWrite(chan,&ok,1);
X	    }
X	  }
X      }
X      Close(fh);
X  }
X  else {
X	rcode = 0;
X	Printf("\nCould not open %s\n",vname);
X  }
X  SetWindowTitles(Win,Title,-1);
X  FreeMem(NS,sizeof(*NS)+4096);
X  ClearPointer(Win);
X  return(rcode);
X}
X
Xint editmessage(chan,msgno)
X
Xlong *chan;
XUBYTE msgno;
X
X/* Reply to message number msgno using ed or the env var EDITOR.
X * A temporary file in the T: directory is used.
X *
X * Still buggy for unknown reasons.
X */
X
X{
X  char *buf, fname[32];
X  struct MailMsg *p = MailP;
X  int ok = 0, test;
X  struct FileInfoBlock *fileinfo;
X  struct FileLock *lock;
X  struct FileHandle *fh = NULL;
X  LONG len;
X  short count;
X  BYTE hd = EDITMESSAGE, i;
X
X  if (!(fileinfo = AllocMem(sizeof(struct FileInfoBlock)+BUFLENGTH,0)))
X      return(ok);
X  buf = (char *) (fileinfo + sizeof(struct FileInfoBlock));
X  strcpy(fname,"T:MailChk");
X  strcpy(Title,"Replying...");
X  SetWindowTitles(Win,Title,-1);
X  if (GetDEnv("EDITOR") != NULL) strcpy(buf,GetDEnv("EDITOR"));
X  else strcpy(buf,"ed");
X  BUSYPOINTER(Win);
X  if (SyncRun(buf,fname,0,0) >= 0) {
X      if (((lock = Lock(fname,ACCESS_READ)) != 0) &&
X	Examine(lock,fileinfo)) {
X	len = fileinfo->fib_Size;
X	UnLock(lock);
X	strcpy(Title,"Could not open tmp file");
X	if (!(fh = Open(fname,1005))) goto fin;
X	strcpy(Title,"Inconsistency error");
X	for (i=1; (i != msgno && p != NULL); i++)
X	     p = p->next;
X	if (p == NULL) goto fin;
X	sscanf(p->msg+1,"%d %s",&test,buf);
X	if (test != msgno) goto fin;
X	strcpy(Title,"Transmission error");
X	if (DWrite(chan,&hd,1) != 1) goto fin;
X	count = strlen(buf);
X	if (DWrite(chan,&count,2) != 2) goto fin;
X	if (DWrite(chan,buf,count) != count) goto fin;
X	if (DWrite(chan,&len,4) != 4) goto fin;
X	do {
X	  count = Read(fh,buf,BUFLENGTH);
X	  if (count > 0 && DWrite(chan,buf,count) != count) goto fin;
X	} while (count == BUFLENGTH);
X	strcpy(Title,"Remote error");
X	if (DRead(chan,&ok,1) != 1) ok = 0;
X      }
X      else {
X	  strcpy(Title,"Reply function cancelled");
X	  goto fin2;
X      }
X  }
X  else { sprintf(Title,"Editor %s not found",buf);
X	 goto fin2;
X  }
Xfin:
X  if (fh) Close(fh);
X  if (ok) {
X      DeleteFile(fname);
X      strcpy(Title,"Reply was suscessful");
X  }
X  else {
X      DeleteFile("T:dead.letter");
X      Rename(fname,"T:dead.letter");
X      strcat(Title," - Letter is in T:dead.letter");
X  }
Xfin2:
X  SetWindowTitles(Win,Title,-1);
X  ClearPointer(Win);
X  FreeMem(fileinfo,sizeof(struct FileInfoBlock)+BUFLENGTH);
X  return(ok);
X}
X
Xgetmailprm(p,nochars,len)
X
Xstruct MailMsg *p;
Xunsigned long *nochars, *len;
X
X/* Extract the no of chars (nochars) from a particular header (pointed to
X * by p) in the message and the no of chars without the header lines
X * (len).
X */
X
X{
X  char *str;
X
X  if (str = rindex(p->msg,'/')) {
X      sscanf(++str,"%ld %ld",nochars,len);
X  }
X  else *nochars = 0;
X}
X
Xfreemail(p)
X
Xstruct MailMsg *p;
X
X/* Free all the memory used by the linked list
X */
X
X{
X  while (p != NULL) {
X    FreeMem(p,sizeof(*p));
X    p = p->next;
X  }
X  MailP = NULL;
X  NumMsg = 0;
X}
X
XCloseWinSafely(win)
X
XWIN *win;
X
X/* From RKM 1.3.
X * Close window win safely when it shares an IDCMP port with other
X * windows.
X */
X
X{
X  Forbid();
X  StripIntuiMessages(win->UserPort,win);
X  win->UserPort = NULL;
X  ModifyIDCMP(win,0);
X  Permit();
X  CloseWindow(win);
X}
X
XStripIntuiMessages(mp,win)
X
XPORT *mp;
XWIN *win;
X
X/* From RKM 1.3 */
X
X{
X  IMESS *msg, *succ;
X
X  msg = (IMESS *) mp->mp_MsgList.lh_Head;
X  while (succ = (IMESS *) msg->ExecMessage.mn_Node.ln_Succ) {
X    if (msg->IDCMPWindow == win) {
X	Remove(msg);
X	ReplyMsg(msg);
X    }
X    msg = succ;
X  }
X}
X
END_OF_FILE
if test 23145 -ne `wc -c <'amiga/client/mailchk.c'`; then
    echo shar: \"'amiga/client/mailchk.c'\" unpacked with wrong size!
fi
# end of 'amiga/client/mailchk.c'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (07/03/90)

Submitted-by: <lobster@quiche.cs.mcgill.ca>
Posting-number: Volume 90, Issue 193
Archive-name: comm/dnet/mailchk-05/part02

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 3)."
# Contents:  amiga/client/mailchk.c
# Wrapped by tadguy@xanth on Tue Jul  3 08:56:46 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'amiga/client/mailchk.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'amiga/client/mailchk.c'\"
else
echo shar: Extracting \"'amiga/client/mailchk.c'\" \(23145 characters\)
sed "s/^X//" >'amiga/client/mailchk.c' <<'END_OF_FILE'
X/*
X *	MAILCHK.C
X *
X *	DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
X *
X *	Check the mailbox and reports if new mail
X *	has arrived.
X *
X *	Written by S. Laroche.
X *	April 19, 1990
X *
X *	Usage:	mailchk [-N(host) -s(flag) -w(flag) -t(time) -q
X *		-h:  Help message
X *		-s:  flag=0: Don't talk; otherwise talk
X *		-w:  flag=0: No window; other open a window
X *		-t:  (time) is the number of seconds between checks.
X *		     Default:  40 seconds
X *		-q:  Remove mailchk
X *		-h:  help message
X *
X *	Arp.library is needed... (Version 39.1)
X */
X
X#include <stdio.h>
X#include <local/typedefs.h>
X#include <libraries/arpbase.h>
X#include "/dnet/channel.h"
X#include "/server/servers.h"
X#include <local/deemu.h>
X#include "mailmenu.h"          /* menu definitions */
X
X/* Icon images */
X#define YOUHAVEMAIL 0
X#define NEWMAIL     1
X#define NOMAIL	    2
X
X/* Server commands */
X#define GETNEWMAIL  1
X#define GETMAILMSG  2
X#define DELMAILMSG  3
X#define INITSERVER  4
X#define EDITMESSAGE 5
X
X/* For use with Matt Dillon's config utility */
Xshort Deemu[] = {
X    DMSTRT, 0, 0,
X    DMNW  , 0, 4,  0, 10,
X/*    DMNW  , 0, 10, 2, 2, -80, 40, 0xFFFF, */
X    DMEND , 0, 0
X};
X
X#define DMICONNWOFF  4
X/* #define DMNWOFF     14 */
X
X/* Buffer lengths */
X#define MAILLENGTH 256	  /* Max. number of characters in 1 msg header */
X#define BUFLENGTH  512	  /* Length of buffer used for communication */
X
X/* Intuition shortcuts */
X#define MENUSTRIP(n) (SHIFTMENU(n)|SHIFTITEM(NOITEM))
X#define BUSYPOINTER(n) (SetPointer(n, BusyPointer, 22, 16, 0, 0))
X#define IDCMPFLAGS NEWSIZE|MENUPICK|CLOSEWINDOW|MOUSEBUTTONS
X
X/* Storage defined in mailchk_chip.c */
Xextern USHORT BusyPointer[];	       /* Busy pointer image	  */
Xextern struct Image MbImage;	       /* Mailbox icon		  */
Xextern USHORT MbBitMap[3][48*36];      /* Images for mailbox icon */
X
X/* Globals */
Xubyte Title[128];	/* Window title */
Xubyte MailVersion[80];	/* Version number, formatted for Title */
X
X/* Windows and gadgets */
XNW Nw = {
X    0, 20, 640, 100, -1, -1,
X    NULL,
X    WINSTD|NOCAREREFRESH,
X    NULL, NULL, Title, NULL, NULL,
X    32, 18, -1, -1, WBENCHSCREEN
X};  /* Headers window */
X
Xstatic struct Gadget gadget =		/* Used to display the mailbox */
X{ NULL,
X  0, 0, 0, 0,
X  GADGHNONE|GRELWIDTH|GRELHEIGHT|GADGIMAGE,
X  GADGIMMEDIATE|RELVERIFY,
X  WDRAGGING,
X  (APTR) &MbImage,
X  NULL,
X  NULL,
X  NULL,
X  NULL,
X  0, 0
X};  /* Mailbox icon */
X
Xstatic NW IconNW =	  /* The mailbox window */
X{ 0, 11,
X  48, 36,
X  -1, -1,
X  GADGETDOWN|MENUPICK,
X  BORDERLESS|SMART_REFRESH|NOCAREREFRESH,
X  &gadget,
X  NULL,
X  NULL,
X  NULL,
X  NULL,
X  0, 0, 0, 0,
X  WBENCHSCREEN
X}; /* Window for icon */
X
X/* linked lists of headers */
Xstruct MailMsg {
X  char msg[MAILLENGTH];
X  struct MailMsg *next;
X};
X
Xstruct MailMsg *MailP=NULL;  /* 1st pointer of linked list	  */
XUSHORT NumMsg = 0;	     /* Number of messages in linked list */
X
X/* Message struct to communicate between two running mailchk */
Xstruct mailmsg {
X  struct Message ml_msg;
X  unsigned long secs;
X  BYTE quit, speak, win;
X};
X
X
XWIN *Win = NULL, *MbWin = NULL;
XRP  *Rp;
X
Xchar DefaultSpeaker[] = "SPEAK:";  /* Used when env. var. SPEAKER isn't set */
X
Xlong IntuitionBase;
Xlong GfxBase;
Xlong ArpBase;
X
Xstruct FileRequester *FileReq = NULL;
XPORT *MailPort = NULL;
X
XBYTE SpeakPlease = 2, WindowPlease = 2;
X
Xmain(ac,av)
X
Xchar *av[];
X
X{
X    long chan = NULL;
X    unsigned long numsecs = 0L;
X    BYTE firstrun = 1, quit = 0;
X    char *host = NULL;
X    int i;
X
X    ArpBase = (long)OpenLibrary(ArpName,39L);
X    if (ArpBase == NULL) exit(1);
X
X    if (!param(ac,av,&numsecs,&quit,&host)) {
X       CloseLibrary(ArpBase);
X       exit(0);
X    }
X    {
X      char buf[64];
X      PORT *pr;
X
X      sprintf(MailVersion, "MailChkV%s%s ", VERSION, MAILCHK_VERSION);
X      strncpy(buf,MailVersion,7);
X      buf[7] = '\0';
X      strcat(MailVersion, " - April 25 1990");
X      Enable_Abort = 0;
X      if (pr = FindPort(buf)) {
X	  PORT *mailrp;
X	  struct mailmsg *mailmsg;
X
X	  if (!(mailrp = CreatePort(NULL,0))) goto fail;
X	  if (!(mailmsg = (struct mailmsg *) AllocMem(sizeof(struct mailmsg),
X						MEMF_PUBLIC))) {
X		DeletePort(mailrp);
X		goto fail;
X	  }
X	  mailmsg->ml_msg.mn_Node.ln_Type = NT_MESSAGE;
X	  mailmsg->ml_msg.mn_Length = sizeof(struct mailmsg);
X	  mailmsg->ml_msg.mn_ReplyPort = mailrp;
X	  mailmsg->secs = numsecs;
X	  mailmsg->quit = quit;
X	  mailmsg->speak = SpeakPlease;
X	  mailmsg->win = WindowPlease;
X	  PutMsg(pr,mailmsg);
X	  Wait(1 << mailrp->mp_SigBit | SIGBREAKF_CTRL_C);
X	  DeletePort(mailrp);
X	  FreeMem(mailmsg,sizeof(struct mailmsg));
X	  if (quit) Printf("Mailchk, removed\n");
X	  else Printf("Mailchk, changed parameters\n");
X	  goto fail;
X      }
X      else if (!(MailPort = CreatePort(buf,0))) goto fail;
X    }
X    if (numsecs == 0) numsecs = 40L;
X    if (SpeakPlease == 2) SpeakPlease = 1;
X    if (WindowPlease == 2) WindowPlease = 1;
X    IntuitionBase = (long)OpenLibrary("intuition.library", 0);
X    GfxBase = (long)OpenLibrary("graphics.library", 0);
X    chan = DOpen(host, PORT_MAILCHK, 0, 0);
X    if (chan == NULL) {
X	Puts("no connect");
X	goto fail;
X    }
X
X    if ((FileReq = ArpAllocFreq()) == NULL) goto fail;
X    FileReq->fr_Hail = "Save message to which file?";
X    FileReq->fr_Dir = "MAIL:";
X/*    InitDeemuNW(Deemu+DMNWOFF, &Nw); */
X    InitDeemuNW(Deemu+DMICONNWOFF, &IconNW);
X    if ((MbWin = OpenWindow(&IconNW)) == NULL) goto fail;
X    refreshmenu();
X    SetMenuStrip(MbWin,Menu);
X    OffMenu(MbWin,MENUSTRIP(1));
X    if (initmailserver(chan,numsecs,firstrun))
X	 checkmail(chan,numsecs);
X
Xfail:
X    if (Win)
X	CloseWinSafely(Win);
X    if (MbWin)
X	CloseWindow(MbWin);
X    if (MailPort)
X	DeletePort(MailPort);
X    if (chan)
X	DClose(chan);
X    if (IntuitionBase)
X	CloseLibrary(IntuitionBase);
X    if (GfxBase)
X	CloseLibrary(GfxBase);
X    if (ArpBase)
X	CloseLibrary(ArpBase);
X}
X
Xint param(ac,av,numsecs,quit,host)
X
Xchar *av[];
XBYTE *quit;
Xunsigned long *numsecs;
XULONG *host;
X
X{
X      register short i;
X      for (i = 1; i < ac; ++i) {
X	if (strncmp(av[i], "-N", 2) == 0) {
X	    *host = (ULONG) av[i]+2;
X	    continue;
X	}
X	if (strncmp(av[i],"-d",2) == 0) {
X	    continue;
X	}
X	if (strncmp(av[i],"-n",2) == 0) {
X	    continue;
X	}
X	if (strncmp(av[i],"-t",2) == 0) {
X	    *numsecs = atoi(av[i]+2);
X	    continue;
X	}
X	if (strncmp(av[i],"-q",2) == 0) {
X	    *quit = 1;
X	    break;
X	}
X	if (strncmp(av[i],"-s",2) == 0) {
X	    SpeakPlease = (BYTE) atoi(av[i]+2);
X	    continue;
X	}
X	if (strncmp(av[i],"-w",2) == 0) {
X	    WindowPlease = (BYTE) atoi(av[i]+2);
X	    continue;
X	}
X	if (strncmp(av[i],"-h",2) != 0) {
X	    Printf("Illegal switch:  %s\n",av[i]);
X	}
X	Printf("DNET    - (C) Matthew Dillon 1988\n");
X	Printf("%s\n",MailVersion);
X	Printf("\nUsage:  run mailchk [-N(host) -t(time) -s(flag) -w(flag) q|h]\n");
X	Printf("        -t(time) Interval between checks in seconds [DEFAULT = 40 seconds]\n");
X	Printf("        -N(network id) Dnet network number\n");
X	Printf("        -s(flag) 0 = do not speak, 1 = speak [DEFAULT]\n");
X	Printf("        -w(flag) 0 = no window, 1 = window [DEFAULT]\n");
X	Printf("        -q Remove the MailChk client, if it is running\n");
X	Printf("        -h This message...\n");
X	return(0);
X      }
X      return(1);
X}
X
Xinitmailserver(chan,numsecs,firstrun)
X
Xlong chan, numsecs;
Xchar firstrun;
X
X{
X  char init = INITSERVER;
X
X    if ((DWrite(chan,&init,1) == 1) && (DWrite(chan,&numsecs,4) == 4)
X	 && (DWrite(chan,&firstrun,1) == 1)) return(1);
X    return(0);
X
X}
X
Xcheckmail(chan,numsecs)
X
Xlong chan, numsecs;
X
X{
X    long imask, dmask, omask, mask;
X    char notdone = 1, nowindow = 0;
X    ULONG prsec = 0, prmic = 0, prsec2 = 0, prmic2 = 0;
X    BYTE pos = 0, oldpos = 0;
X
X    dmask   = 1 << ((PORT *) chan)->mp_SigBit;
X    omask   = 1 << MailPort->mp_SigBit;
X    imask   = 1 << MbWin->UserPort->mp_SigBit;
X    while (notdone) {
X	if (Win) {
X	    OnMenu(Win,MENUSTRIP(0));
X	    OnMenu(Win,MENUSTRIP(1));
X	}
X	OnMenu(MbWin,MENUSTRIP(0));
X	mask = Wait(imask|dmask|omask|SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_E);
X	OffMenu(MbWin,MENUSTRIP(0));
X	if (Win) {
X	    OffMenu(Win,MENUSTRIP(0));
X	    OffMenu(Win,MENUSTRIP(1));
X	}
X	if (mask & SIGBREAKF_CTRL_C) {
X	    notdone = 0; break; }
X	if (mask & omask) {
X	    struct mailmsg *msg;
X	    BYTE quit = 0;
X
X	    while (msg = (struct mailmsg *) GetMsg(MailPort)) {
X	      if (msg->secs > 0) numsecs = msg->secs;
X	      quit |= msg->quit;
X	      if (msg->speak < 2) SpeakPlease = msg->speak;
X	      if (msg->win < 2) WindowPlease = msg->win;
X	      if (msg->secs > 0)
X		  initmailserver(chan,numsecs,2);
X	      ReplyMsg(msg);
X	    }
X	    if (quit) { notdone = 0; break; }
X	}
X	if (mask & SIGBREAKF_CTRL_E) {
X	    initmailserver(chan,numsecs,2);
X	    continue;
X	}
X	if (mask & imask) {
X	    IMESS *im;
X	    ULONG class, code;
X
X	    while (im = (IMESS *) GetMsg(MbWin->UserPort)) {
X		class = im->Class;
X		switch(class) {
X		case GADGETDOWN:
X		    if (im->IDCMPWindow != MbWin || NumMsg == 0) {
X			ReplyMsg(im);
X			break;
X		    }
X		    if (DoubleClick(prsec2,prmic2,im->Seconds,im->Micros)) {
X			ReplyMsg(im);
X			if (Win) {
X			    WindowToFront(Win);
X			    break;
X			}
X			else if (WindowPlease) {
X				 Win = OpenWindow(&Nw);
X				 if (Win != NULL) {
X				     Rp = Win->RPort;
X				     Win->UserPort = MbWin->UserPort;
X				     ModifyIDCMP(Win,IDCMPFLAGS);
X				     refreshmenu();
X				     SetMenuStrip(Win,Menu);
X				     OffMenu(Win,MENUSTRIP(0));
X				     OffMenu(Win,MENUSTRIP(1));
X				 }
X			     }
X			newimage(YOUHAVEMAIL);
X			if (NumMsg == 65535) getnewmail(chan);
X			else {
X			    strcpy(Title,MailVersion);
X			    dispnewmail(0,0,1);
X			}
X		    }
X		    else {
X			  prsec2 = im->Seconds;
X			  prmic2 = im->Micros;
X			  ReplyMsg(im);
X		    }
X		    break;
X		case NEWSIZE:
X		    dispnewmail(pos,0,1);
X		    break;
X		case MOUSEBUTTONS:
X		    if (im->Code == SELECTUP) {
X		      if (DoubleClick(prsec,prmic,im->Seconds,im->Micros)
X			  && pos == oldpos) {
X			if (pos > 0) {
X			    getmailmsg(chan,pos,0);
X			}
X		      }
X		      else {
X			  prsec = im->Seconds;
X			  prmic = im->Micros;
X			    }
X		      if (pos == 0) dispnewmail(0,oldpos,0);
X		      else oldpos = pos;
X		    }
X		    else if (im->Code == SELECTDOWN) {
X			     register short i=1;
X			     short temp;
X			     struct MailMsg *p = MailP;
X
X			     temp = (im->MouseY - Win->BorderTop) / Rp->TxHeight + 1;
X			     while ( i != temp && p != NULL) {
X				i++;
X				p = p->next;
X			     }
X			     if (p == NULL) { oldpos = pos; pos = 0;}
X			     else { pos = temp;
X				    dispnewmail(pos,oldpos,0);
X				  }
X			 }
X		    break;
X		case CLOSEWINDOW:
X		    nowindow = 1;
X		    break;
X		case MENUPICK:
X		    code = im->Code;
X		    ReplyMsg(im);
X		    switch((uword)((MENUNUM(code)<<8)|ITEMNUM(code))) {
X		    case 0x0100:    /*	View	*/
X			getmailmsg(chan,pos,0);
X			break;
X		    case 0x0101:    /*	Print	*/
X			getmailmsg(chan,pos,1);
X			break;
X		    case 0x0102:    /*	Delete	*/
X			delmailmsg(chan,pos);
X			break;
X		    case 0x0103:    /*	Save	*/
X			getmailmsg(chan,pos,2);
X			break;
X		    case 0x0104:    /*	Speak	*/
X			getmailmsg(chan,pos,3);
X			break;
X		    case 0x0105:    /*	Reply	*/
X			editmessage(chan,pos);
X			break;
X		    case 0x0000:    /*	Talk	*/
X			SpeakPlease = 1 - SpeakPlease;
X			break;
X		    case 0x0001:    /*	Window	*/
X			WindowPlease = 1 - WindowPlease;
X			break;
X		    case 0x0002:    /*	Remove	*/
X			notdone = 0;
X			break;
X		    }
X		}
X		if (class != MENUPICK && class != GADGETDOWN) ReplyMsg(im);
X	    }
X	}
X	if (mask & dmask) {
X	    char len = 0;
X	    short temp = 0;
X
X	    if (DNRead(chan, &len, 1) != 0) {
X		if (len < sizeof(Title) && DRead(chan, Title, len) == len) {
X		    Title[len-1] = 0;
X		    if (strncmp(Title,"No mail",7) == 0) {
X			nowindow = 1;
X			freemail(MailP);
X			newimage(NOMAIL);
X		    }
X		    else { if (strncmp(Title,"New mail",8) == 0) {
X			       DisplayBeep(NULL);
X			       newimage(NEWMAIL);
X			       Delay(50);
X			       DisplayBeep(NULL);
X			   }
X			   else newimage(YOUHAVEMAIL);
X			   if (SpeakPlease) {
X			       char *Speaker;
X			       struct FileHandle *fh;
X
X			       Speaker = GetDEnv("SPEAKER");
X			       if (Speaker == NULL) Speaker = DefaultSpeaker;
X			       fh = Open(Speaker,1006);
X			       if (fh) {
X				   if (strncmp(Title,"New",3) == 0)
X				       Write(fh,"You have new mail.",18);
X				   else Write(fh,"You have mail.",14);
X				   Close(fh);
X			       }
X			   }
X			   NumMsg = -1;
X			   if (Win) {
X			       WindowToFront(Win);
X			       getnewmail(chan);
X			       newimage(YOUHAVEMAIL);
X			   }
X			   if (!SpeakPlease && !WindowPlease) {
X			       Puts(Title);
X			       getnewmail(chan);
X			   }
X		    }
X		}
X	    }
X	    else if (DCheckEof(chan)) notdone = 0;
X	}
X	if (nowindow && Win) {
X	    ClearMenuStrip(Win);
X	    Nw.LeftEdge = Win->LeftEdge;
X	    Nw.TopEdge = Win->TopEdge;
X	    Nw.Width = Win->Width;
X	    Nw.Height = Win->Height;
X	    CloseWinSafely(Win);
X	    Win = NULL;
X	}
X	nowindow = 0;
X    }
X
X    freemail(MailP);
X    if (Win) {
X	ClearMenuStrip(Win);
X	CloseWinSafely(Win);
X	Win = NULL;
X    }
X}
X
X/*
X *  Utility routines.	************************************************
X */
X
Xrefreshmenu()
X
X/* Refresh the two toggle menus(Talk, Window) in the Project strip
X * according to the flags SpeakPlease and WindowPlease.
X */
X
X{
X   struct MenuItem *mn_ad;
X
X   mn_ad = (struct MenuItem *) ItemAddress(Menu,SHIFTMENU(0)|SHIFTITEM(0));
X   if (SpeakPlease) mn_ad->Flags |= CHECKED;
X   else mn_ad->Flags &= ~(CHECKED);
X   mn_ad = (struct MenuItem *) ItemAddress(Menu,SHIFTMENU(0)|SHIFTITEM(1));
X   if (WindowPlease) mn_ad->Flags |= CHECKED;
X   else mn_ad->Flags &= ~(CHECKED);
X}
X
Xnewimage(index)
X
X/* Change the mailbox icon.
X * Values of index:
X * 0 -> "You have mail", 1-> "New mail", 2-> "No mail"
X */
X
X{
X  MbImage.ImageData = &MbBitMap[index][0];
X  RefreshGList(&gadget,MbWin,NULL,1);
X}
X
X
Xgetnewmail(chan)
X
Xlong chan;
X
X/* Get all messages (headers only) from the host.
X * It will also display thoses headers using dispnewmail().
X * The magic number 1 is used to tell the server what we want.
X */
X
X{
X  unsigned char len = GETNEWMAIL;
X  struct MailMsg *p;
X  register USHORT count = 0;
X
X  if (Win) {
X      BUSYPOINTER(Win);
X      SetWindowTitles(Win,MailVersion,-1);
X  }
X  freemail(MailP);
X  if (DWrite(chan, &len, 1) == 1 && DRead(chan, &len, 1) == 1) {
X      while (len > 0) {
X	if (MailP) {
X	    p->next = AllocMem(sizeof(*p),0);
X	    p = p->next;
X	}
X	else {
X	    MailP = AllocMem(sizeof(*p),0);
X	    p = MailP;
X	}
X	if (p == NULL) break;
X	else p->next = NULL;
X	if (len < MAILLENGTH && (DRead(chan, p->msg, len) == len)) {
X	    p->msg[len-1] = '\0';
X	    DRead(chan,&len,1);
X	    count++;
X	}
X	else break;
X
X      }
X  }
X  NumMsg = count;
X  if (Win) ClearPointer(Win);
X  dispnewmail(0,0,1);
X}
X
Xdispnewmail(ONmsgno,OFFmsgno,flag)
X
XBYTE ONmsgno, OFFmsgno, flag;
X
X/* Display mail headers in a window if one is opened or on stdout otherwise.
X * ONmsgno :  msg no to be output in reverse ( 0 = none)
X * OFFmsgno:  msg no to be output normally.
X * flag    :  1 -> It's a new window, 0 -> it's an old window
X */
X
X{
X  char th, tb, tw;
X  short y, Wh, Ww, WOx, WOy;
X  int len;
X  struct MailMsg *p;
X  BYTE i=1;
X
X  p = MailP;
X  if (Win != NULL) {
X      th = Rp->TxHeight;
X      tb = Rp->TxBaseline;
X      tw = Rp->TxWidth;
X      y = Win->BorderTop;
X      Ww = Win->Width - Win->BorderRight - Win->BorderLeft;
X      Wh = Win->Height- Win->BorderTop - Win->BorderBottom;
X      WOx = Win->BorderLeft;
X      WOy = Win->BorderTop;
X      if (flag) {
X	  char buf[25], buf2[9];
X
X	  SetAPen(Rp, 0);
X	  RectFill(Rp, WOx, WOy, Ww + WOx, Wh + WOy);
X	  WindowToFront(Win);
X	  strcpy(buf2,"message");
X	  if (NumMsg > 1) strcat(buf2,"s");
X	  sprintf(buf," (%d %s)",NumMsg,buf2);
X	  if (Title[strlen(Title)-1] != ')') strcat(Title,buf);
X	  SetWindowTitles(Win, Title, -1);
X      }
X  }
X  while (p != NULL && ((Win == NULL) || ((y+tb) < Wh))) {
X    short tl;
X
X    if (! Win && flag) Puts(p->msg);
X    else { if (flag || i == ONmsgno || i == OFFmsgno) {
X	       if (ONmsgno == i) {
X		   SetBPen(Rp,2);
X		   SetAPen(Rp,0);
X	       }
X	       else {
X		   SetAPen(Rp,2);
X		   SetBPen(Rp,0);
X	       }
X	       len = strlen(p->msg);
X	       tl = TextLength(Rp,p->msg,len);
X	       if (tl > Ww) len = Ww / tw;
X	       Move(Rp,Win->BorderLeft,y+tb);
X	       Text(Rp,p->msg,len);
X	       if (ONmsgno == i) SetAPen(Rp,2);
X	       else if (OFFmsgno == i || flag) SetAPen(Rp,0);
X	       RectFill(Rp,Rp->cp_x,y,Ww+WOx,y+th-1);
X	   }
X	   y += th;
X	   i++;
X    }
X    p = p->next;
X  }
X}
X
Xdelmailmsg(chan,msgno)
X
Xlong chan;
XBYTE msgno;
X
X/* Send a command to the server asking it to delete message number msgno.
X */
X
X{
X  register BYTE i=1;
X  struct MailMsg *p = MailP;
X  char dummy[32];
X  BYTE dl = DELMAILMSG, ok;
X  unsigned long stchar = 0,nochars;
X
X  BUSYPOINTER(Win);
X  for (i=1; (i != msgno && p != NULL); i++) {
X    getmailprm(p,&nochars,dummy);
X    stchar += nochars;
X    p = p->next;
X  }
X  if (p == NULL) return();
X  getmailprm(p,&nochars,dummy);
X
X  if ((DWrite(chan,&dl,1) == 1) &&
X      (DWrite(chan,&stchar,4) == 4) &&
X      (DWrite(chan,&nochars,4) == 4) &&
X      (DRead(chan,&ok,1) == 1)) {
X      if (ok) strcpy(Title,"Delete successful ");
X      else strcpy(Title,"Delete error ");
X      getnewmail(chan);
X  }
X  ClearPointer(Win);
X}
X
Xint getmailmsg(chan,msgno,flag)
X
Xlong chan;
XBYTE msgno, flag;
X
X/* Get message number msgno from the host and take the following action
X * according to the value of flag:
X *
X *    0 -> View the message on screen (using more or the env var PAGER)
X *    1 -> Print the message on PRT:
X *    2 -> Save the message in a file.
X *    3 -> Send the message to the SPEAK: device (without the headers)
X */
X
X{
X  struct MailMsg *p = MailP;
X  BYTE i, ok=0, hd = GETMAILMSG, l, start = 0;
X  unsigned long stchar=0L, nochars, len;
X  struct FileHandle *fh;
X  ubyte *buf;
X  char pname[128], vname[100], title[132], *tmp;
X  int rcode = 1;
X  struct NewShell *NS;
X  if (NS = AllocMem(sizeof(*NS)+4096,MEMF_CLEAR)) {
X      NS->nsh_StackSize = 4000;
X      NS->nsh_Control = BACKGROUND_SHELL;
X  }
X  else return(rcode);
X  strcpy(vname,"DPIPE:Mail");
X  switch (flag) {
X    case 0:			  /* View */
X      if ((tmp = GetDEnv("PAGER")) == NULL) {
X	  strcpy(pname,"sys:utilities/more");
X      }
X      else { strcpy(pname,tmp);
X	     free(tmp);
X      }
X      strcat(pname," ");
X      strcat(pname,vname);
X      strcpy(title,"Viewing ");
X      start = 1;
X      break;
X    case 1:			 /* Print */
X      strcpy(vname,"PRT:");
X      strcpy(title,"Printing ");
X      break;
X    case 2:			 /* Save */
X      if (!(FileRequest(FileReq))) {
X	    return(rcode);}
X      strcpy(vname,FileReq->fr_Dir);
X      TackOn(vname,FileReq->fr_File);
X      strcpy(title,"Saving ");
X      strcat(title,vname);
X      break;
X    case 3:			 /* Speak */
X      tmp = GetDEnv("SPEAKER");
X      if (tmp == NULL) tmp = DefaultSpeaker;
X      strcpy(vname,tmp);
X      strcpy(title,"Speaking ");
X      break;
X  }
X  buf = (ubyte *) (NS + sizeof(*NS));
X  l = strlen(title);
X  for (i=1; (i != msgno && p != NULL); i++) {
X    getmailprm(p,&nochars,&len);
X    stchar += nochars;
X    p = p->next;
X  }
X  if (p == NULL) return(rcode);
X  getmailprm(p,&nochars,&len);
X  if (flag == 3) {stchar += len; nochars -= len; }
X  if (flag == 0) {
X      strcat(title," using ");
X      strcat(title,pname);
X  }
X  BUSYPOINTER(Win);
X  if (fh = Open(vname,1006)) {
X      if (DWrite(chan, &hd, 1) == 1 && DWrite(chan, &stchar, 4) == 4
X	  && DWrite(chan,&nochars,4) == 4) {
X	  SetWindowTitles(Win, title, -1);
X	  while (DRead(chan,&len,4) == 4 && len > 0) {
X	    if (DRead(chan,buf,len) == len) {
X		if (start) {
X		    if (ASyncRun(pname,0L,NS) < 0) {
X			ok = 1;
X			DWrite(chan,&ok,1);
X			rcode = 0;
X			break;
X		    }
X		    start = 0;
X		}
X		if (Write(fh,buf,len) != len) {
X		    ok = 1;
X		    DWrite(chan,&ok,1);
X		    rcode = 0;
X		    break;
X		}
X		DWrite(chan,&ok,1);
X	    }
X	  }
X      }
X      Close(fh);
X  }
X  else {
X	rcode = 0;
X	Printf("\nCould not open %s\n",vname);
X  }
X  SetWindowTitles(Win,Title,-1);
X  FreeMem(NS,sizeof(*NS)+4096);
X  ClearPointer(Win);
X  return(rcode);
X}
X
Xint editmessage(chan,msgno)
X
Xlong *chan;
XUBYTE msgno;
X
X/* Reply to message number msgno using ed or the env var EDITOR.
X * A temporary file in the T: directory is used.
X *
X * Still buggy for unknown reasons.
X */
X
X{
X  char *buf, fname[32];
X  struct MailMsg *p = MailP;
X  int ok = 0, test;
X  struct FileInfoBlock *fileinfo;
X  struct FileLock *lock;
X  struct FileHandle *fh = NULL;
X  LONG len;
X  short count;
X  BYTE hd = EDITMESSAGE, i;
X
X  if (!(fileinfo = AllocMem(sizeof(struct FileInfoBlock)+BUFLENGTH,0)))
X      return(ok);
X  buf = (char *) (fileinfo + sizeof(struct FileInfoBlock));
X  strcpy(fname,"T:MailChk");
X  strcpy(Title,"Replying...");
X  SetWindowTitles(Win,Title,-1);
X  if (GetDEnv("EDITOR") != NULL) strcpy(buf,GetDEnv("EDITOR"));
X  else strcpy(buf,"ed");
X  BUSYPOINTER(Win);
X  if (SyncRun(buf,fname,0,0) >= 0) {
X      if (((lock = Lock(fname,ACCESS_READ)) != 0) &&
X	Examine(lock,fileinfo)) {
X	len = fileinfo->fib_Size;
X	UnLock(lock);
X	strcpy(Title,"Could not open tmp file");
X	if (!(fh = Open(fname,1005))) goto fin;
X	strcpy(Title,"Inconsistency error");
X	for (i=1; (i != msgno && p != NULL); i++)
X	     p = p->next;
X	if (p == NULL) goto fin;
X	sscanf(p->msg+1,"%d %s",&test,buf);
X	if (test != msgno) goto fin;
X	strcpy(Title,"Transmission error");
X	if (DWrite(chan,&hd,1) != 1) goto fin;
X	count = strlen(buf);
X	if (DWrite(chan,&count,2) != 2) goto fin;
X	if (DWrite(chan,buf,count) != count) goto fin;
X	if (DWrite(chan,&len,4) != 4) goto fin;
X	do {
X	  count = Read(fh,buf,BUFLENGTH);
X	  if (count > 0 && DWrite(chan,buf,count) != count) goto fin;
X	} while (count == BUFLENGTH);
X	strcpy(Title,"Remote error");
X	if (DRead(chan,&ok,1) != 1) ok = 0;
X      }
X      else {
X	  strcpy(Title,"Reply function cancelled");
X	  goto fin2;
X      }
X  }
X  else { sprintf(Title,"Editor %s not found",buf);
X	 goto fin2;
X  }
Xfin:
X  if (fh) Close(fh);
X  if (ok) {
X      DeleteFile(fname);
X      strcpy(Title,"Reply was suscessful");
X  }
X  else {
X      DeleteFile("T:dead.letter");
X      Rename(fname,"T:dead.letter");
X      strcat(Title," - Letter is in T:dead.letter");
X  }
Xfin2:
X  SetWindowTitles(Win,Title,-1);
X  ClearPointer(Win);
X  FreeMem(fileinfo,sizeof(struct FileInfoBlock)+BUFLENGTH);
X  return(ok);
X}
X
Xgetmailprm(p,nochars,len)
X
Xstruct MailMsg *p;
Xunsigned long *nochars, *len;
X
X/* Extract the no of chars (nochars) from a particular header (pointed to
X * by p) in the message and the no of chars without the header lines
X * (len).
X */
X
X{
X  char *str;
X
X  if (str = rindex(p->msg,'/')) {
X      sscanf(++str,"%ld %ld",nochars,len);
X  }
X  else *nochars = 0;
X}
X
Xfreemail(p)
X
Xstruct MailMsg *p;
X
X/* Free all the memory used by the linked list
X */
X
X{
X  while (p != NULL) {
X    FreeMem(p,sizeof(*p));
X    p = p->next;
X  }
X  MailP = NULL;
X  NumMsg = 0;
X}
X
XCloseWinSafely(win)
X
XWIN *win;
X
X/* From RKM 1.3.
X * Close window win safely when it shares an IDCMP port with other
X * windows.
X */
X
X{
X  Forbid();
X  StripIntuiMessages(win->UserPort,win);
X  win->UserPort = NULL;
X  ModifyIDCMP(win,0);
X  Permit();
X  CloseWindow(win);
X}
X
XStripIntuiMessages(mp,win)
X
XPORT *mp;
XWIN *win;
X
X/* From RKM 1.3 */
X
X{
X  IMESS *msg, *succ;
X
X  msg = (IMESS *) mp->mp_MsgList.lh_Head;
X  while (succ = (IMESS *) msg->ExecMessage.mn_Node.ln_Succ) {
X    if (msg->IDCMPWindow == win) {
X	Remove(msg);
X	ReplyMsg(msg);
X    }
X    msg = succ;
X  }
X}
X
END_OF_FILE
if test 23145 -ne `wc -c <'amiga/client/mailchk.c'`; then
    echo shar: \"'amiga/client/mailchk.c'\" unpacked with wrong size!
fi
# end of 'amiga/client/mailchk.c'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.