home *** CD-ROM | disk | FTP | other *** search
- /*
- * AnyMail -x MailReadyFileName -c Command -e user/pattern -i user/pattern ...
- *
- * (C) Copyright 1990 by Chris Hind Genly, chris@genly.uucp
- *
- * 1.0
- * ---
- * - Original version. Written by Chris Hind Genly. Major hacks by
- * Matt Dillon.
- *
- * 1.1
- * ---
- * - Empty mail files are no longer listed.
- * - Pattern matching is now case insensitive.
- * - LockFile() is used on files in uumail:
- * - Display is updated after each mail file is scanned, rather than after
- * all of uumail: is scanned.
- */
-
- #include <exec/types.h>
- #include <exec/lists.h>
- #include <exec/ports.h>
- #include <exec/memory.h>
- #include <dos/dos.h>
- #include <dos/exall.h>
- #include <intuition/classes.h>
- #include <intuition/intuition.h>
- #include <pragmas/intuition_pragmas.h>
-
- #include <graphics/graphint.h>
- #include <graphics/scale.h>
- #include <graphics/gfxbase.h>
- #include <pragmas/graphics_pragmas.h>
-
- #include <clib/dos_protos.h>
- #include <clib/exec_protos.h>
- #include <clib/intuition_protos.h>
- #include <clib/graphics_protos.h>
- #define LIBRARIES_MATHFFP_H
- #include <clib/alib_protos.h>
- #undef LIBRARIES_MATHFFP_H
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include "protos.h"
- #include "config.h"
- #include "version.h"
- #include <owndevunit.h>
-
- #ifndef __SASC
- char *strlwr(char *);
- #endif
-
- typedef struct Node Node;
- typedef struct List List;
- typedef struct Window Window;
- typedef struct RastPort RPort;
- typedef struct MsgPort MsgPort;
-
- /* 1.1 */
- #define LOWERCHAR(c) ('A' <= (c) && (c) <= 'Z' ? (c)-'A'+'a' : (c))
-
- /*
- * ONode is used to track each file that has been scanned and contains
- * a list of messages already scanned for the file.
- */
-
- typedef struct ONode {
- Node on_Node; /* name of file / link node */
- List on_List; /* message list for file */
- long on_Offset; /* offset for last valid message */
- long on_EndOffset; /* end of file (check if appended to) */
- long on_MsgNo; /* last message # */
- } ONode;
-
- #define on_Succ on_Node.ln_Succ
- #define on_Name on_Node.ln_Name
-
- Window *Win; /* intuition window */
- MsgPort *SigPort; /* signal port for sendmail */
- List FilList; /* file-name list */
- List Excludes;
- List Includes;
- int Count;
- BPTR MailLock;
- char Buf[256];
- char Title[256];
-
- struct Library *OwnDevUnitBase;
- struct IntuitionBase *IntuitionBase;
- struct GfxBase *GfxBase;
-
- IDENT(".05");
-
- struct NewWindow Nw = {
- 40, 10, 560, 180, (unsigned char)-1, (unsigned char)-1,
- IDCMP_CLOSEWINDOW | IDCMP_REFRESHWINDOW | IDCMP_MOUSEBUTTONS,
- WINDOWCLOSE | WINDOWDRAG | WINDOWSIZING | SIMPLE_REFRESH | WINDOWDEPTH,
- NULL, NULL,
- (UBYTE *) "AnyMail Version 1.0 You have mail",
- NULL, /* Screen */
- NULL, /* BitMap */
- 30, 30, (unsigned short)-1, (unsigned short)-1, WBENCHSCREEN
- };
-
- int Init(void);
- int TimeToRepeat(int *);
- int OkToScan(struct FileInfoBlock *);
- void MakeNode(struct List *, char *);
- void Display(void);
- void Terminate(void);
- void SaveConfig(Window *);
- void LoadConfig(struct NewWindow *);
- long AnyMail(char *, ONode *);
- char *FromName(char *);
- char *ExtractPersonalName(char *);
- ONode *GetONode(char *);
- int amatch(char *, char *, int *);
-
- /*
- * A FileInfoBlock structure MUST be longword aligned.
- */
-
- char *MailRdyName;
- struct FileInfoBlock *Fib;
-
- int main (int argc, char **argv)
- {
- int i;
- char *command = 0;
- int doCommand = FALSE;
-
- Fib = (struct FileInfoBlock *)malloc(sizeof(struct FileInfoBlock));
- NewList(&Excludes);
- NewList(&Includes);
- NewList(&FilList);
-
- atexit(Terminate);
-
- if ((OwnDevUnitBase = OpenLibrary ((UBYTE *) ODU_NAME, 0)) == NULL) {
- puts("Couldn't open lock library");
- exit(20);
- }
-
- for (i = 1; i < argc; ++i) {
- if (stricmp(argv[i], "-x") == 0) {
- MailRdyName = argv[++i];
- } else if (stricmp(argv[i], "-e") == 0) {
- MakeNode(&Excludes, argv[++i]);
- } else if (stricmp(argv[i], "-i") == 0) {
- MakeNode(&Includes, argv[++i]);
- } else if (stricmp(argv[i], "-c") == 0) {
- command = argv[++i];
- } else {
- fprintf(stderr, "AnyMail: Unknown keyword %s\n", argv[i]);
- }
- }
- if (MailRdyName)
- SigPort = CreatePort ((UBYTE *) MailRdyName, 1);
-
- if (Init()) {
- while (TimeToRepeat(&doCommand)) {
- ONode *onf;
- long offset;
-
- MailLock = Lock ((UBYTE *) GetConfigDir (UUMAIL), ACCESS_READ);
- if (!MailLock) /* unrecoverable error */
- break;
- if (Examine(MailLock, Fib)) {
- while (ExNext(MailLock, Fib)) {
- if (!OkToScan(Fib))
- continue;
- onf = GetONode(Fib->fib_FileName);
- if (onf->on_EndOffset < Fib->fib_Size) {
- onf->on_EndOffset = Fib->fib_Size;
- offset = AnyMail(Fib->fib_FileName, onf);
- if (onf->on_Offset != offset) {
- Display();
- onf->on_Offset = offset;
- }
- }
- }
- } else {
- break;
- }
- UnLock(MailLock);
- MailLock = 0;
- }
- }
-
- if (doCommand && command)
- Execute ((UBYTE *) command, 0, 0);
-
- return(0);
- }
-
- int
- OkToScan(struct FileInfoBlock *fib)
- {
- Node *n;
- char *fileName;
- int cnt;
-
- if (fib->fib_DirEntryType >= 0)
- return FALSE;
-
- for (n = Includes.lh_Head; n->ln_Succ; n = n->ln_Succ) {
- fileName = fib->fib_FileName;
- strlwr(fileName);
- if (amatch(fileName, n->ln_Name, &cnt) && cnt == strlen(fileName))
- return(TRUE);
- }
-
- for (n = Excludes.lh_Head; n->ln_Succ; n = n->ln_Succ) {
- fileName = fib->fib_FileName;
- strlwr(fileName);
- if (amatch(fileName, n->ln_Name, &cnt) && cnt == strlen(fileName))
- return(FALSE);
- }
-
- return(TRUE);
- }
-
- int
- Init (void)
- {
- IntuitionBase = (struct IntuitionBase *) OpenLibrary ((UBYTE *) "intuition.library", 0);
- if (IntuitionBase == 0) {
- fprintf(stderr, "AnyMail: Unable to open intuition.library\n");
- return(0);
- }
-
- GfxBase = (struct GfxBase *) OpenLibrary ((UBYTE *) "graphics.library", 0);
- if (GfxBase == 0) {
- fprintf(stderr, ": Unable to open graphics.library\n");
- return(0);
- }
-
- return(1);
- }
-
- int
- TimeToRepeat(int *DoCommand)
- {
- struct IntuiMessage *im;
- int done = FALSE;
- int repeat = FALSE;
- long windowMask;
- long portMask;
- long mask;
-
- if (Win == NULL) {
- Display();
- return(TRUE);
- }
-
- windowMask = 1 << Win->UserPort->mp_SigBit;
-
- if (SigPort)
- portMask = 1 << SigPort->mp_SigBit;
- else
- portMask = 0;
-
- while (!done) {
- mask = Wait(windowMask|portMask|SIGBREAKF_CTRL_C);
-
- if (mask & windowMask) {
- while (im = (struct IntuiMessage *)GetMsg(Win->UserPort)) {
- switch(im->Class) {
- case MOUSEBUTTONS:
- if (im->Code == SELECTDOWN) {
- *DoCommand = TRUE;
- done = TRUE;
- }
- break;
- case REFRESHWINDOW:
- BeginRefresh(Win);
- EndRefresh(Win, TRUE);
- Display();
- break;
- case CLOSEWINDOW:
- done = TRUE;
- break;
- }
- ReplyMsg((struct Message *)im);
- }
- }
- if (mask & portMask) {
- repeat = TRUE;
- done = TRUE;
- }
- if (mask & SIGBREAKF_CTRL_C)
- exit(1);
- }
-
- return repeat;
- }
-
- long
- AnyMail (char *user, ONode *onf)
- {
- static char FromLine[256];
- static char SubjLine[256];
- char *file = malloc(strlen(user) + 32);
- FILE *fi;
- long msgno = 0;
- long offset = onf->on_Offset;
-
- if ('a' <= user[0] && user[0] <= 'z')
- user[0] = user[0] - 'a' + 'A';
-
- strcpy(file, MakeConfigPath(UUMAIL, user));
-
- LockFile(file); /* 1.1 */
-
- if (fi = fopen(file, "r")) {
- if (fseek(fi, offset, SEEK_SET) < 0) {
- fclose(fi);
- UnLockFile(file); /* 1.1 */
- return offset;
- }
- while (fgets(Buf, sizeof(Buf), fi)) {
- /*
- * Start of message
- */
-
- if (strncmp(Buf, "From ", 5) != 0)
- continue;
-
- ++msgno;
-
- /*
- * Scan headers for From: and Subject:
- * Headers end with a blank line.
- */
-
- FromLine[0] = 0;
- SubjLine[0] = 0;
-
- while (fgets(Buf, sizeof(Buf), fi) && Buf[0] != '\n') {
- if (strncmp(Buf, "From:", 5) == 0)
- strcpy(FromLine, Buf + 5);
- if (strncmp(Buf, "Subject:", 8) == 0)
- strcpy(SubjLine, Buf + 8);
- }
-
- /* Remove the trailing new line from the subject */
-
- if (SubjLine[0])
- SubjLine[strlen(SubjLine)-1] = 0;
-
- /*
- * (try) Make sure we didn't read the file just as sendmail
- * was appending to it.
- */
-
- if (!feof(fi)) {
- sprintf(Buf, "%-2d %-20.20s %s",
- ++onf->on_MsgNo,
- FromName(FromLine),
- SubjLine
- );
- MakeNode(&onf->on_List, Buf);
- ++Count;
- offset = ftell(fi);
- }
- }
- fclose(fi);
- }
-
- UnLockFile(file); /* 1.1 */
-
- return offset;
- }
-
- void
- Display(void)
- {
- int xmin, xmax, ymin, ymax, x, y;
- int len, lenmax;
- ONode *onf;
- Node *node;
- RPort *rp;
-
- if (Win == NULL) {
- LoadConfig(&Nw);
- Win = OpenWindow(&Nw);
- if (Win == NULL) {
- Nw.LeftEdge = 40;
- Nw.TopEdge = 10;
- Nw.Width = 560;
- Nw.Height= 180;
- Win = OpenWindow(&Nw);
- }
- if (Win == NULL)
- return;
-
- }
- rp = Win->RPort;
-
- xmin = Win->BorderLeft;
- ymin = Win->BorderTop;
- xmax = Win->Width - Win->BorderRight - 1;
- ymax = Win->Height - Win->BorderBottom - 1;
-
- if (xmin < xmax && ymin < ymax) {
- SetAPen(rp, 0);
- RectFill(rp, xmin, ymin, xmax, ymax);
- }
-
- x = xmin + 2;
- y = ymin + 4;
- lenmax = (xmax-xmin+1)/GfxBase->DefaultFont->tf_XSize;
-
- SetAPen(rp, 1);
- SetBPen(rp, 0);
-
- for (onf = (ONode *)FilList.lh_Head; onf->on_Succ; onf = (ONode *)onf->on_Succ) {
-
- if (onf->on_List.lh_Head->ln_Succ == 0) /* 1.1 */
- continue; /* 1.1 */
-
- /*
- * display 'To filename', then messages for this file
- */
-
- {
- if (y + GfxBase->DefaultFont->tf_YSize > ymax)
- break;
- sprintf(Buf, "To %s", onf->on_Name);
- len = strlen(Buf);
- if (len > lenmax)
- len = lenmax;
- Move(rp, x, y + GfxBase->DefaultFont->tf_Baseline);
- SetDrMd(rp, COMPLEMENT);
- Text (rp, (UBYTE *) Buf, len);
- SetDrMd(rp, JAM2);
- y += GfxBase->DefaultFont->tf_YSize;
- }
- for (node = onf->on_List.lh_Head; node->ln_Succ; node = node->ln_Succ) {
- if (y + GfxBase->DefaultFont->tf_YSize > ymax)
- break;
- len = strlen(node->ln_Name);
- if (len > lenmax)
- len = lenmax;
- Move (rp, x, y + GfxBase->DefaultFont->tf_Baseline);
- Text (rp, (UBYTE *) node->ln_Name, len);
- y += GfxBase->DefaultFont->tf_YSize;
- }
- }
- sprintf(Title, "AnyMail Version 1.1 You have %d message%s waiting.",
- Count,
- (Count==1) ? "" : "s"
- );
- SetWindowTitles (Win, (UBYTE *) Title, 0);
- }
-
- void
- Terminate(void)
- {
- if (Win) {
- SaveConfig(Win);
- CloseWindow(Win);
- Win = NULL;
- }
-
- if (GfxBase) {
- CloseLibrary ((struct Library *) GfxBase);
- GfxBase = NULL;
- }
-
- if (IntuitionBase) {
- CloseLibrary ((struct Library *) IntuitionBase);
- IntuitionBase = NULL;
- }
-
- if (MailLock) {
- UnLock(MailLock);
- MailLock = 0;
- }
-
- /*
- * delete sigport before removing file
- */
-
- if (SigPort) {
- DeletePort(SigPort);
- SigPort = NULL;
- }
-
- UnLockFiles();
-
- if (OwnDevUnitBase) {
- CloseLibrary(OwnDevUnitBase);
- OwnDevUnitBase = NULL;
- }
-
- if (MailRdyName)
- remove(MailRdyName);
- }
-
- /*
- * The real name is between parens. If it can't be found, use the
- * whole from line
- */
-
- char *
- FromName (char *fromLine)
- {
- char *start;
- char *end;
-
- start = strchr(fromLine, '(');
- if (start) {
- start++;
- end = strchr(start, ')');
- if (end) {
- *end = 0;
- return(start);
- }
- }
- end = strchr(fromLine, '\n');
- if (end)
- *end = 0;
- return(fromLine);
- }
-
- void
- MakeNode (List *list, char *name)
- {
- Node *node;
-
- if (node = malloc(sizeof(Node) + strlen(name) + 1)) {
- node->ln_Name = (char *)(node + 1);
- strcpy(node->ln_Name, name);
- }
- AddTail(list, node);
- }
-
- ONode *
- GetONode (char *name)
- {
- ONode *onf;
-
- for (onf = (ONode *) FilList.lh_Head; onf->on_Succ; onf = (ONode *)onf->on_Succ) {
- if (stricmp(name, onf->on_Name) == 0)
- break;
- }
- if (onf->on_Succ == NULL) {
- onf = malloc (sizeof (ONode) + strlen (name) + 1);
- setmem (onf, sizeof (ONode), 0);
- onf->on_Name = (char *) (onf + 1);
- strcpy (onf->on_Name, name);
- NewList (&onf->on_List);
- AddTail (&FilList, (struct Node *) onf);
- }
- return onf;
- }
-
- int CfgLE;
- int CfgTE;
- int CfgW;
- int CfgH;
-
- void
- LoadConfig (struct NewWindow *nw)
- {
- FILE *fi;
- if (fi = fopen("S:AnyMail.config", "r")) {
- fscanf(fi, "%d %d %d %d", &CfgLE, &CfgTE, &CfgW, &CfgH);
- nw->LeftEdge = CfgLE;
- nw->TopEdge = CfgTE;
- nw->Width = CfgW;
- nw->Height = CfgH;
- fclose(fi);
- }
- }
-
- void
- SaveConfig (Window *win)
- {
- FILE *fi;
-
- if (CfgLE != win->LeftEdge || CfgTE != win->TopEdge || CfgW != win->Width || CfgH != win->Height) {
- if (fi = fopen("S:AnyMail.config", "w")) {
- fprintf(fi, "%d %d %d %d\n", win->LeftEdge, win->TopEdge, win->Width, win->Height);
- fclose(fi);
- }
- }
- }
-
- /*
- * Match the pattern, p, against the start of the string, s.
- * Return TRUE if there is a match, FALSE if not. If there is a match, set
- * cnt to the number of characters matched.
- *
- * ? Matches any character
- * #p Maches zero or more ps, where p is a pattern not starting with #.
- */
- int
- amatch(
- char *s, /* The string to match */
- char *p, /* The pattern to match against */
- int *cnt
- )
- {
- char *bas = s;
- char buff[2];
- int cnt1, cnt2;
-
- while(*p) {
- switch(*p) {
- default:
- /* 1.1 uses LOWERCHAR() */
- if (LOWERCHAR(*s) == LOWERCHAR(*p)) ++s, ++p;
- else return FALSE;
- break;
- case '?':
- if (*s) ++s, ++p;
- else return FALSE;
- break;
- case '#':
- if (p[1] == 0) return FALSE; /* Syntax error */
-
- buff[0] = p[1]; buff[1] = '\0';
- if (amatch(s, buff, &cnt1) && amatch(s+cnt1, p, &cnt2)) {
- *cnt = s-bas + cnt1 + cnt2;
- return TRUE;
- } else
- p += 2;
- break;
- }
- }
-
- *cnt = s-bas;
-
- return TRUE;
- }
-
- #ifndef __SASC
-
- char *
- strlwr(s)
- char *s;
- {
- char *b;
-
- for (b = s; *b; ++b) {
- if (*b >= 'A' && *b <= 'Z')
- *b |= 0x20;
- }
- return(s);
- }
- #endif
-