home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / comms / network / grn1asrc.lha / grn.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-20  |  24.0 KB  |  925 lines

  1. #include    "defs.h"
  2.  
  3. extern char *FileNameToNewsGroup (char *filename);      /* IMPORT */
  4. extern char *NewsGroupToFileName (char *newsgroup);     /* IMPORT */
  5. extern int  BuildHierarchicalList (void);               /* IMPORT */
  6.  
  7. int hierarchical = 0;                    /* EXPORT */
  8.  
  9. #include    <stdarg.h>
  10. #include    <stdio.h>
  11.  
  12. ULONG    grnrcVersion = '1.20';
  13. UWORD    windowHeight;
  14. UWORD    wrapCol = 82;                // selectable wrap point for articles
  15.  
  16. /************************************************************************/
  17.  
  18. FILEREQ     *saveReq = 0;
  19. FILEREQ     *publishReq = 0;
  20.  
  21. static MPORT    *port = 0;
  22. char        userName[256], grnrcName[256];
  23. char        newsEditor[256], mailEditor[256];
  24. char        postNews[256], sendMail[256];
  25. char        uunews[256] = "UUNEWS:";
  26. char        uulib[256] = "UULIB:";
  27. char        uuspool[256] = "UUSPOOL:";
  28. char        logfile[256] = "";
  29.  
  30. BOOL        treeDirty = 0;
  31.  
  32. LIST        groupList;
  33.  
  34. LOCK        lock = 0;
  35. FIB        *fib = 0;
  36.  
  37. WINDOW        *mainWindow = 0;
  38.  
  39. UWORD        mode = GROUPS_MODE;
  40.  
  41. void ClearWindow( void ) {
  42.     WORD    x, y, x1, y1;
  43.  
  44.     x  = mainWindow->BorderLeft;
  45.     y  = mainWindow->BorderTop;
  46.     x1 = mainWindow->Width - mainWindow->BorderRight - 1;
  47.     y1 = mainWindow->Height - mainWindow->BorderBottom - 1;
  48.  
  49.     SetAPen( mainWindow->RPort, 0);
  50.     SetDrMd( mainWindow->RPort, JAM1 );
  51.     RectFill( mainWindow->RPort, x, y, x1, y1 );
  52.  
  53.     RefreshWindowFrame( mainWindow );
  54. }
  55.  
  56. void    CloseMain() {
  57.     if (publishReq) { FreeFileRequest(publishReq); publishReq = 0; }
  58.     if (saveReq) { FreeFileRequest(saveReq); saveReq = 0; }
  59.     if (fib) {
  60.         FreeDosObject(DOS_FIB, (void *)fib);
  61.         fib = 0;
  62.     }
  63.     if (lock) {
  64.         UnLock(lock);
  65.         lock = 0;
  66.     }
  67.     if (mainWindow) {
  68.         CloseWindow(mainWindow);
  69.         mainWindow = 0;
  70.     }
  71. }
  72.  
  73. /*
  74.  * void Abort(void);
  75.  *
  76.  * Synopsis:
  77.  *    Cleanup and exit.  Can be called anywhere, anytime, including from
  78.  *    the debugger by setting PC = Abort.
  79.  */
  80. long    abort_code = 0;
  81. void    Abort(void) {
  82.     CloseGroups();
  83.     CloseMain();
  84.     if (port) DeletePort(port);
  85.     CloseSystem();
  86.     exit(abort_code);
  87. }
  88.  
  89. /*
  90.  * void panic0(v, s,a1,a2,a3,a4);
  91.  * ULONG    v;
  92.  * char     *s;
  93.  * ULONG    a1,a2,a3,a4;
  94.  *
  95.  * Synopsis:
  96.  *    Anywhere you use:
  97.  *        v = (some function);
  98.  *        if (!v) {
  99.  *            printf("some string");
  100.  *            Abort();
  101.  *        }
  102.  *    You can use:
  103.  *        v = (some function);
  104.  *        panic0(v, "some string");
  105.  *    The string and args (a1,a2,a3,a4) are passed to printf...
  106.  */
  107. void    panic0(APTR v, const char *s, ...) {
  108.     FILE    *outfp;
  109.     va_list va;
  110.  
  111.     va_start(va, s);
  112.     if (v) return;
  113.     printf("Panic: ");
  114.     _pfmt(s, va, fwrite, stdout);
  115.     printf("\n");
  116.     if (!logfile[0]) sprintf(logfile, "UUSPOOL:logfile");
  117.     outfp = fopen(logfile, "a");
  118.     if (outfp) {
  119.         fprintf(outfp, "GRn panic: ");
  120.         _pfmt(s, va, fwrite, outfp);
  121.         fprintf(outfp, "\n");
  122.         fclose(outfp);
  123.     }
  124.     va_end(va);
  125.     abort_code = 999;
  126.     Abort();
  127. }
  128.  
  129. void    panic(const char *s, ...) {
  130.     FILE    *outfp;
  131.     va_list va;
  132.  
  133.     va_start(va, s);
  134.     printf("Panic: ");
  135.     printf(s, va);
  136.     _pfmt(s, va, fwrite, stdout);
  137.     printf("\n");
  138.     if (!logfile[0]) sprintf(logfile, "UUSPOOL:logfile");
  139.     outfp = fopen(logfile, "a");
  140.     if (outfp) {
  141.         fprintf(outfp, "GRn panic: ");
  142.         _pfmt(s, va, fwrite, outfp);
  143.         fprintf(outfp, "\n");
  144.         fclose(outfp);
  145.     }
  146.     va_end(va);
  147.     abort_code = 999;
  148.     Abort();
  149. }
  150.  
  151. /************************************************************************/
  152.  
  153. UBYTE    *mbuf = 0, *mbufp, *mbufe;
  154.  
  155. void    mclose(void) { if (mbuf) { free(mbuf); mbuf = 0; } }
  156. BOOL    mopen(char *fn) {
  157.     int    fd;
  158.     ULONG    size;
  159.  
  160.     mclose();
  161.     fd = open(fn, O_READ);
  162.     if (fd == -1) return 0;
  163.     size = lseek(fd, 0, 2); lseek(fd, 0, 0);
  164.     mbuf = (UBYTE *)malloc(size);
  165.     if (!mbuf) { close(fd); return 0; }
  166.     read(fd, mbuf, size);
  167.     close(fd);
  168.     mbufp = mbuf;
  169.     mbufe = &mbufp[size];
  170.     return !0;
  171. }
  172.  
  173. BOOL    mread(buf, size)
  174. UBYTE    *buf;
  175. ULONG    size;
  176. {
  177.     ULONG    i;
  178.  
  179.     if (!mbuf || mbufp == mbufe) return 0;
  180.     for (i=0; i<size; i++) *buf++ = (mbufp == mbufe) ? 0 : *mbufp++;
  181.     return !0;
  182. }
  183.  
  184. BOOL    mgets(buf)
  185. UBYTE    *buf;
  186. {
  187.     if (mbufp == mbufe) return 0;
  188.     while (mbufp != mbufe && (*buf++ = *mbufp++));
  189.     *buf++ = '\0';
  190.     return !0;
  191. }
  192.  
  193. /************************************************************************/
  194.  
  195. BOOL    EmptyList(list)
  196. LIST    *list;
  197. {
  198.     if (list->lh_TailPred == (NODE *)list) return !0;
  199.     return 0;
  200. }
  201.  
  202. NODE    *FindListItem(list, num)
  203. LIST    *list;
  204. short    num;
  205. {
  206.     NODE    *np;
  207.  
  208.     for (np = list->lh_Head; np->ln_Succ; np=np->ln_Succ) {
  209.         if (!num) return np;
  210.         num--;
  211.     }
  212.     return 0;
  213. }
  214.  
  215. void    SortList(list, col)
  216. LIST    *list;
  217. short    col;
  218. {
  219.     LIST    tmp;
  220.     NODE    *np, *np2;
  221.  
  222.     if (EmptyList(list)) return;
  223.     NewList(&tmp);
  224.     while (!EmptyList(list)) {
  225.         np = RemHead(list);
  226.         if (EmptyList(&tmp)) {
  227.             AddHead(&tmp, np);
  228.         }
  229.         else {
  230.             if (strcmp(&np->ln_Name[col], &tmp.lh_Head->ln_Name[col]) < 0) {
  231.                 AddHead(&tmp, np);
  232.             }
  233.             else if (strcmp(&np->ln_Name[col], &tmp.lh_TailPred->ln_Name[col]) > 0) {
  234.                 AddTail(&tmp, np);
  235.             }
  236.             else {
  237.                 for (np2=tmp.lh_Head; np2->ln_Succ; np2=np2->ln_Succ) {
  238.                     if (strcmp(&np->ln_Name[col], &np2->ln_Name[col]) < 0) {
  239.                         Insert(&tmp, np, np2->ln_Pred);
  240.                         break;
  241.                     }
  242.                 }
  243.             }
  244.         }
  245.  
  246.     }
  247.     NewList(list);
  248.     while (!EmptyList(&tmp)) {
  249.         np = RemHead(&tmp);
  250.         AddTail(list, np);
  251.     }
  252. }
  253.  
  254. void    FreeListNodes(list, flag)
  255. LIST    *list;
  256. BOOL    flag;
  257. {
  258.     NODE    *np1, *np2;
  259.     short    count = 0;
  260.  
  261.     for (np1 = list->lh_Head; np1->ln_Succ;) {
  262.         np2 = np1->ln_Succ;
  263.         if (flag) free(np1->ln_Name);
  264.         free(np1);
  265.         count++;
  266.         np1 = np2;
  267.     }
  268.     NewList(list);
  269. }
  270.  
  271. /************************************************************************/
  272.  
  273. void    FixName(dst, src)
  274. char    *dst, *src;
  275. {
  276.     short    i, j;
  277.     BOOL    ltFlag = 0;
  278.     char    *d = dst;
  279.     short    pcount = 0;
  280.  
  281.     for (i=0; src[i]; i++) if (src[i] == '<') ltFlag = !0;
  282.  
  283.     if (*src == '"') {
  284.         for (j=1; src[j] && src[j] != '"'; j++) *dst++ = src[j];
  285.         *dst++ = '\0';
  286.         if (dst-d > 512) printf("FixName1 string to big: %d bytes '%s'\n", dst-d, d);
  287.         return;
  288.     }
  289.     if (*src == '<') {
  290.         for (j=1; src[j] && src[j] != '@' && src[j] != '>'; j++) {
  291.             if (src[j] == '.')
  292.                 *dst++ = ' ';
  293.             else
  294.                 *dst++ = src[j];
  295.         }
  296.         *dst++ = '\0';
  297.         if (dst-d > 512) printf("FixName2 string to big: %d bytes '%s'\n", dst-d, d);
  298.         return;
  299.     }
  300.     for (j=0; src[j]; j++) {
  301.         if (src[j] == '<') {
  302.             if (!j) {
  303.                 if (strlen(src) > 511) printf("FixName3 string to big: %d bytes '%s'\n", dst-d, src);
  304.                 strncpy(dst, src, 512);
  305.                 return;
  306.             }
  307.             else {
  308.                 for (i=0; i<j; i++) *dst++ = *src++;
  309.                 *dst++ = '\0';
  310.                 if (dst-d > 512) printf("FixName4 string to big: %d bytes '%s'\n", dst-d, d);
  311.                 return;
  312.             }
  313.         }
  314.  
  315.         // example nested parens:  (Blonder (The one and Only :))
  316.         if (src[j] == '(' && !ltFlag) {
  317.             pcount++;
  318.             j++;
  319.             while (src[j] && pcount) {
  320.                 switch (src[j]) {
  321.                     case ')':       pcount--;
  322.                             if (pcount) *dst++ = src[j];
  323.                             j++;
  324.                             break;
  325.                     case '(':       pcount++;
  326.                     default:    *dst++ = src[j++];
  327.                             break;
  328.                 }
  329.             }
  330.             *dst++ = '\0';
  331.             if (dst-d > 512) printf("FixName5 string to big: %d bytes '%s'\n", dst-d, d);
  332.             return;
  333.         }
  334.     }
  335.     j=-1;
  336.     for (i=0; src[i]; i++) if (src[i] == '!') j = i;
  337.     if (j != -1) {
  338.         j++;
  339.         while (src[j] && src[j] != ',' && src[j] != '@') *dst++ = src[j++];
  340.         *dst++ = '\0';
  341.     }
  342.     else {
  343.         while (*src && *src != '%' && *src != '@') *dst++ = *src++;
  344.         *dst++ = '\0';
  345.     }
  346.     if (dst-d > 512) printf("FixName6 string to big: %d bytes '%s'\n", dst-d, d);
  347. }
  348.  
  349. /************************************************************************/
  350.  
  351. void    WriteNewsTree() {
  352.     int    fd;
  353.     ART    *ap;
  354.     GLIST    *gp;
  355.     UWORD    end = END;
  356.  
  357.     if (!treeDirty) return;
  358.     t_printf(mainWindow, "GRn - Writing News Tree");
  359.     fd = open(grnrcName, O_WRITE);
  360.     if (fd == -1) panic("Can't open %s for output", grnrcName);
  361.     write(fd, &grnrcVersion, 4);
  362.  
  363.     for (gp = (GLIST *)groupList.lh_Head; gp->node.ln_Succ; gp=(GLIST *)gp->node.ln_Succ) {
  364.         write(fd, gp->groupName, strlen(gp->groupName)+1);
  365.         write(fd, &gp->hideHeaders, 1);
  366.         write(fd, &gp->hideRead, 1);
  367.         write(fd, &gp->nextReceived, 4);
  368.         write(fd, &gp->sortActive, 2);
  369.         // sort the articles in this group by number
  370.         SortArticlesByNumber(&gp->artList);
  371.         for (ap=(ART *)gp->artList.lh_Head; ap->node.ln_Succ; ap=(ART *)ap->node.ln_Succ) {
  372.             write(fd, &ap->state, 2);
  373.             write(fd, &ap->filenum, 4);
  374.             write(fd, ap->from, strlen(ap->from)+1);
  375.             write(fd, ap->subject, strlen(ap->subject)+1);
  376.         }
  377.         write(fd, &end, 2);
  378.     }
  379.     close(fd);
  380.     treeDirty = 0;
  381. }
  382.  
  383. //
  384. // This routine scans uunews: and finds all the newsgroups and articles.
  385. // The news tree is built from scratch and all articles are marked as unread.
  386. //
  387. void    BuildNewsTree(void) {
  388.     ART    *ap;
  389.     GLIST    *gp;
  390.     UWORD    groupCount = 0;
  391.     char    groupName[256], filename[256], temp[512], from[512], subject[512];
  392.     FILE    *fp;
  393.  
  394.     t_printf(mainWindow, "GRn - Building News Tree...");
  395.     lock = Lock(uunews, SHARED_LOCK);
  396.     panic0((APTR)lock, "Lock(%s) failed", uunews);
  397.  
  398.     hierarchical = 1; /* presume globally true, until proven otherwise */
  399.     Examine (lock, fib);
  400.     while (ExNext (lock, fib)) {
  401.         if (fib->fib_DirEntryType < 0)
  402.             continue;
  403.         if (hierarchical && strchr (fib->fib_FileName, '.') == NULL) {
  404.             /* This is the first directory (ALL modern newsgroups */
  405.             /* have more than one level. So if the structure is   */
  406.             /* flat, and it WASNT hierarchical, we wouldn't get   */
  407.             /* here because it would have a period in it). If it  */
  408.             /* is hierarchical, then do the hierarchical thing    */
  409.             /* and then get out of here....               */
  410.             groupCount = BuildHierarchicalList ();
  411.             if (groupCount < 0) {
  412.                 panic0 (0, "There was an error building the newsgroup list\n");
  413.                 groupCount = -groupCount;
  414.             }
  415.             break;
  416.         }
  417.         hierarchical = 0;
  418.         gp = (GLIST *) malloc (sizeof (GLIST));
  419.         panic0 (gp, "Can't malloc GLIST %d bytes\n", sizeof (GLIST));
  420.         gp->node.ln_Name = &gp->header [0];
  421.         // since this is FLAT, it's already the newsgroup name,
  422.         // it doesn't have to be translated.....
  423.         strcpy (gp->groupName, fib->fib_FileName);
  424.         strcpy (gp->header, fib->fib_FileName);
  425.         AddTail (&groupList, (NODE *) gp);
  426.         groupCount++;
  427.     }
  428.     UnLock (lock);
  429.     lock = 0;
  430.     SortList (&groupList, 0);
  431.  
  432.     gp = (GLIST *)groupList.lh_Head;
  433.  
  434.     for (; gp->node.ln_Succ; gp=(GLIST *)gp->node.ln_Succ) {
  435.         t_printf(mainWindow, "GRn - Scanning %s...", gp->groupName);
  436.         gp->articles = gp->unread = 0;
  437.         strcpy(groupName, uunews);
  438.         AddPart(groupName, NewsGroupToFileName (gp->groupName), 256);
  439.         lock = Lock(groupName, SHARED_LOCK);
  440.         panic0((APTR)lock, "Lock(%s) failed", groupName);
  441.         sprintf(filename, "%s/.next", groupName);
  442.         fp = fopen(filename, "r");
  443.         if (!fp) {
  444.             gp->nextReceived = 0;
  445.         }
  446.         else {
  447.             fgets(temp, 512, fp);
  448.             fclose(fp);
  449.             gp->nextReceived = atoi(temp);
  450.         }
  451.         gp->hideHeaders = !0; gp->hideRead = !0;
  452.         gp->sortActive = 0;
  453.         NewList(&gp->artList);
  454.         Examine(lock, fib);
  455.         while (ExNext(lock, fib)) {
  456.             if (fib->fib_DirEntryType > 0) continue;
  457.             if (!atoi(fib->fib_FileName)) continue;
  458.             ap = (ART *)malloc(sizeof(ART));
  459.             panic0(ap, "Can't malloc ART %d bytes", sizeof(ART));
  460.             ap->node.ln_Name = &ap->header[0];
  461.             ap->state = UNREAD;
  462.             ap->filenum = atoi(fib->fib_FileName);
  463.  
  464.             sprintf(filename, "%s/%s", groupName, fib->fib_FileName);
  465.             fp = fopen(filename, "r");
  466.             panic0(fp, "open on %s failed", filename);
  467.             strcpy(from, "UNKNOWN");
  468.             strcpy(subject, "NO SUBJECT");
  469.             while (fgets(temp, 512, fp)) {
  470.                 temp[strlen(temp)-1] = '\0';
  471.                 if (!temp[0]) break;
  472.                 if (!strncmp(temp, "From: ", 6)) strcpy(from, &temp[6]);
  473.                 else if (!strncmp(temp, "Subject: ", 9)) strcpy(subject, &temp[9]);
  474.             }
  475.             fclose(fp);
  476.  
  477.             FixName(temp, from);
  478.             ap->from = (char *)malloc(strlen(temp)+1);
  479.             panic0(ap->from, "Can't allocate memory for From:\n");
  480.             strcpy(ap->from, temp);
  481.  
  482.             ap->subject = (char *)malloc(strlen(subject)+1);
  483.             panic0(ap->subject, "Can't allocate memory for subject:\n");
  484.             strcpy(ap->subject, subject);
  485.  
  486.             AddTail(&gp->artList, (NODE *)ap);
  487.             gp->articles++; gp->unread++;
  488.         }
  489.         sprintf(gp->header, "%-40.40s %6d articles %6d UnRead", gp->groupName, gp->articles, gp->unread);
  490.     }
  491.     UnLock(lock); lock = 0;
  492.     treeDirty = !0;
  493. }
  494.  
  495. void    ReadNewsTree() {
  496.     ART    *ap;
  497.     GLIST    *gp;
  498.     char    groupName[256], temp[256];
  499.     UWORD    endTest;
  500.     ULONG    pct;
  501.  
  502.     t_printf(mainWindow, "GRn - Reading News Tree...");
  503.     while (1) {
  504.         if (!mgets(&groupName[0])) break;
  505.         gp = (GLIST *)malloc(sizeof(GLIST));
  506.         panic0(gp, "Can't malloc GLIST %d bytes", sizeof(GLIST));
  507.         gp->node.ln_Name = &gp->header[0];
  508.         AddTail(&groupList, (NODE *)gp);
  509.         NewList(&gp->artList);
  510.         gp->articles = gp->unread = 0;
  511.         mread(&gp->hideHeaders, 1);
  512.         mread(&gp->hideRead, 1);
  513.         mread(&gp->nextReceived, 4);
  514.         mread(&gp->sortActive, 2);
  515.         pct = (100*(ULONG)(mbufp-mbuf))/(ULONG)(mbufe-mbuf);
  516.         if (GuageRequest(pct,"Initializing", "Setting up News Tree", "Abort")) Abort();
  517.         while (1) {
  518.             mread(&endTest, 2);
  519.             if (endTest == END) break;
  520.             ap = (ART *)malloc(sizeof(ART));
  521.             panic0(ap, "Can't malloc ART %d bytes", sizeof(ART));
  522.             ap->node.ln_Name = &ap->header[0];
  523.             ap->state = endTest;
  524.             mread(&ap->filenum, 4);
  525.             mgets(temp);
  526.             ap->from = (char *)malloc(strlen(temp)+1);
  527.             panic0(ap->from, "Can't allocate memory for From: field");
  528.             strcpy(ap->from, temp);
  529.  
  530.             mgets(temp);
  531.             ap->subject = (char *)malloc(strlen(temp)+1);
  532.             panic0(ap->subject, "Can't allocate memory for Subject: field");
  533.             strcpy(ap->subject, temp);
  534.  
  535.             AddTail(&gp->artList, (NODE *)ap);
  536.             gp->articles++;
  537.             if (ap->state == UNREAD || ap->state == NEW) gp->unread++;
  538.         }
  539.         strcpy(gp->groupName, groupName);
  540.         sprintf(gp->header, "%-40.40s %6d articles %6d UnRead", gp->groupName, gp->articles, gp->unread);
  541.     }
  542.     mclose();
  543. }
  544.  
  545. void    UpdateNewsTree() {
  546.     GLIST    *gp;
  547.     ART    *ap;
  548.     long    num, last;        // article number
  549.     char    fname[256], work[512], from[512], subject[512];
  550.     FILE    *fp;
  551.     BOOL    flag;
  552.  
  553.     // for each group
  554.     for (gp=(GLIST *)groupList.lh_Head; gp->node.ln_Succ; gp = (GLIST *)gp->node.ln_Succ) {
  555.         t_printf(mainWindow, "GRn - Pruning %s", gp->groupName);
  556.         // scan through list and check to see if the files are still there!
  557.         flag = 0;
  558.         for (ap=(ART *)gp->artList.lh_Head; ap->node.ln_Succ; ap = (ART *)ap->node.ln_Succ) {
  559.             strcpy(fname, uunews);
  560.             AddPart(fname, NewsGroupToFileName (gp->groupName), 256);
  561.             sprintf(work, "%d", ap->filenum);
  562.             AddPart(fname, work, 256);
  563.             if (!flag) {
  564.                 lock = Lock(fname, SHARED_LOCK);
  565.                 if (lock) {
  566.                     UnLock(lock); lock = 0;
  567.                     flag = !0;
  568.                 }
  569.                 else {
  570.                     if (ap->state == UNREAD) gp->unread--;
  571.                     gp->articles--;
  572.                     Remove((NODE *)ap);
  573.                     if (ap->subject) free(ap->subject);
  574.                     if (ap->from) free(ap->from);
  575.                     free(ap);
  576.                     treeDirty = !0;
  577.                 }
  578.             }
  579.         }
  580.         // Find new articles, mark as unread!
  581.         t_printf(mainWindow, "GRn - Getting new articles for %s", gp->groupName);
  582.         strcpy(fname, uunews);
  583.         AddPart(fname, NewsGroupToFileName (gp->groupName), 256);
  584.         AddPart(fname, ".next", 256);
  585.         fp = fopen(fname, "r");
  586.         if (fp) {
  587.             fgets(work, 512, fp);
  588.             fclose(fp);
  589.             last = atoi(work);
  590.         }
  591.         else {
  592.             last = 1000000;
  593.         }
  594.         for (num = gp->nextReceived; num<last; num++) {
  595.             strcpy(fname, uunews);
  596.             AddPart(fname, NewsGroupToFileName (gp->groupName), 256);
  597.             sprintf(work, "%d", num);
  598.             AddPart(fname, work, 256);
  599.             fp = fopen(fname, "r");
  600.             if (!fp) {
  601.                 if (last == 1000000) break;
  602.                 continue;
  603.             }
  604.             ap = (ART *)malloc(sizeof(ART));
  605.             panic0(ap, "Can't malloc ART %d bytes", sizeof(ART));
  606.             ap->node.ln_Name = &ap->header[0];
  607.             ap->state = UNREAD;
  608.             ap->filenum = num;
  609.  
  610.             strcpy(from, "UNKNOWN");
  611.             strcpy(subject, "NO SUBJECT");
  612.             while (fgets(work, 512, fp)) {
  613.                 work[strlen(work)-1] = '\0';
  614.                 if (!work[0]) break;
  615.                 if (!strncmp(work, "From: ", 6)) strcpy(from, &work[6]);
  616.                 else if (!strncmp(work, "Subject: ", 9)) strcpy(subject, &work[9]);
  617.             }
  618.             fclose(fp);
  619.             FixName(work, from);
  620.             ap->from = (char *)malloc(strlen(work)+1);
  621.             panic0(ap->from, "Can't allocate memory for From:\n");
  622.             strcpy(ap->from, work);
  623.             ap->subject = (char *)malloc(strlen(subject)+1);
  624.             panic0(ap->subject, "Can't allocate memory for subject:\n");
  625.             strcpy(ap->subject, subject);
  626.             AddTail(&gp->artList, (NODE *)ap);
  627.             gp->articles++;
  628.             gp->unread++;
  629.             treeDirty = !0;
  630.         }
  631.         sprintf(gp->header, "%-40.40s %6d articles %6d UnRead", gp->groupName, gp->articles, gp->unread);
  632.         if (gp->nextReceived != last) {
  633.             gp->nextReceived = last;
  634.             treeDirty = !0;
  635.         }
  636.     }
  637. }
  638.  
  639. void    CheckNews() {
  640.     ULONG    testver = 0x0a0a5050;
  641.  
  642.     if (!mopen(grnrcName)) {
  643.         BuildNewsTree();
  644.         return;
  645.     }
  646.     mread(&testver, 4);
  647.     if (testver != grnrcVersion) panic("grnrc is wrong version, delete it and run GRn again");
  648.     if (GuageRequest(0,"Initializing", "Setting up News Tree", "Abort")) Abort();
  649.     ReadNewsTree();
  650.     GuageRequest(1000,"Initializing", "Setting up News Tree", "Abort");
  651.     UpdateNewsTree();
  652.     SortList(&groupList, 0);
  653. }
  654.  
  655. /************************************************************************/
  656.  
  657. void    ParseConfig(void) {
  658.     char    buf[512], *ps;
  659.     FILE    *fp;
  660.     BOOL    uulibFlag = 0;
  661.  
  662.     userName[0] = mailEditor[0] = newsEditor[0] = '\0';
  663.     GetVar("USERNAME", &userName[0], 256, GVF_GLOBAL_ONLY);
  664.     GetVar("NEWSEDITOR", &newsEditor[0], 256, GVF_GLOBAL_ONLY);
  665.     GetVar("MAILEDITOR", &mailEditor[0], 256, GVF_GLOBAL_ONLY);
  666.     GetVar("SENDMAIL", &sendMail[0], 256, GVF_GLOBAL_ONLY);
  667.     GetVar("POSTNEWS", &postNews[0], 256, GVF_GLOBAL_ONLY);
  668.     if (userName[0] && newsEditor[0] && mailEditor[0] && sendMail[0] && postNews[0]) return;
  669.  
  670.     fp = fopen("s:uuconfig", "r");
  671.     if (!fp) {
  672.         fp = fopen("uulib:config", "r");
  673.         panic0(fp, "Can't open uulib:config");
  674.         uulibFlag = !0;
  675.     }
  676.     while (fgets(buf, 512, fp) && (!userName[0] || !newsEditor[0] || !mailEditor[0] || !sendMail[0] || !postNews[0])) {
  677.         buf[strlen(buf)-1] = '\0';
  678.         if (userName[0] == '\0' && !strnicmp(buf, "UserName", 8)) {
  679.             ps = &buf[8];
  680.             while (*ps == ' ' || *ps == '\t') ps++;
  681.             if (*ps == '\0') panic("s:uuconfig or uulib:config UserName is NULL");
  682.             strcpy(userName, ps);
  683.         }
  684.         else if (newsEditor[0] == '\0' && !strnicmp(buf, "NewsEditor", 10)) {
  685.             ps = &buf[10];
  686.             while (*ps == ' ' || *ps == '\t') ps++;
  687.             if (*ps == '\0') panic("s:uuconfig or uulib:config NewsEditor is NULL");
  688.             strcpy(newsEditor, ps);
  689.         }
  690.         else if (mailEditor[0] == '\0' && !strnicmp(buf, "MailEditor", 10)) {
  691.             ps = &buf[10];
  692.             while (*ps == ' ' || *ps == '\t') ps++;
  693.             if (*ps == '\0') panic("s:uuconfig or uulib:config MailEditor is NULL");
  694.             strcpy(mailEditor, ps);
  695.         }
  696.         else if (sendMail[0] == '\0' && !strnicmp(buf, "SendMail", 8)) {
  697.             ps = &buf[8];
  698.             while (*ps == ' ' || *ps == '\t') ps++;
  699.             if (*ps == '\0') panic("s:uuconfig or uulib:config Sendmail is NULL");
  700.             strcpy(sendMail, ps);
  701.         }
  702.         else if (postNews[0] == '\0' && !strnicmp(buf, "PostNews", 8)) {
  703.             ps = &buf[8];
  704.             while (*ps == ' ' || *ps == '\t') ps++;
  705.             if (*ps == '\0') panic("s:uuconfig or uulib:config Postnews is NULL");
  706.             strcpy(postNews, ps);
  707.         }
  708.         else if (!strnicmp(buf, "UUNews", 6)) {
  709.             ps = &buf[6];
  710.             while (*ps == ' ' || *ps == '\t') ps++;
  711.             if (*ps) strcpy(uunews, ps);
  712.         }
  713.         else if (!uulibFlag && !strnicmp(buf, "UUlib", 5)) {
  714.             ps = &buf[5];
  715.             while (*ps == ' ' || *ps == '\t') ps++;
  716.             if (*ps) strcpy(uulib, ps);
  717.         }
  718.         else if (!strnicmp(buf, "UUSpool", 7)) {
  719.             ps = &buf[7];
  720.             while (*ps == ' ' || *ps == '\t') ps++;
  721.             if (*ps) strcpy(uuspool, ps);
  722.         }
  723.     }
  724.     fclose(fp);
  725.     if (userName[0]) {
  726.         strcpy(grnrcName, uulib);
  727.         sprintf(buf, "%s.grnrc", userName);
  728.         AddPart(grnrcName, buf, 256);
  729.     }
  730.     else
  731.         panic("s:uuconfig or uulib:config must contain UserName!");
  732.     if (newsEditor[0] && !mailEditor[0])
  733.         strcpy(mailEditor, newsEditor);
  734.     else if (!newsEditor[0] && mailEditor[0])
  735.         strcpy(newsEditor, mailEditor);
  736.     panic0((APTR)newsEditor[0], "s:uuconfig or uulib:config must contain NewsEditor");
  737.     panic0((APTR)mailEditor[0], "s:uuconfig or uulib:config must contain MailEditor");
  738.     if (!sendMail[0]) strcpy(sendMail, "SendMail");
  739.     if (!postNews[0]) strcpy(postNews, "PostNews");
  740.     if (!logfile[0]) {
  741.         strcpy(logfile, uuspool);
  742.         AddPart(logfile, "logfile", 256);
  743.     }
  744. }
  745.  
  746. /************************************************************************/
  747.  
  748. void    QueryAbort() {
  749.     if (!treeDirty) Abort();
  750.     if (TwoGadgetRequest("GRN - Abort...", "Quit without updating News Tree?", "_YES", "_NO, I cnanged my mind")) Abort();
  751.     mode = GROUPS_MODE;
  752. }
  753.  
  754. void    TRAP() {
  755.     UWORD    *custom = (UWORD *)0xdff180;
  756.     UWORD    i = 0;
  757.  
  758.     while (1) *custom = i++;
  759. }
  760.  
  761. int    main(int ac, char *av[]) {
  762.     LIBRARY *check;
  763.     STRPTR    s;
  764.     char    **tt;
  765.     BOOL    lFlag = 0, tFlag = 0, hFlag = 0;
  766.  
  767.  
  768.     check = OpenLibrary("intuition.library", 37);
  769.     if (!check) {
  770.         printf ("Can't open intuition.library\n");
  771.         panic("Requires OS version 37 or higher");
  772.     }
  773.     CloseLibrary(check);
  774.  
  775.     if (ac == 0) {
  776.         WorkbenchBase = OpenLibrary("workbench.library", 0);
  777.         panic0(WorkbenchBase, "Can't open workbench.library");
  778.         IconBase = OpenLibrary("icon.library", 0);
  779.         panic0(IconBase, "Can't open icon.library");
  780.         CxBase = OpenLibrary("commodities.library", 0);
  781.         panic0(CxBase, "Can't open commodities.library");
  782.         tt = ArgArrayInit(ac, av);
  783.         panic0(tt, "Can't ArgArrayInit...");
  784.  
  785.         s = ArgString(tt, "TOP", "");
  786.         if (s[0]) { prefTop = atoi(s); tFlag = !0; }
  787.         s = ArgString(tt, "LEFT", "");
  788.         if (s[0]) { prefLeft = atoi(s); lFlag = !0; }
  789.         s = ArgString(tt, "WIDTH", "");
  790.         if (s[0]) prefWidth = atoi(s);
  791.         s = ArgString(tt, "HEIGHT", "");
  792.         if (s[0]) { prefHeight = atoi(s); hFlag = !0; }
  793.         s = ArgString(tt, "MSGFONT", "");
  794.         if (s[0]) strcpy(prefFontName, s);
  795.         s = ArgString(tt, "MSGFONTSIZE", "");
  796.         if (s[0]) prefFontSize = atoi(s);
  797.         s = ArgString(tt, "LOGFILE", "");
  798.         if (s[0]) strcpy(logfile, s);
  799.         s = ArgString(tt, "WRAP", "");
  800.         if (s[0]) wrapCol = atoi(s);
  801.         ArgArrayDone();
  802.         CloseLibrary(CxBase);
  803.         CloseLibrary(IconBase);
  804.         CloseLibrary(WorkbenchBase);
  805.         InitSystem();
  806.     }
  807.     else {
  808.         InitSystem();
  809.         prefLeft = screenWidth - prefWidth;
  810.         prefTop = screenTop;
  811.         prefHeight = screenHeight-screenTop;
  812.     }
  813.     if (ac == 0) {
  814.         if (!lFlag) prefLeft = screenWidth - prefWidth;
  815.         if (!tFlag) prefTop = screenTop;
  816.         if (!hFlag) prefHeight = screenHeight-screenTop;
  817.     }
  818.  
  819.     onbreak(Abort);
  820.  
  821.     port = FindPort("GRN_PORT");
  822.     if (port) {
  823.         port = 0;
  824.         DisplayBeep(screen);
  825.         Abort();
  826.     }
  827.     port = CreatePort("GRN_PORT", 0);
  828.     panic0(port, "Can't create GRN_PORT");
  829.  
  830.     fib = (FIB *)AllocDosObject(DOS_FIB, TAG_DONE);
  831.     panic0(fib, "Can't AllocDosObject(DOS_FIB)");
  832.  
  833.     NewList(&groupList);
  834.  
  835.     windowHeight = prefHeight;
  836.     mainWindow = CreateWindow(NULL, prefLeft, prefTop, prefWidth,windowHeight, "GRn - Looking for news...");
  837.     panic0(mainWindow, "Can't open main window");
  838.  
  839.     saveReq = (FILEREQ *)AllocAslRequestTags(ASL_FileRequest,
  840.         ASL_Hail, "Save Message...",
  841.         ASL_Window, mainWindow,
  842.         ASL_FuncFlags, FILF_SAVE,
  843.         TAG_DONE
  844.     );
  845.     panic0(saveReq, "Can't AllocFileRequest");
  846.  
  847.     publishReq = (FILEREQ *)AllocAslRequestTags(ASL_FileRequest,
  848.         ASL_Hail, "Publish File...",
  849.         ASL_Window, mainWindow,
  850.         TAG_DONE
  851.     );
  852.     panic0(publishReq, "Can't AllocFileRequest");
  853.  
  854.     t_printf(mainWindow, "GRn - Getting your UserName");
  855.     ParseConfig();
  856.     CheckNews();
  857.  
  858.     currentGroup = (GLIST *)groupList.lh_Head;
  859.  
  860.     while (mode != QUIT_MODE) {
  861.         switch (mode) {
  862.             case NEXTGROUPS_MODE:
  863.             case PREVGROUPS_MODE:
  864.             case GROUPS_MODE:    GroupsWindow(); break;
  865.             case ARTICLES_MODE:    ArticlesWindow(); break;
  866.             case QUIT_MODE:     break;
  867.             case ABORT_MODE:    QueryAbort(); break;
  868.             default:        break;
  869.         }
  870.     }
  871.     WriteNewsTree();
  872.     Abort();
  873. }
  874.  
  875. int    wbmain(struct WBStartup *msg) {
  876.     LIBRARY *check;
  877.     char    *s;
  878.     BOOL    lFlag = 0, tFlag = 0, hFlag = 0;
  879.     char    **tt;
  880.     union {
  881.         char            **args;
  882.         struct WBStartup    *msg;
  883.     } argv;
  884.  
  885.     argv.msg = msg;
  886.     check = OpenLibrary("intuition.library", 37);
  887.     if (!check) panic("Requires OS version 37 or higher");
  888.     CloseLibrary(check);
  889.  
  890.     WorkbenchBase = OpenLibrary("workbench.library", 0);
  891.     panic0(WorkbenchBase, "Can't open workbench.library");
  892.     IconBase = OpenLibrary("icon.library", 0);
  893.     panic0(IconBase, "Can't open icon.library");
  894.     CxBase = OpenLibrary("commodities.library", 0);
  895.     panic0(CxBase, "Can't open commodities.library");
  896.     CurrentDir(msg->sm_ArgList->wa_Lock); /* DICE's startup code doesn't do this */
  897.     tt = ArgArrayInit(0, argv.args);
  898.     panic0(tt, "Can't ArgArrayInit2...");
  899.  
  900.     s = ArgString(tt, "TOP", "");
  901.     if (s[0]) { prefTop = atoi(s); tFlag = !0; }
  902.     s = ArgString(tt, "LEFT", "");
  903.     if (s[0]) { prefLeft = atoi(s); lFlag = !0; }
  904.     s = ArgString(tt, "WIDTH", "");
  905.     if (s[0]) prefWidth = atoi(s);
  906.     s = ArgString(tt, "HEIGHT", "");
  907.     if (s[0]) { prefHeight = atoi(s); hFlag = !0; }
  908.     s = ArgString(tt, "MSGFONT", "");
  909.     if (s[0]) strcpy(prefFontName, s);
  910.     s = ArgString(tt, "MSGFONTSIZE", "");
  911.     if (s[0]) prefFontSize = atoi(s);
  912.     s = ArgString(tt, "LOGFILE", "");
  913.     if (s[0]) strcpy(logfile, s);
  914.     s = ArgString(tt, "WRAP", "");
  915.     if (s[0]) wrapCol = atoi(s);
  916.     ArgArrayDone();
  917.     CloseLibrary(CxBase);
  918.     CloseLibrary(IconBase);
  919.     CloseLibrary(WorkbenchBase);
  920.     if (!lFlag) prefLeft = screenWidth - prefWidth;
  921.     if (!tFlag) prefTop = screenTop;
  922.     if (!hFlag) prefHeight = screenHeight-screenTop;
  923.     return main(1,NULL);
  924. }
  925.