home *** CD-ROM | disk | FTP | other *** search
- #include "defs.h"
- #include "memalloc.h"
- #include "headers.h"
-
- #include <stdarg.h>
-
- // #define PROCDEBUG
-
- #ifdef PROCDEBUG
- #define D(x) printf x
- #else
- #define D(x)
- #endif
-
- extern char *FileNameToNewsGroup (char *filename); /* IMPORT */
- extern char *NewsGroupToFileName (char *newsgroup); /* IMPORT */
- extern int BuildHierarchicalList (void); /* IMPORT */
-
- int hierarchical = 0; /* EXPORT */
- /* should be set by ONLY SetHierarchical() */
- int subscribe_mode = 0;
- /* subscribe to new groups first! */
- char **subscribe_list;
- /* list of new newsgroups to subscribe to */
- int subscribe_count;
- /* how many in the list */
- int update_only_mode = 0;
- /* only update grnrc file, then exit. No windows, no nothing. */
-
- ULONG grnrcVersion = '1.20';
- UWORD windowHeight;
- UWORD wrapCol = 82; // selectable wrap point for articles
-
- /************************************************************************/
-
- FILEREQ *saveReq = 0;
- FILEREQ *publishReq = 0;
-
- static MPORT *port = 0;
- char userName[256], grnrcName[256];
- char newsEditor[256], mailEditor[256];
- char postNews[256], sendMail[256];
- char uunews[256] = "UUNEWS:";
- char uulib[256] = "UULIB:";
- char uuspool[256] = "UUSPOOL:";
- char logfile[256] = "";
-
- BOOL treeDirty = 0;
-
- LIST groupList;
-
- LOCK lock = 0;
- FIB *fib = 0;
-
- WINDOW *mainWindow = 0;
-
- UWORD mode = GROUPS_MODE;
-
- void ClearWindow (void)
- {
- WORD x, y, x1, y1;
-
- x = mainWindow->BorderLeft;
- y = mainWindow->BorderTop;
- x1 = mainWindow->Width - mainWindow->BorderRight - 1;
- y1 = mainWindow->Height - mainWindow->BorderBottom - 1;
-
- SetAPen( mainWindow->RPort, 0);
- SetDrMd( mainWindow->RPort, JAM1 );
- RectFill( mainWindow->RPort, x, y, x1, y1 );
-
- RefreshWindowFrame (mainWindow);
- return;
- }
-
- void CloseMain (void)
- {
- if (publishReq) {
- FreeFileRequest (publishReq);
- publishReq = 0;
- }
- if (saveReq) {
- FreeFileRequest (saveReq);
- saveReq = 0;
- }
- if (fib) {
- FreeDosObject (DOS_FIB, (void *) fib);
- fib = 0;
- }
- if (lock) {
- UnLock (lock);
- lock = 0;
- }
- if (mainWindow) {
- CloseWindow (mainWindow);
- mainWindow = 0;
- }
- return;
- }
-
- /*
- * void Abort(void);
- *
- * Synopsis:
- * Cleanup and exit. Can be called anywhere, anytime, including from
- * the debugger by setting PC = Abort.
- */
- long abort_code = 0;
-
- void Abort (void)
- {
- CloseGroups ();
- CloseMain ();
- if (port) {
- DeletePort (port);
- port = 0;
- }
- CloseSystem ();
- exit (abort_code);
- }
-
- /*
- * void panic0(v, s,a1,a2,a3,a4);
- * ULONG v;
- * char *s;
- * ULONG a1,a2,a3,a4;
- *
- * Synopsis:
- * Anywhere you use:
- * v = (some function);
- * if (!v) {
- * printf("some string");
- * Abort();
- * }
- * You can use:
- * v = (some function);
- * panic0(v, "some string");
- * The string and args (a1,a2,a3,a4) are passed to printf...
- */
- void panic0 (APTR v, const char *s, ...)
- {
- FILE *outfp;
- va_list va;
-
- va_start (va, s);
- if (v)
- return;
- printf ("Panic: ");
- _pfmt (s, va, fwrite, stdout);
- printf ("\n");
- if (logfile [0] == '\0')
- strcpy (logfile, "UUSPOOL:logfile");
- outfp = fopen (logfile, "a");
- if (outfp) {
- fprintf (outfp, "GRn panic: ");
- _pfmt (s, va, fwrite, outfp);
- fprintf (outfp, "\n");
- fclose (outfp);
- }
- va_end (va);
- abort_code = 999;
- Abort ();
- /* NOTREACHED */
- return;
- }
-
- void panic (const char *s, ...)
- {
- FILE *outfp;
- va_list va;
-
- va_start (va, s);
- printf ("Panic: ");
- printf (s, va);
- _pfmt (s, va, fwrite, stdout);
- printf ("\n");
- if (logfile [0] == '\0')
- strcpy (logfile, "UUSPOOL:logfile");
- outfp = fopen(logfile, "a");
- if (outfp) {
- fprintf (outfp, "GRn panic: ");
- _pfmt (s, va, fwrite, outfp);
- fprintf (outfp, "\n");
- fclose (outfp);
- }
- va_end (va);
- abort_code = 999;
- Abort ();
- /* NOTREACHED */
- return;
- }
-
- /************************************************************************/
-
- UBYTE *mbuf = 0, *mbufp, *mbufe;
-
- void mclose (void)
- {
- if (mbuf) {
- free (mbuf);
- mbuf = 0;
- }
- return;
- }
-
- BOOL mopen (char *fn)
- {
- int fd;
- ULONG size;
-
- mclose ();
- fd = open (fn, O_READ);
- if (fd < 0)
- return 0;
-
- size = lseek (fd, 0, 2);
- lseek (fd, 0, 0);
- mbuf = (UBYTE *) malloc (size);
- if (!mbuf) {
- close (fd);
- return 0;
- }
- read (fd, mbuf, size);
- close (fd);
- mbufp = mbuf;
- mbufe = &mbufp[size];
- return 1;
- }
-
- BOOL mread (UBYTE *buf, ULONG size)
- {
- ULONG i;
-
- if (!mbuf || mbufp == mbufe)
- return 0;
- for (i = 0; i < size; i++)
- *buf++ = (mbufp == mbufe) ? 0 : *mbufp++;
- return 1;
- }
-
- BOOL mgets (UBYTE *buf)
- {
- if (mbufp == mbufe)
- return 0;
- while (mbufp != mbufe && (*buf++ = *mbufp++));
- *buf = '\0';
- return 1;
- }
-
- /************************************************************************/
-
- BOOL EmptyList (LIST *list)
- {
- if (list->lh_TailPred == (NODE *)list)
- return !0;
- return 0;
- }
-
- NODE *FindListItem (LIST *list, short num)
- {
- NODE *np;
-
- for (np = list->lh_Head; np->ln_Succ; np = np->ln_Succ) {
- if (!num)
- return np;
- num--;
- }
- return 0;
- }
-
- void SortList (LIST *list, short col)
- {
- LIST tmp;
- register NODE *np;
- register NODE *np2;
- register char *pname;
-
- if (EmptyList (list))
- return;
- NewList (&tmp);
-
- while (!EmptyList (list)) {
- np = RemHead (list);
- if (EmptyList (&tmp)) {
- AddHead (&tmp, np);
- }
- else {
- pname = &np->ln_Name [col];
- if (strcmp (pname, &tmp.lh_Head->ln_Name [col]) < 0) {
- AddHead (&tmp, np);
- }
- else if (strcmp (pname, &tmp.lh_TailPred->ln_Name [col]) > 0) {
- AddTail (&tmp, np);
- }
- else {
- for (np2 = tmp.lh_Head; np2->ln_Succ; np2 = np2->ln_Succ) {
- if (strcmp (pname, &np2->ln_Name [col]) < 0) {
- Insert (&tmp, np, np2->ln_Pred);
- break;
- }
- }
- }
- }
-
- }
- NewList (list);
- while (!EmptyList (&tmp)) {
- np = RemHead (&tmp);
- AddTail (list, np);
- }
- return;
- }
-
- /************************************************************************/
-
- void FixName (char *dst, char *src)
- {
-
- #define CHK_SIZE_ERR(x,p) if ((int) (p) >= 512) OutputStrings (2, "FixName error (", itoa (x), ") string too big: ", itoa ((int) (dst - d)), " bytes '", d, "'\n", NULL);
-
- short i, j;
- BOOL ltFlag = 0;
- char *d = dst;
- short pcount = 0;
-
- // D (("FixName: enter\n"));
-
- for (i = 0; src [i]; i++)
- if (src [i] == '<') {
- ltFlag = 1;
- break;
- }
-
- if (*src == '"') {
- // From: "Some Quoted Horror" <mbs@adastra.cvl.va.us>
- for (j = 1; src [j] && src [j] != '"'; j++)
- *dst++ = src [j];
- *dst++ = '\0';
- CHK_SIZE_ERR (1, (dst - d));
- return;
- }
- if (*src == '<') {
- // From: <mbs@adastra.cvl.va.us> (Michael B. Smith)
- // -or-
- // From: <mbs@adastra.cvl.va.us> Michael B. Smith
- // This piece could be better....
- for (j = 1; src [j] && src [j] != '@' && src [j] != '>'; j++) {
- if (src [j] == '.')
- *dst++ = ' ';
- else
- *dst++ = src [j];
- }
- *dst++ = '\0';
- CHK_SIZE_ERR (2, (dst - d));
- return;
- }
- for (j = 0; src [j]; j++) {
- if (src [j] == '<') {
- if (!j) {
- OutputStrings (2, "Should never happen\n", NULL);
- CHK_SIZE_ERR (3, strlen (src));
- strncpy (dst, src, 512);
- return;
- }
- else {
- // From: Michael B. Smith <mbs@adastra.cvl.va.us>
- for (i = 0; i < j; i++)
- *dst++ = *src++;
- *dst++ = '\0';
- CHK_SIZE_ERR (4, (dst - d));
- return;
- }
- }
-
- // example nested parens: (Blonder (The one and Only :))
- if (src[j] == '(' && !ltFlag) {
- pcount++;
- j++;
- while (src [j] && pcount) {
- switch (src [j]) {
- case ')':
- pcount--;
- if (pcount)
- *dst++ = src [j];
- j++;
- break;
- case '(':
- pcount++;
- default:
- *dst++ = src [j++];
- break;
- }
- }
- *dst++ = '\0';
- CHK_SIZE_ERR (5, (dst - d));
- return;
- }
- }
- j = -1;
- for (i = 0; src [i]; i++)
- if (src [i] == '!')
- j = i;
- #if 1
- if (j < 0)
- d = src;
- else
- d = &src [j + 1];
-
- while (*d && *d != ',' && *d != '@' && *d !='%')
- *dst++ = *d++;
- *dst++ = '\0';
- #else
- if (j != -1) {
- j++;
- while (src [j] && src [j] != ',' && src [j] != '@')
- *dst++ = src [j++];
- *dst++ = '\0';
- }
- else {
- while (*src && *src != '%' && *src != '@')
- *dst++ = *src++;
- *dst++ = '\0';
- }
- #endif
- CHK_SIZE_ERR (6, (dst - d));
- // D (("FixName: exit\n"));
- return;
- }
-
- #undef CHK_SIZE_ERR
-
- /************************************************************************/
-
- void SetHierarchical (void)
- {
- BPTR lock;
-
- // This routine finds out if we are hierarchical or not
- // and sets the global variable 'hierarchical' appropriately.
- //
- // The way things are set up, this causes a slight performance
- // hit on non-hierarchical systems.
- //
- // uses the global fib
-
- lock = Lock (uunews, SHARED_LOCK);
- panic0 ((APTR) lock, "Lock (%s) failed", uunews);
-
- hierarchical = 1; /* presume globally true, until proven otherwise */
- Examine (lock, fib);
- while (ExNext (lock, fib)) {
- if (fib->fib_DirEntryType < 0)
- continue;
- if (hierarchical && strchr (fib->fib_FileName, '.') == NULL) {
- /* This is the first directory (ALL modern newsgroups */
- /* have more than one level. So if the structure is */
- /* flat, and it WASNT hierarchical, we wouldn't get */
- /* here because it would have a period in it). If it */
- /* is hierarchical, then do the hierarchical thing */
- /* and then get out of here....as our initial guess */
- /* was correct. */
-
- // unless this system is running C-News. <sigh>
- if (strcmp (fib->fib_FileName, "in.coming") == 0)
- continue;
- if (strcmp (fib->fib_FileName, "out.going") == 0)
- continue;
-
- break;
- }
- hierarchical = 0;
- break;
- }
- UnLock (lock);
-
- return;
- }
-
- /************************************************************************/
-
- #define MOVE4(x) { *p++ = ((x >> 24) & 0xff); *p++ = ((x >> 16) & 0xff); *p++ = ((x >> 8) & 0xff); *p++ = (x & 0xff); }
- #define MOVE2(x) { *p++ = ((x >> 8) & 0xff); *p++ = (x & 0xff); }
- #define MOVE1(x) { *p++ = (x & 0xff); }
- #define MOVESTR(x) { p2 = x; while (*p2) *p++ = *p2++; *p++ = '\0'; }
-
- void WriteNewsTree (void)
- {
- int fd;
- int do_it_the_hard_way = 0;
- ART *ap;
- GLIST *gp;
- UWORD end = END;
- char *memoryfile;
- register ULONG pct;
- register ULONG artCount = 0;
- register ULONG groupSize = 0;
- register ULONG artSize = 0;
- long len;
- long offset;
-
- extern ULONG totalArticles;
- extern ULONG totalGroups;
-
- D (("WriteNewsTree: enter\n"));
-
- if (!treeDirty)
- return;
-
- if ((fd = creat (grnrcName, 0660)) < 0) {
- // don't panic() since the user might can correct the problem!
- t_printf ("Can't open %s for output!!!!", grnrcName);
- D (("WriteNewsTreee: exit, can't open grnrc\n"));
- return;
- }
-
- t_printf (mainWindow, "Building in-core copy of %s", grnrcName);
-
- for (gp = (GLIST *) groupList.lh_Head;
- gp->node.ln_Succ;
- gp = (GLIST *) gp->node.ln_Succ) {
-
- groupSize += strlen (gp->groupName) + 11;
-
- for (ap = (ART *)gp->artList.lh_Head;
- ap->node.ln_Succ;
- ap = (ART *)ap->node.ln_Succ) {
-
- artSize += strlen (ap->from) +
- strlen (ap->subject) + 8;
- }
- }
- // printf ("Memoryfile size = %d\n", groupSize + artSize);
-
- memoryfile = malloc (groupSize + artSize + 5);
-
- // Output the data. If we can't get enough memory, then output
- // grnrc the old way.
-
- if (!memoryfile) {
- do_it_the_hard_way = 1;
- D (("WriteNewsTree: can't get memory\n"));
- }
- else {
- register char *p = memoryfile;
- register char *p2;
-
- // t_printf (mainWindow, "Building in-core copy of your grnrc");
-
- MOVE4 (grnrcVersion);
-
- for (gp = (GLIST *) groupList.lh_Head;
- gp->node.ln_Succ;
- gp = (GLIST *) gp->node.ln_Succ) {
-
- pct = (100 * artCount) / totalArticles;
- if (GuageRequest (pct, "Closing Down", "Building News Tree", "Wait"))
- ;
- MOVESTR (gp->groupName);
- MOVE1 (gp->hideHeaders);
- MOVE1 (gp->hideRead);
- MOVE4 (gp->nextReceived);
- MOVE2 (gp->sortActive);
- SortArticlesByNumber (&gp->artList);
- for (ap = (ART *) gp->artList.lh_Head;
- ap->node.ln_Succ;
- ap = (ART *) ap->node.ln_Succ) {
-
- artCount++;
- MOVE2 (ap->state);
- MOVE4 (ap->filenum);
- MOVESTR (ap->from);
- MOVESTR (ap->subject);
- }
- MOVE2 (end);
- }
- // printf ("Built memoryfile\n");
- GuageRequest (1000, "Closing Down", "Building News Tree", "Wait");
-
- t_printf (mainWindow, "Dumping News Tree to %s", grnrcName);
-
- len = (long) (p - memoryfile);
- offset = 0;
- do {
- pct = write (fd, &memoryfile [offset], len);
- if (pct < 0) {
- // shit.
- t_printf (mainWindow, "Output failure. Trying again.");
- D (("WriteNewsTree: write error\n"));
- free (memoryfile);
- memoryfile = 0;
- close (fd);
- fd = creat (grnrcName, 0660);
- if (fd < 0) {
- t_printf (mainWindow, "I give up. Try again later.");
- D (("WriteNewsTree: exit, can't creat() grnrc after write error\n"));
- return;
- }
- do_it_the_hard_way = 1;
- len = 0;
- break;
- }
- offset += pct;
- len -= pct;
- } while (len > 0);
- }
-
- if (do_it_the_hard_way) {
- t_printf (mainWindow, "GRn - Writing News Tree to %s", grnrcName);
- write (fd, &grnrcVersion, 4);
- artCount = 0;
-
- for (gp = (GLIST *) groupList.lh_Head;
- gp->node.ln_Succ;
- gp = (GLIST *) gp->node.ln_Succ) {
-
- pct = (100 * artCount) / totalArticles;
- if (GuageRequest (pct, "Closing Down", "Writing News Tree", "Wait"))
- ;
- write (fd, gp->groupName, strlen (gp->groupName)+1);
- write (fd, &gp->hideHeaders, 1);
- write (fd, &gp->hideRead, 1);
- write (fd, &gp->nextReceived, 4);
- write (fd, &gp->sortActive, 2);
- // sort the articles in this group by number
- SortArticlesByNumber (&gp->artList);
- for (ap = (ART *) gp->artList.lh_Head;
- ap->node.ln_Succ;
- ap = (ART *) ap->node.ln_Succ) {
-
- artCount++;
- write (fd, &ap->state, 2);
- write (fd, &ap->filenum, 4);
- write (fd, ap->from, strlen (ap->from)+1);
- write (fd, ap->subject, strlen (ap->subject)+1);
- }
- write(fd, &end, 2);
- }
- GuageRequest (1000, "Closing Down", "Writing News Tree", "Wait");
- }
-
- if (memoryfile) {
- #if 1
- free (memoryfile);
- #else
- // this code is for debugging changes to the GRnRC format
- char buf [2];
- register char *p = memoryfile;
- int i;
- int er;
-
- printf ("checking memoryfile against grnrc\n");
- if ((fd = open (grnrcName, O_RDONLY)) < 0) {
- printf ("Can't open grnrc for input!\n");
- free (memoryfile);
- return;
- }
- // this is slow, but effective
- er = 0;
- while (read (fd, buf, 1) > 0) {
- if (((*p) & 0xff) != (buf [0] & 0xff)) {
- printf ("Mismatch. Byte %d, p = 0x%x, buf = 0x%x\n",
- (int) (p - memoryfile), (*p) & 0xff, (buf [0] & 0xff));
- er++;
- break;
- }
- p++;
- }
- if (er == 0) {
- printf ("No errors in %d bytes!\n", (int) (p - memoryfile));
- }
- close (fd);
- free (memoryfile);
- #endif
- }
-
- close (fd);
- treeDirty = 0;
-
- D (("WriteNewsTree: exit\n"));
- return;
- }
-
- #undef MOVE1
- #undef MOVE2
- #undef MOVE4
- #undef MOVESTR
-
- //
- // This routine builds an article (ART) entry. It gets the Subject and From
- // header out of the file.
- //
- ART *BuildART (const char *fname, const int num, const int state)
- {
- ART *ap;
- char *subject;
- static char work [512];
-
- From = NULL;
- Subject = NULL;
- if (ScanAndLoadHeaders (fname, HEADER_FROM | HEADER_SUBJECT, 0) < 0) {
- return NULL;
- }
- subject = Subject ? Subject : "<No Subject Found>";
- if (From)
- FixName (work, From);
- else
- strcpy (work, "<No From Found>");
-
- ap = AllocART (work, subject);
- ap->state = state;
- ap->filenum = num;
-
- return ap;
- }
- //
- // This routine scans uunews: and finds all the newsgroups and articles.
- // The news tree is built from scratch and all articles are marked as unread.
- //
- void BuildNewsTree (void)
- {
- ART *ap;
- GLIST *gp;
- UWORD num;
- char groupName[256], filename[256], temp[512];
- BPTR fh;
- char *p;
-
- if (subscribe_mode) {
- int i;
-
- t_printf (mainWindow, "GRn - Building New Subscription Lists");
-
- for (i = 0; i < subscribe_count; i++) {
- p = subscribe_list [i + 2];
- strcpy (filename, uunews);
- AddPart (filename, NewsGroupToFileName (p), 256);
- if (lock = Lock (filename, SHARED_LOCK)) {
- // should we Examine() to make sure it's a
- // directory? Naahhh.
- // FIXME - validate newsgroup name from
- // uulib:NewsGroups
- gp = AllocGLIST (p, p);
- AddTail (&groupList, (NODE *) gp);
- UnLock (lock);
- lock = 0;
- }
- else {
- OutputStrings (2, "Newsgroup doesn't exist: ", p, "\n", NULL);
- }
- }
- }
- else {
- t_printf (mainWindow, "GRn - Building News Tree...");
-
- if (hierarchical) {
- if (BuildHierarchicalList () < 0)
- panic0 (0, "There was an error building the newsgroup list\n");
- }
- else {
- lock = Lock (uunews, SHARED_LOCK);
- panic0 ((APTR)lock, "Lock(%s) failed", uunews);
-
- Examine (lock, fib);
- while (ExNext (lock, fib)) {
- if (fib->fib_DirEntryType < 0)
- continue;
- // ignore C-News control directories
- if (strcmp (fib->fib_FileName, "in.coming") == 0)
- continue;
- if (strcmp (fib->fib_FileName, "out.going") == 0)
- continue;
-
- gp = AllocGLIST (fib->fib_FileName, fib->fib_FileName);
- AddTail (&groupList, (NODE *) gp);
- }
- UnLock (lock);
- lock = 0;
- }
- }
-
- SortList (&groupList, 0);
-
- gp = (GLIST *)groupList.lh_Head;
-
- for (; gp->node.ln_Succ; gp=(GLIST *)gp->node.ln_Succ) {
- t_printf (mainWindow, "GRn - Scanning %s...", gp->groupName);
- gp->articles = 0;
- gp->unread = 0;
- strcpy (groupName, uunews);
- AddPart (groupName, NewsGroupToFileName (gp->groupName), 256);
- lock = Lock (groupName, SHARED_LOCK);
- if (!lock) {
- // could fail for a variety of reasons. We don't care.
- OutputStrings (2, "Lock() failed on ", groupName, "\n", NULL);
- continue;
- }
- strcpy (filename, groupName);
- strcat (filename, "/.next");
- if (fh = Open (filename, MODE_OLDFILE)) {
- Read (fh, temp, 512);
- Close (fh);
- gp->nextReceived = atoi (temp);
- }
- else {
- gp->nextReceived = 0;
- }
- gp->hideHeaders = !0;
- gp->hideRead = !0;
- gp->sortActive = 0;
- NewList (&gp->artList);
- Examine (lock, fib);
- while (ExNext (lock, fib)) {
- // FIXME - across a network this could be a SOFTLINK
- if (fib->fib_DirEntryType > 0)
- continue;
- if (!(num = atoi (fib->fib_FileName)))
- continue;
-
- CopyStrings (filename, groupName, "/", fib->fib_FileName, NULL);
- ap = BuildART (filename, num, UNREAD);
- if (!ap) {
- OutputStrings (2, "fopen() failed on ", filename, "\n", NULL);
- continue;
- }
- AddTail (&gp->artList, (NODE *) ap);
-
- gp->articles++;
- gp->unread++;
- }
- sprintf(gp->header, "%-40.40s %6d articles %6d UnRead", gp->groupName, gp->articles, gp->unread);
- }
- UnLock (lock);
- lock = 0;
- treeDirty = 1;
- return;
- }
-
- void ReadNewsTree (void) {
- ART *ap;
- GLIST *gp;
- char temp [256], subj [256];
- UWORD endTest;
- ULONG fileNum;
- ULONG pct;
-
- t_printf (mainWindow, "GRn - Reading News Tree...");
- while (1) {
- if (!mgets (temp))
- break;
- t_printf (mainWindow, "GRN - Reading News Tree...(%s)", temp);
- gp = AllocGLIST (temp, NULL);
- AddTail (&groupList, (NODE *)gp);
- NewList (&gp->artList);
- gp->articles = 0;
- gp->unread = 0;
- mread (&gp->hideHeaders, 1);
- mread (&gp->hideRead, 1);
- mread (&gp->nextReceived, 4);
- mread (&gp->sortActive, 2);
- pct = (100 * (ULONG)(mbufp - mbuf)) / (ULONG)(mbufe - mbuf);
- if (GuageRequest (pct, "Initializing", "Setting up News Tree", "Abort"))
- Abort ();
- while (1) {
- mread (&endTest, 2);
- if (endTest == END)
- break;
- mread (&fileNum, 4);
- mgets (temp); // From: header
- mgets (subj); // Subject: header
-
- ap = AllocART (temp, subj);
- ap->state = endTest;
- ap->filenum = fileNum;
-
- AddTail (&gp->artList, (NODE *) ap);
- gp->articles++;
- if (ap->state == UNREAD || ap->state == NEW)
- gp->unread++;
- }
- sprintf (gp->header, "%-40.40s %6d articles %6d UnRead",
- gp->groupName, gp->articles, gp->unread);
- }
- mclose ();
- return;
- }
-
- void UpdateNewsTree (void) {
- register GLIST *gp; // the current group pointer
- register ART *ap; // the current article pointer
- register ART *save_ap; // save the pointer while we clean up
- long num, last; // article number
- char fname [256], work [256];
- char *ptr; // points to the end of the constant part of fname
- BPTR lock;
- BPTR fh;
-
- // FIXME - we should CurrentDir() to UUNEWS:, and do all operations
- // relative to there.
-
- // for each group
- for (gp=(GLIST *)groupList.lh_Head; gp->node.ln_Succ; gp = (GLIST *)gp->node.ln_Succ) {
- t_printf (mainWindow, "GRn - Pruning %s", gp->groupName);
- strcpy (fname, uunews);
- AddPart (fname, NewsGroupToFileName (gp->groupName), 256);
- ptr = fname + strlen (fname);
- // scan through list and check to see which files
- // are still there!
- for (ap = (ART *)gp->artList.lh_Head; ap->node.ln_Succ; ap = (ART *)ap->node.ln_Succ) {
- *ptr = '\0';
- strcpy (work, itoa (ap->filenum));
- AddPart (fname, work, 256);
- if (lock = Lock (fname, SHARED_LOCK)) {
- UnLock (lock);
- break; // as soon as we find one, quit looking
- // for them not to be there...
- }
- else {
- if (ap->state == UNREAD)
- gp->unread--;
- gp->articles--;
- save_ap = (ART *) ap->node.ln_Pred;
- Remove ((NODE *) ap);
- FreeART (ap);
- ap = save_ap;
- treeDirty = 1;
- }
- }
- // Find new articles, mark as unread!
- t_printf (mainWindow, "GRn - Getting new articles for %s",
- gp->groupName);
- *ptr = '\0';
- AddPart (fname, ".next", 256);
- if (fh = Open (fname, MODE_OLDFILE)) {
- Read (fh, work, 256);
- Close (fh);
- last = atoi (work);
- }
- else {
- last = 1000000;
- }
- for (num = gp->nextReceived; num < last; num++) {
- *ptr = '\0';
- strcpy (work, itoa (num));
- AddPart (fname, work, 256);
-
- ap = BuildART (fname, num, UNREAD);
- if (!ap) {
- if (last == 1000000)
- break;
- continue;
- }
-
- AddTail (&gp->artList, (NODE *) ap);
- gp->articles++;
- gp->unread++;
- treeDirty = 1;
- }
- sprintf (gp->header, "%-40.40s %6d articles %6d UnRead", gp->groupName, gp->articles, gp->unread);
- if (gp->nextReceived != last) {
- gp->nextReceived = last;
- treeDirty = 1;
- }
- }
- return;
- }
-
- void CheckNews (void) {
- ULONG testver = 0x0a0a5050;
-
- SetHierarchical ();
- if (!mopen (grnrcName)) {
- BuildNewsTree ();
- return;
- }
- mread (&testver, 4);
- if (testver != grnrcVersion)
- panic ("grnrc is wrong version, delete it and run GRn again");
-
- if (subscribe_mode)
- BuildNewsTree ();
-
- if (GuageRequest (0, "Initializing", "Setting up News Tree", "Abort"))
- Abort ();
- ReadNewsTree ();
- GuageRequest (1000, "Initializing", "Setting up News Tree", "Abort");
-
- UpdateNewsTree ();
- SortList (&groupList, 0);
- return;
- }
-
- /************************************************************************/
-
- void ParseConfig (void)
- {
- char buf[512], *ps;
- FILE *fp;
- BOOL uulibFlag = 0;
-
- // FIXME - use uucp:src/lib/config.c routines (specifically GetConfig())
-
- userName[0] = mailEditor[0] = newsEditor[0] = '\0';
- GetVar ("USERNAME", userName, 256, GVF_GLOBAL_ONLY);
- GetVar ("NEWSEDITOR", newsEditor, 256, GVF_GLOBAL_ONLY);
- GetVar ("MAILEDITOR", mailEditor, 256, GVF_GLOBAL_ONLY);
- GetVar ("SENDMAIL", sendMail, 256, GVF_GLOBAL_ONLY);
- GetVar ("POSTNEWS", postNews, 256, GVF_GLOBAL_ONLY);
- if (userName[0] && newsEditor[0] && mailEditor[0] && sendMail[0] && postNews[0]) return;
-
- fp = fopen("s:uuconfig", "r");
- if (!fp) {
- fp = fopen("uulib:config", "r");
- panic0(fp, "Can't open uulib:config");
- uulibFlag = !0;
- }
- while (fgets(buf, 512, fp) && (!userName[0] || !newsEditor[0] || !mailEditor[0] || !sendMail[0] || !postNews[0])) {
- buf[strlen(buf)-1] = '\0';
- if (userName[0] == '\0' && !strnicmp(buf, "UserName", 8)) {
- ps = &buf[8];
- while (*ps == ' ' || *ps == '\t') ps++;
- if (*ps == '\0') panic("s:uuconfig or uulib:config UserName is NULL");
- strcpy(userName, ps);
- }
- else if (newsEditor[0] == '\0' && !strnicmp(buf, "NewsEditor", 10)) {
- ps = &buf[10];
- while (*ps == ' ' || *ps == '\t') ps++;
- if (*ps == '\0') panic("s:uuconfig or uulib:config NewsEditor is NULL");
- strcpy(newsEditor, ps);
- }
- else if (mailEditor[0] == '\0' && !strnicmp(buf, "MailEditor", 10)) {
- ps = &buf[10];
- while (*ps == ' ' || *ps == '\t') ps++;
- if (*ps == '\0') panic("s:uuconfig or uulib:config MailEditor is NULL");
- strcpy(mailEditor, ps);
- }
- else if (sendMail[0] == '\0' && !strnicmp(buf, "SendMail", 8)) {
- ps = &buf[8];
- while (*ps == ' ' || *ps == '\t') ps++;
- if (*ps == '\0') panic("s:uuconfig or uulib:config Sendmail is NULL");
- strcpy(sendMail, ps);
- }
- else if (postNews[0] == '\0' && !strnicmp(buf, "PostNews", 8)) {
- ps = &buf[8];
- while (*ps == ' ' || *ps == '\t') ps++;
- if (*ps == '\0') panic("s:uuconfig or uulib:config Postnews is NULL");
- strcpy(postNews, ps);
- }
- else if (!strnicmp(buf, "UUNews", 6)) {
- ps = &buf[6];
- while (*ps == ' ' || *ps == '\t') ps++;
- if (*ps) strcpy(uunews, ps);
- }
- else if (!uulibFlag && !strnicmp(buf, "UUlib", 5)) {
- ps = &buf[5];
- while (*ps == ' ' || *ps == '\t') ps++;
- if (*ps) strcpy(uulib, ps);
- }
- else if (!strnicmp(buf, "UUSpool", 7)) {
- ps = &buf[7];
- while (*ps == ' ' || *ps == '\t') ps++;
- if (*ps) strcpy(uuspool, ps);
- }
- }
- fclose(fp);
- if (userName[0]) {
- strcpy(grnrcName, uulib);
- sprintf(buf, "%s.grnrc", userName);
- AddPart(grnrcName, buf, 256);
- }
- else
- panic("s:uuconfig or uulib:config must contain UserName!");
- if (newsEditor[0] && !mailEditor[0])
- strcpy(mailEditor, newsEditor);
- else if (!newsEditor[0] && mailEditor[0])
- strcpy(newsEditor, mailEditor);
- panic0((APTR)newsEditor[0], "s:uuconfig or uulib:config must contain NewsEditor");
- panic0((APTR)mailEditor[0], "s:uuconfig or uulib:config must contain MailEditor");
- if (!sendMail[0]) strcpy(sendMail, "SendMail");
- if (!postNews[0]) strcpy(postNews, "PostNews");
- if (!logfile[0]) {
- strcpy(logfile, uuspool);
- AddPart(logfile, "logfile", 256);
- }
- }
-
- /************************************************************************/
-
- void GRnRC (void)
- {
- ULONG testver = 0x0a0a5050;
-
- ParseConfig ();
- SetHierarchical ();
-
- if (!mopen (grnrcName)) {
- BuildNewsTree ();
- Abort ();
- }
- mread (&testver, 4);
- if (testver != grnrcVersion)
- panic ("grnrc is wrong version, delete it and run GRn again");
-
- currentGroup = (GLIST *) groupList.lh_Head;
- ReadNewsTree ();
- UpdateNewsTree ();
- SortList (&groupList, 0);
- WriteNewsTree ();
- Abort ();
- /* NOTREACHED */
- return;
- }
-
- /************************************************************************/
-
- void QueryAbort (void)
- {
- if (!treeDirty)
- Abort ();
- if (TwoGadgetRequest ("GRn - Abort...",
- "Quit without updating News Tree?",
- "_YES",
- "_NO, I changed my mind"))
- Abort ();
- mode = GROUPS_MODE;
- return;
- }
-
- void TRAP (void)
- {
- UWORD *custom = (UWORD *)0xdff180;
- UWORD i = 0;
-
- while (1)
- *custom = i++;
- }
-
- void usage (void)
- {
- char *msg = "usage: grn [-u] [-s newsgrouplist]\n"
- GRN_VERSION "\n";
-
- write (2, msg, strlen (msg));
- exit (10);
- }
-
- int main (int ac, char *av[])
- {
- LIBRARY *check;
- STRPTR s;
- char **tt;
- BOOL lFlag = 0, tFlag = 0, hFlag = 0;
-
- check = OpenLibrary ("intuition.library", 37);
- if (!check) {
- printf ("Can't open intuition.library\n");
- panic("Requires OS version 37 or higher");
- }
- CloseLibrary(check);
-
- if (ac > 1) {
- // got arguments
- // this is ugly, but for just a couple, why generalize?
- if (strcmp (av [1], "-u") == 0) {
- update_only_mode = 1;
- if (ac > 2)
- usage ();
- }
- else
- if (strcmp (av [1], "-s") == 0) {
- subscribe_mode = 1;
- subscribe_list = av;
- subscribe_count = ac - 2;
- }
- else {
- usage ();
- }
- }
-
- if (ac == 0) {
- WorkbenchBase = OpenLibrary("workbench.library", 0);
- panic0(WorkbenchBase, "Can't open workbench.library");
- IconBase = OpenLibrary("icon.library", 0);
- panic0(IconBase, "Can't open icon.library");
- CxBase = OpenLibrary("commodities.library", 0);
- panic0(CxBase, "Can't open commodities.library");
- tt = ArgArrayInit(ac, av);
- panic0(tt, "Can't ArgArrayInit...");
-
- s = ArgString(tt, "TOP", "");
- if (s[0]) { prefTop = atoi(s); tFlag = !0; }
- s = ArgString(tt, "LEFT", "");
- if (s[0]) { prefLeft = atoi(s); lFlag = !0; }
- s = ArgString(tt, "WIDTH", "");
- if (s[0]) prefWidth = atoi(s);
- s = ArgString(tt, "HEIGHT", "");
- if (s[0]) { prefHeight = atoi(s); hFlag = !0; }
- s = ArgString(tt, "MSGFONT", "");
- if (s[0]) strcpy(prefFontName, s);
- s = ArgString(tt, "MSGFONTSIZE", "");
- if (s[0]) prefFontSize = atoi(s);
- s = ArgString(tt, "LOGFILE", "");
- if (s[0]) strcpy(logfile, s);
- s = ArgString(tt, "WRAP", "");
- if (s[0]) wrapCol = atoi(s);
- s = ArgString(tt, "UPDATERC", "");
- if (s[0]) update_only_mode = 1;
- ArgArrayDone();
- CloseLibrary(CxBase);
- CloseLibrary(IconBase);
- CloseLibrary(WorkbenchBase);
- InitSystem ();
- }
- else {
- InitSystem ();
- prefLeft = screenWidth - prefWidth;
- prefTop = screenTop;
- prefHeight = screenHeight-screenTop;
- }
- if (ac == 0) {
- if (!lFlag) prefLeft = screenWidth - prefWidth;
- if (!tFlag) prefTop = screenTop;
- if (!hFlag) prefHeight = screenHeight-screenTop;
- }
-
- onbreak(Abort);
-
- Forbid ();
- port = FindPort ("GRN_PORT");
- if (port) {
- port = 0;
- Permit ();
- if (screen)
- DisplayBeep (screen);
- else
- printf ("GRn already running!!!\n");
- Abort();
- }
- port = CreatePort ("GRN_PORT", 0);
- Permit ();
- panic0 (port, "Can't create GRN_PORT");
-
- fib = (FIB *) AllocDosObject (DOS_FIB, TAG_DONE);
- panic0 (fib, "Can't AllocDosObject (DOS_FIB)");
-
- NewList (&groupList);
-
- if (update_only_mode) {
- GRnRC ();
- /* NOTREACHED */
- exit (0);
- }
- windowHeight = prefHeight;
- mainWindow = CreateWindow(NULL, prefLeft, prefTop, prefWidth,windowHeight, "GRn - Looking for news...");
- panic0(mainWindow, "Can't open main window");
-
- saveReq = (FILEREQ *)AllocAslRequestTags(ASL_FileRequest,
- ASL_Hail, "Save Message...",
- ASL_Window, mainWindow,
- ASL_FuncFlags, FILF_SAVE,
- TAG_DONE
- );
- panic0(saveReq, "Can't AllocFileRequest");
-
- publishReq = (FILEREQ *)AllocAslRequestTags(ASL_FileRequest,
- ASL_Hail, "Publish File...",
- ASL_Window, mainWindow,
- TAG_DONE
- );
- panic0(publishReq, "Can't AllocFileRequest");
-
- t_printf(mainWindow, "GRn - Getting your UserName");
- ParseConfig();
- CheckNews();
-
- currentGroup = (GLIST *)groupList.lh_Head;
-
- while (mode != QUIT_MODE) {
- switch (mode) {
- case NEXTGROUPS_MODE:
- case PREVGROUPS_MODE:
- case GROUPS_MODE: GroupsWindow(); break;
- case ARTICLES_MODE: ArticlesWindow(); break;
- case QUIT_MODE: break;
- case ABORT_MODE: QueryAbort(); break;
- default: break;
- }
- }
- WriteNewsTree();
- Abort();
- }
-
- int wbmain(struct WBStartup *msg) {
- LIBRARY *check;
- char *s;
- BOOL lFlag = 0, tFlag = 0, hFlag = 0;
- char **tt;
- union {
- char **args;
- struct WBStartup *msg;
- } argv;
-
- argv.msg = msg;
- check = OpenLibrary("intuition.library", 37);
- if (!check) panic("Requires OS version 37 or higher");
- CloseLibrary(check);
-
- WorkbenchBase = OpenLibrary("workbench.library", 0);
- panic0(WorkbenchBase, "Can't open workbench.library");
- IconBase = OpenLibrary("icon.library", 0);
- panic0(IconBase, "Can't open icon.library");
- CxBase = OpenLibrary("commodities.library", 0);
- panic0(CxBase, "Can't open commodities.library");
- CurrentDir(msg->sm_ArgList->wa_Lock); /* DICE's startup code doesn't do this */
- tt = ArgArrayInit(0, argv.args);
- panic0(tt, "Can't ArgArrayInit2...");
-
- s = ArgString(tt, "TOP", "");
- if (s[0]) { prefTop = atoi(s); tFlag = !0; }
- s = ArgString(tt, "LEFT", "");
- if (s[0]) { prefLeft = atoi(s); lFlag = !0; }
- s = ArgString(tt, "WIDTH", "");
- if (s[0]) prefWidth = atoi(s);
- s = ArgString(tt, "HEIGHT", "");
- if (s[0]) { prefHeight = atoi(s); hFlag = !0; }
- s = ArgString(tt, "MSGFONT", "");
- if (s[0]) strcpy(prefFontName, s);
- s = ArgString(tt, "MSGFONTSIZE", "");
- if (s[0]) prefFontSize = atoi(s);
- s = ArgString(tt, "LOGFILE", "");
- if (s[0]) strcpy(logfile, s);
- s = ArgString(tt, "WRAP", "");
- if (s[0]) wrapCol = atoi(s);
- s = ArgString(tt, "UPDATERC", "");
- if (s[0]) update_only_mode = 1;
- ArgArrayDone();
- CloseLibrary(CxBase);
- CloseLibrary(IconBase);
- CloseLibrary(WorkbenchBase);
- if (!lFlag) prefLeft = screenWidth - prefWidth;
- if (!tFlag) prefTop = screenTop;
- if (!hFlag) prefHeight = screenHeight-screenTop;
- return main(1,NULL);
- }
-
-