home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / auucp+-1.02 / fuucp_plus_src.lzh / postnews.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-29  |  37.0 KB  |  1,658 lines

  1. /*
  2.  * This software is Copyright 1986, 1989 by Rick Adams.
  3.  *
  4.  * Permission is hereby granted to copy, reproduce, redistribute or
  5.  * otherwise use this software as long as: there is no monetary
  6.  * profit gained specifically from the use or reproduction or this
  7.  * software, it is not sold, rented, traded or otherwise marketed, and
  8.  * this copyright notice is included prominently in any copy
  9.  * made.
  10.  *
  11.  * The author make no claims as to the fitness or correctness of
  12.  * this software for any use whatsoever, and it is provided as is. 
  13.  * Any use of this software is at the user's own risk.
  14.  *
  15.  * Postnews: post a news message to Usenet.  This C version replaces a shell
  16.  * script, and does more intelligent prompting and filtering than possible
  17.  * in a shell script.
  18.  *
  19.  * Ported to the Amiga by Ingo Feulner 1990.
  20.  *
  21.  *  2 Oct 90: Fixed a bug in the date routine.
  22.  *
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include <fcntl.h>
  29. #include <errno.h>
  30.  
  31. #ifdef AMIGA
  32. #include <dos.h>
  33. #include <time.h>
  34. // #include "unix.h"
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37. #include "include/config.h"
  38. #include "postnews.h"
  39. // #include "system.h"
  40.  
  41.  
  42. #define MKTEMP mktemp
  43. #define UNLINK remove
  44. #define perror poserr
  45. #define DFTEDITOR "c:ed"
  46.  
  47. #define LBUFLEN 1024
  48. #define BUFLEN  512
  49. #define MBUFLEN 256
  50. #define SBUFLEN 32
  51.  
  52. #define NGDELIM ','
  53. #define NEGCHAR '!'
  54.  
  55. extern char *__regargs mktemp(char *);
  56.  
  57. #define index strchr
  58. #define rindex strrchr
  59. char *_TZ;
  60.  
  61. FILE *xfopen(char *, char *);
  62. void copydists(char *, char *, char *);
  63.  
  64. static char *version20 = "$VER: postnews 1.03 (2 Oct 90)\n\r";
  65.  
  66. #endif /* AMIGA */
  67.  
  68. #define APPEND 1
  69. #define REPLACE 2
  70.  
  71.  
  72. char tempfname[50];        /* file name used for making article */
  73. char original[MBUFLEN];        /* file name of original, used in followup */
  74.  
  75. #ifndef AMIGA
  76. char user[SBUFLEN];        /* user name */
  77. #else
  78. char *newsdir;                  /* news directory */
  79. char *activefile;               /* full path of active file */
  80. char *newslibdir;               /* news lib directory */
  81. char *bugfile;                  /* full path of bug file */
  82.  
  83. char *user;            /* user name */
  84. char *realname;            /* user realname */
  85. char *node;            /* node */
  86. char *domain;            /* node domain */
  87. char *messageid;        /* messageid */
  88. char *organization;        /* organization */
  89. char *path;            /* posting path */
  90.  
  91. char curpath[256];              /* Path postnews was called from */
  92.  
  93. char approve_able = 1;          /* Should we check if the user has inserted
  94.                                    an 'Approved:' line in the header?
  95.                                    Only NEW article.
  96.                                 */
  97. #endif /* !AMIGA */
  98.  
  99. char ccname[MBUFLEN];        /* file name for article copy */
  100.  
  101. /* article header information */
  102. char subject[MBUFLEN];
  103. char distribution[MBUFLEN];
  104. char references[BUFLEN];
  105. char newsgroups[BUFLEN];
  106. char followto[MBUFLEN];
  107. char isfrom[MBUFLEN];
  108. char msgid[MBUFLEN];
  109. char keywords[MBUFLEN];
  110. char summary[BUFLEN];
  111. char approved[MBUFLEN];
  112.  
  113. char ngsep[] = { NGDELIM, '\0' };    /* == "," */
  114.  
  115. char *Progname = "postnews";        /* for xerror */
  116.  
  117. time_t fmodtime;
  118. char buf[BUFLEN];
  119.  
  120. #define MAXDISTR    16
  121. struct distr
  122. {
  123.     char abbr[24];
  124.     char descr[128];
  125. } distr[MAXDISTR];
  126.  
  127. char def_distr[24] = "";    /* default distribution */
  128.  
  129. void xerror(char *txt, long arg1, long arg2, long arg3)
  130. {
  131.   char buffer[BUFLEN];
  132.  
  133.   (void)sprintf(buffer, txt, arg1, arg2, arg3); 
  134.   (void)fprintf(stderr, buffer);
  135.   xxit(1);
  136. }
  137.  
  138.  
  139. void main(int argc, char *argv[])
  140. {
  141.     int c;
  142.  
  143.     init();
  144.  
  145.     if (argc == 2)
  146.     {
  147.                 approve_able = 0; /* Check  not for 'Approved' line -IF- */
  148.  
  149.         if (!prefix(argv[1], newsdir))
  150.             xerror("Can only followup to articles in %s\n", newsdir);
  151.  
  152.         followup(argv[1]);
  153.         (void) strcpy(original, argv[1]);
  154.  
  155.     }
  156.     else
  157.     {
  158.       if (askyes("Is this message in response to some other message? ","no"))
  159.       {
  160.         char ng[BUFLEN], num[BUFLEN];
  161.         long i, j, lastnum;
  162.         char *p;
  163.         int fd, dir;
  164.         char canpost;
  165.  
  166.                 approve_able = 0;
  167.  
  168.         getpr("In what newsgroup was the article posted? ",ng);
  169.         if (!valid_ng(ng, &i, &j, &canpost, TRUE))
  170.             if (canpost == 'i' )
  171.                 byebye("There is no such newsgroup.");
  172.             else if (canpost == 'n')
  173.                 byebye("You are not allowed to post to that group.");
  174.  
  175.         printf("Valid article numbers are from %ld to %ld\n", j, i);
  176.         lastnum = i + 1;
  177.         dir = -1;
  178.  
  179.         for(;;)
  180.         {
  181.             getpr("\nWhat was the article number? ", num);
  182.             switch(num[0]) {
  183.             case '+':
  184.                 dir = 1;
  185.                 sprintf(num, "%ld", lastnum + 1);
  186.                 break;
  187.             case '-':
  188.                 dir = -1;
  189.                 /* no break */
  190.             case '\0':
  191.                 sprintf(num, "%ld", lastnum + dir);
  192.                 break;
  193.             }
  194.  
  195.             (void) strcpy(original, MakeConfigPath(UUNEWS, ng));
  196.             for (p=original+strlen(newsdir)+1; *p ;++p)
  197.                 if (*p == '.')
  198.                     *p = '/';
  199.             (void) strcat(original, "/");
  200.             (void) strcat(original, num);
  201.  
  202.             if ((fd=open(original,0)) >= 0)
  203.             {
  204.                 (void) close(fd);
  205.  
  206.                 printf("\narticle %s\n", original);
  207.  
  208.                 if (article_line(original, "From: ", buf))
  209.                     printf("%s\n", buf);
  210.                 if (article_line(original, "Subject: ", buf))
  211.                     printf("%s\n", buf);
  212.                 if (askyes("Is this the one you want? ", "n"))
  213.                     break;
  214.             }
  215.             else
  216.                 printf("I can't find that article.\n");
  217.  
  218.             lastnum = atol(num);
  219.         }
  220.  
  221.         followup(original);
  222.       }
  223.       else
  224.       {
  225.         do
  226.         {
  227.             getpr("Subject: ", subject);
  228.             if (*subject == '?')
  229.             {
  230. printf("People read the subject line to learn what your article is about.\n");
  231. printf("You want it to do the same job as a newspaper headline.\n");
  232. printf("So type in something both brief and descriptive.\n");
  233.                 *subject = '\0';
  234.             }
  235.         } while (*subject == '\0');
  236.         getpr("Keywords: ", keywords);
  237.  
  238.         while (!get_newsgroup())
  239.             ;
  240.         get_distribution((char *)0);
  241.       }
  242.     }
  243.  
  244.     if (pre_checks())
  245.         xxit(1);
  246.  
  247.     prep_article();
  248.     c = 'e';
  249.     for (;;)
  250.     {
  251.         if (c == 'e')
  252.         {
  253.             edit_article();
  254.             post_checks();
  255.         }
  256.         do
  257.         {
  258.             do
  259.             {
  260.                 getpr("\nWhat now?  [send, edit, list, quit, write, append] ", buf);
  261.                 c = buf[0];
  262.             } while (c == '\0');
  263.             if (isupper(c))
  264.                 c = tolower(c);
  265.             if (c == 'q')
  266.             {
  267.                 (void) UNLINK(tempfname);
  268.                 xxit(1);
  269.             }
  270.             if (c == 'l')
  271.             {
  272.                 char *pager = getenv("PAGER");
  273.  
  274.                 if (pager == NULL || *pager == '\0')
  275.                 {
  276.                     pager = "type";
  277.                 }
  278.                 sprintf(buf, "%s %s", pager, tempfname);
  279.                 (void)Execute(buf, 0, 0);
  280.             }
  281.             if (c == 'w' || c == 'a')
  282.             {
  283.                 int ifd, ofd, nbytes;
  284.                 char iobuf[BUFSIZ];
  285.                 char fname[BUFLEN];
  286.                 getpr("Filename? ", fname);
  287.                 if (fname[0] == '\0')
  288.                     continue;
  289.                 ofd = (c == 'w') ? creat(fname, 0666)
  290.                          : open(fname, 2);
  291.                 if (ofd < 0)
  292.                     perror(fname);
  293.                 else
  294.                 {
  295.                     if (c == 'a')
  296.                         (void) lseek(ofd, 0L, 2);
  297.                     ifd = open(tempfname, 0);
  298.                     if (ifd < 0)
  299.                         xerror("Can't reopen %s\n", tempfname);
  300.                     while ((nbytes = read(ifd, iobuf, BUFSIZ)) > 0 )
  301.                         write(ofd, iobuf, nbytes);
  302.                     close(ofd);
  303.                     close(ifd);
  304.                 }
  305.             }
  306.         } while (!index("eps", c));
  307.         if (c != 'e')
  308.             post_article(); /* will exit if posted successfully */
  309.     }
  310. }
  311.  
  312. /*
  313.  * Find out the topic of interest.
  314.  */
  315. int get_newsgroup(void)
  316. {
  317.     int n;
  318.     long i;
  319.     char canpost;
  320.     static int first = 1;
  321.  
  322.     printf("Newsgroups (enter one at a time, end with a blank line):\n");
  323.     if (first)
  324.     {
  325.         printf("\nThe most relevant newsgroup should be the first, you should\n");
  326.         printf("add others only if your article really MUST be read by people\n");
  327.         printf("who choose not to read the appropriate group for your article.\n");
  328.         printf("But DO use multiple newsgroups rather than posting many times.\n\n");
  329.         first = 0;
  330.     }
  331.  
  332.     printf("For a list of newsgroups, type ?\n");
  333.     n = 0;
  334.     newsgroups[0] = '\0';
  335.  
  336.     for(;;)
  337.     {
  338.         getpr("> ", buf);
  339.         if (buf[0] == '\0')
  340.             if (n == 0)
  341.                 return FALSE;
  342.             else
  343.                 return TRUE;
  344.  
  345.         if (buf[0] == '?')
  346.         {
  347.             char *pager = getenv("PAGER");
  348.  
  349.             if (pager == NULL)
  350.             {
  351.                 pager = "type";
  352.             }
  353.             printf("These are the currently active groups:\n");
  354.             (void) fflush(stdout);
  355.  
  356.             sprintf(buf, "%s %s/newsgroups", pager, newslibdir);
  357.             (void) Execute(buf, 0, 0);
  358.             continue;
  359.         }
  360.  
  361.         if (valid_ng(buf, &i, &i, &canpost, FALSE))
  362.         {
  363.             if (n++ != 0)
  364.                 (void) strcat(newsgroups, ngsep);
  365.             (void) strcat(newsgroups, buf);
  366.         }
  367.         else
  368.         {
  369.             if (canpost == 'n')
  370.                 printf("You are not allowed to post to %s\n", buf);
  371.             else if (canpost == 'i')
  372.                 printf("%s is not a valid newsgroup.\n", buf);
  373.         }
  374.     }
  375. }
  376.  
  377. /*
  378.  * Find out how widely the author wants the message distributed.
  379.  */
  380. void get_distribution(deflt)
  381. char *deflt;
  382. {
  383.     int i;
  384.     char *r;
  385.     char def[BUFLEN];
  386.     char *lastgroup;
  387.  
  388.     lastgroup = newsgroups;
  389.     (void) strcpy(def, newsgroups);
  390.     r = index(def, NGDELIM);
  391.     if (r)
  392.         *r = '\0';
  393.     r = index(def, '.');
  394.     if (r)
  395.     {
  396.         *r = '\0';
  397.         if (strcmp(def, "net") == 0)
  398.             (void) strcpy(def, "world");
  399.     }
  400.     else
  401.     {
  402.         distribution[0] = '\0';
  403.         return;
  404.     }
  405.  
  406.     if (strcmp(def, "to") == 0)
  407.     {
  408.         /*
  409.          * This only works if "to.xx" is the first (or only)
  410.          * newsgroup, but it usually is ..
  411.          * Perhaps we should make the distribution be "to.xxx" ??
  412.          */
  413.         distribution[0] = '\0';
  414.         return;        /* He's probably testing something */
  415.     }
  416.     if (deflt != (char *)0)
  417.         (void) strcpy(def, deflt);
  418.     if (ngmatch("misc.test", newsgroups))
  419.         (void) strcpy(def, "local");
  420.     for (i=0; distr[i].abbr[0]; i++)
  421.     {
  422.         if (strcmp(distr[i].abbr, def) == 0)
  423.             break;
  424.     }
  425.     if (distr[i].abbr[0] == '\0')
  426.         strcpy(def, def_distr);
  427.     for(;;)
  428.     {
  429.         do
  430.         {
  431.             (void) sprintf(buf, "Distribution (default='%s', '?' for help) : ", def);
  432.             getpr(buf, distribution);
  433.             if (distribution[0] == '\0')
  434.             {
  435.                 if (strcmp(def, "*None*") == 0)
  436.                     printf("You must enter a distribution, '?' for help.\n");
  437.                 (void) strcpy(distribution, def);
  438.             }
  439.         } while (strcmp(distribution, "*None*") == 0);
  440.  
  441.         /* Did the user ask for help? */
  442.         if (distribution[0] == '?')
  443.         {
  444.             printf("How widely should your article be distributed?\n\n");
  445.             for (i=0; distr[i].abbr[0]; i++)
  446.                 printf("%s\t%s\n", distr[i].abbr, distr[i].descr);
  447.             printf("\nEnter the word that specifies the distribution that you require.\n");
  448.             continue;
  449.         }
  450.  
  451.         /* Check that it's a proper distribution */
  452.         for (i=0; distr[i].abbr[0]; i++)
  453.         {
  454.             if (strncmp(distr[i].abbr, distribution, sizeof(distr[0].abbr)) == 0)
  455.             {
  456.                 return;
  457.             }
  458.         }
  459.         if (strcmp(distribution, def) != 0)
  460.             printf("Type ? for help.\n");
  461.         else
  462.         {
  463.             int once = TRUE;
  464.  
  465.             do
  466.             {
  467.                 r = lastgroup;
  468.                 while (r = index(r, NGDELIM))
  469.                     if (!prefix(++r, def))
  470.                         break;
  471.                 if (r == NULL)
  472.                 {
  473.                     /*
  474.                      * no newsgroups are distribution
  475.                      * names, and user simply will
  476.                      * not type a valid distribution,
  477.                      * assume that the default is OK.
  478.                      */
  479.                     distribution[0] = '\0';
  480.                     return;
  481.                 }
  482.                 lastgroup = r;
  483.                 if (once)
  484.                     printf("Sorry, '%s' is an unknown distribution.  Type ? for help.\n", def);
  485.                 once = FALSE;
  486.                 strcpy(def, r);
  487.                 r = index(def, NGDELIM);
  488.                 if (r)
  489.                     *r = '\0';
  490.                 r = index(def, '.');
  491.             } while (r == NULL);
  492.             *r = '\0';
  493.             if (strcmp(def, "net") == 0)
  494.                 strcpy(def, "world");
  495.         }
  496.     }
  497. }
  498.  
  499. /*
  500.  * Do sanity checks before the author types in the message.
  501.  */
  502. int pre_checks(void)
  503. {
  504.     if (recording(newsgroups))
  505.         return 1;
  506.     return 0;
  507. }
  508.  
  509. /*
  510.  * Set up the temp file with headers.
  511.  */
  512. void prep_article(void)
  513. {
  514.     FILE *tf, *of;
  515.     struct stat stbuf;
  516.  
  517.     (void) strcpy(tempfname, "T:postXXXXXXXX");
  518.     MKTEMP(tempfname);
  519.  
  520.     /* insert a header */
  521.     tf = xfopen(tempfname, "w");
  522.     fprintf(tf, "Subject: %s\n", subject);
  523.     fprintf(tf, "Newsgroups: %s\n", newsgroups);
  524.  
  525.     if (followto[0] != '\0')
  526.         fprintf(tf, "Followup-To: %s\n", followto);
  527.  
  528.     if (distribution[0] != '\0' && strcmp(distribution, "world"))
  529.         fprintf(tf, "Distribution: %s\n", distribution);
  530.  
  531.     if (keywords[0] != '\0')
  532.         fprintf(tf, "Keywords: %s\n", keywords);
  533.  
  534.     if (summary[0] != '\0')
  535.         fprintf(tf, "Summary: %s\n", summary);
  536.  
  537.     if (references[0] != '\0') {
  538.         fprintf(tf, "References: %s\n\n", references);
  539.  
  540.         if (askyes("Do you want to include a copy of the article? ", "no")){
  541.             of = xfopen(original, "r");
  542.             while (fgets(buf, BUFLEN, of) != NULL)
  543.                 if (buf[0] == '\n')    /* skip headers */
  544.                     break;
  545.             fprintf(tf, "In article %s, %s writes:\n", msgid, isfrom);
  546.             while (fgets(buf, BUFLEN, of) != NULL)
  547.                 fprintf(tf, "> %s", buf);
  548.             (void) fclose(of);
  549.             printf("OK, but please edit it to suppress unnecessary verbiage, signatures, etc.\n");
  550.             (void) fflush(stdout);
  551.         }
  552.     }
  553.  
  554.     fprintf(tf, "\n\n");
  555.     (void) fflush(tf);
  556.     (void) fclose(tf);
  557.     (void) stat(tempfname, &stbuf);
  558.     fmodtime = stbuf.st_mtime;
  559. }
  560.  
  561. void edit_article(void)
  562. {
  563.     char *editor;
  564.         char buf[BUFLEN];
  565.  
  566.     /* edit the file */
  567.     editor = FindConfig(NEWSEDITOR);
  568.     if (editor == NULL)
  569.         editor = DFTEDITOR;
  570.  
  571.     (void) sprintf(buf, "%s %s", editor, tempfname);
  572.     (void) Execute(buf, 0, 0);
  573.  
  574.         if(approve_able == 1) /* Check for 'Approved:' line -IF- */
  575.         {
  576.           if(article_line(tempfname, "Approved: ", buf) == TRUE)
  577.             strcpy(approved, &buf[10]);
  578.         } 
  579. }
  580.  
  581. /*
  582.  * Do sanity checks after the author has typed in the message.
  583.  */
  584. void post_checks(void)
  585. {
  586.     char group[BUFLEN];
  587.     char *c, *p;
  588.     struct stat stbuf;
  589.  
  590.     if (stat(tempfname, &stbuf) < 0)
  591.     {
  592.         printf("File deleted - no message posted.\n");
  593.         (void) UNLINK(tempfname);
  594.         xxit(1);
  595.     }
  596.     if (stbuf.st_size < 5)
  597.     {
  598.         printf("File too small (<5 characters) - no message posted.\n");
  599.         (void) UNLINK(tempfname);
  600.         xxit(1);
  601.     }
  602.  
  603.     if (stbuf.st_mtime == fmodtime)
  604.     {
  605.         printf("File not modified - no message posted.\n");
  606.         (void) UNLINK(tempfname);
  607.         xxit(1);
  608.     }
  609.  
  610.     /*
  611.      * Is this the right number?  Most of the headers are yet to be added
  612.      */
  613.     if (stbuf.st_size > 64000)
  614.     {
  615.         printf("\nYour message will probably be truncated when it\n");
  616.         printf("passes through a notesfile site, since it is\n");
  617.         printf("greater than 64000 characters.\n\n");
  618.         if (!askyes("Do you still want to post it? ",""))
  619.                 {
  620.             sprintf(ccname, "%s/dead.article", newslibdir);
  621.             save_article();
  622.             (void) UNLINK(tempfname);
  623.             xxit(1);
  624.         }
  625.     }
  626.  
  627.     /*
  628.      * get the newsgroups from the edited article, in
  629.      * case they were altered in the editor
  630.      */
  631.     if (!article_line(tempfname, "Newsgroups: ", group))
  632.     {
  633.   nogroups:
  634.         printf("Not sending to any newsgroups - no message posted\n");
  635.         sprintf(ccname, "%s/dead.article", newslibdir);
  636.         save_article();
  637.         (void) UNLINK(tempfname);
  638.         xxit(1);
  639.     }
  640.     c = &group[11];
  641.     while (*c == ' ' || *c == '\t')
  642.         c++;
  643.     if (*c == '\0')
  644.         goto nogroups;
  645.     for (p = newsgroups; *c; c++)    /* copy to newsgroups, w/o blanks */
  646.         if (*c != ' ' && *c != '\t')
  647.             *p++ = *c;
  648.     *p = '\0';
  649.  
  650.     /* Sanity checks for certain newsgroups */
  651.     if (ngmatch(newsgroups, "all.wanted") && ngmatch(distribution,"world,na,usa,att,btl,eunet,aus"))
  652.     {
  653.         printf("Is your message something that might go in your local\n");
  654.         printf("newspaper, for example a used car ad, or an apartment\n");
  655.         printf("for rent? ");
  656.         if (askyes("",""))
  657.         {
  658.             printf("It's pointless to distribute your article widely, since\n");
  659.             printf("people more than a hundred miles away won't be interested.\n");
  660.             printf("Please use a more restricted distribution.\n");
  661.             get_distribution("*None*");
  662.             modify_article(tempfname, "Distribution: ", distribution,REPLACE);
  663.         }
  664.     }
  665.  
  666.     if (ngmatch(newsgroups, "sub.jokes,sub.sex,rec.humor,!rec.humor.all"))
  667.     {
  668.         if (askyes("Could this be offensive to anyone? ",""))
  669.         {
  670.             getpr("Whom might it offend? ", group);
  671.             (void) sprintf(buf," - offensive to %s (rot 13)", group);
  672.             modify_article(tempfname, "Subject: ", buf, APPEND);
  673.             encode(tempfname);
  674.         }
  675.     }
  676.  
  677.     if (ngmatch(newsgroups, "sub.sources.all,!sub.sources.d,comp.sources.all,!comp.sources.wanted,!comp.sources.d,!comp.sources.bugs"))
  678.     {
  679.         if (!article_line(tempfname, "Subject: ", group))
  680.         {
  681.   nosubj:
  682.             printf("There seems to be no subject for this article.\n");
  683.             getpr("Subject: ", subject);
  684.             modify_article(tempfname, "Subject: ", subject, REPLACE);
  685.         }
  686.         else
  687.         {
  688.             c = &group[8];
  689.             while (*c == ' ' || *c == '\t')
  690.                 c++;
  691.             if (*c == '\0')
  692.                 goto nosubj;
  693.             strcpy(subject, c);
  694.         }
  695.         if (ngmatch(newsgroups, "sub.sources.d,all.wanted") || iswanted(subject))
  696.         {
  697.             printf("Requests for sources should not be posted to any of\n");
  698.             printf("the comp.sources newsgroups, please post such requests\n");
  699.             printf("to comp.sources.wanted only.     Please reenter the newsgroups.\n\n");
  700.             while (!get_newsgroup())
  701.                 ;
  702.             modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
  703.         }
  704.         if (ngmatch(newsgroups, "sub.sources.all,comp.sources.all"))
  705.         {
  706.             if (stbuf.st_size < (4*1024))
  707.             {
  708.                 printf("Your article seems rather small to be a source distribution.\n");
  709.                 if (!askyes("Are you certain that this is really source? ", ""))
  710.                 {
  711.  
  712.                     while (!get_newsgroup())
  713.                         ;
  714.                     modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
  715.                 }
  716.             }
  717.             if (index(newsgroups, NGDELIM))
  718.             {
  719.                 printf("Sources should be posted to one newsgroup only.\n");
  720.                 printf("Please pick the most appropriate group for your article.\n\n");
  721.                 while (!get_newsgroup())
  722.                     ;
  723.                 modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
  724.             }
  725.         }
  726.     }
  727.     if (index(newsgroups, NGDELIM) != NULL && followto[0] == '\0')
  728.     {
  729.         printf("Your article is being posted to multiple newsgroups.\n");
  730.         printf("In which newsgroup should the responses be posted?\n");
  731.         printf("Newsgroups: %s\n", newsgroups);
  732.         printf("(If responses should be mailed to you, enter \"poster\")\n");
  733.         getpr("Followup-To: ", followto);
  734.         if (followto[0] != '\0')
  735.             modify_article(tempfname, "Followup-To: ", followto,
  736.                 REPLACE);
  737.     }
  738. }
  739.  
  740. int iswanted(char *str)
  741. {
  742.     while (*str == ' ')
  743.         str++;
  744.  
  745.     if (prefix(str, "Re:"))
  746.         return FALSE;
  747.  
  748.     if (isin(str, " wanted ") || isin(str, " can any") ||
  749.         isin(str, " need ") || isin(str, " please ") || isin(str, " help ")
  750.         || isin(str, " looking ") || index(str, '?'))
  751.         return TRUE;
  752.  
  753.     return FALSE;
  754. }
  755.  
  756. int isin(char *str, char *words)
  757. {
  758.     char *p;
  759.     int sc, wc;
  760.  
  761.     p = words;
  762.     while (sc = *str++)
  763.     {
  764.         if ((wc = *p++) == '\0')
  765.             return (TRUE);
  766.         if (wc == ' ')
  767.         {
  768.             if (index(".,!?-; \t\n", sc))
  769.                 continue;
  770.         }
  771.         else
  772.         {
  773.             if (isupper(wc))
  774.                 wc = tolower(wc);
  775.             if (isupper(sc))
  776.                 sc = tolower(sc);
  777.             if (wc == sc)
  778.                 continue;
  779.         }
  780.         str -= p - words - 1;
  781.         p = words;
  782.     }
  783.     if (*p == '\0')
  784.         return (TRUE);
  785.     return (FALSE);
  786. }
  787.  
  788. /*
  789.  * Save a copy of the article in the users NEWSARCHIVE directory.
  790.  */
  791. void save_article(void)
  792. {
  793.     FILE *in, *out;
  794.     int c;
  795.     time_t timenow, time();
  796.     char *today, *ctime();
  797.     struct stat stbuf;
  798.     char filename[BUFLEN];
  799.  
  800.     if (stat(ccname, &stbuf) == 0 && (stbuf.st_mode&S_IFMT) == S_IFDIR)
  801.     {
  802.         /*
  803.          * It would be much nicer here to write articles
  804.          * in MH format (numbered files, in rfc822 format)
  805.          *
  806.          * one day ..
  807.          */
  808.         (void) sprintf(filename, "%s/author_copy", ccname);
  809.         (void) strcpy(ccname, filename);
  810.     }
  811.     in = xfopen(tempfname, "r");
  812.     out = xfopen(ccname, "a");
  813.     timenow = time((time_t)0);
  814.     today = ctime(&timenow);
  815.     fprintf(out,"From postnews %s",today);
  816.     while ((c=getc(in)) != EOF)
  817.         putc(c, out);
  818.     putc('\n', out);
  819.     (void) fclose(in);
  820.     (void) fclose(out);
  821. }
  822.  
  823. /*
  824.  * Post the article to the net.
  825.  */
  826. void post_article(void)
  827. {
  828. #define TEMPOUT "T:pnews.final"
  829.  
  830.     FILE *fpout, *fpin, *sig;
  831.     int status;
  832.     int seq;
  833.     long count;
  834.     long pos;
  835.  
  836.     char buffer[LBUFLEN];
  837.     unsigned char c;
  838.     long t;
  839.  
  840.  
  841.     printf("Posting article...\n");
  842.     fflush(stdout);
  843.  
  844.     (void)time(&t);
  845.     seq = GetSequence(1);
  846.  
  847.     /* Open final output file and write header */
  848.     fpout = xfopen(TEMPOUT, "w");
  849.  
  850.     fprintf(fpout, "Path: %s\n", user);
  851.     fprintf(fpout, "From: %s@%s%s (%s)\n", user, node, domain, realname);
  852.     fprintf(fpout, "Newsgroups: %s\n", newsgroups);
  853.     fprintf(fpout, "Subject: %s\n", subject);
  854.     if(keywords[0] != '\0' && keywords[0] != '\n')
  855.       fprintf(fpout, "Keywords: %s\n", keywords);
  856.     if(summary[0] != '\0' && summary[0] != '\n')
  857.       fprintf(fpout, "Summary: %s\n", summary);
  858.     fprintf(fpout, "Message-ID: <%ld@%s%s>\n", seq, node, domain);
  859.     fprintf(fpout, "Date: %s GMT\n", gettime());
  860.     if(references[0] != '\0' && references[0] != '\n')
  861.       fprintf(fpout, "References: %s\n", references);
  862.     if(followto[0] != '\0' && followto[0] != '\n')
  863.       fprintf(fpout, "Followup-To: %s\n", followto);
  864.         if(distribution[0] != '\0')
  865.           fprintf(fpout, "Distribution: %s\n", distribution);
  866.     fprintf(fpout, "Organization: %s\n", organization);
  867.         if(approved[0] != '\0')
  868.           fprintf(fpout, "Approved: %s\n", approved);
  869.  
  870.  
  871.     /* Append .signature file if available */
  872.     fpin = xfopen(tempfname, "a");
  873.  
  874.     fprintf(fpin, "\n--\n");
  875.  
  876.     if((sig = fopen(MakeConfigPath(UULIB, ".signature"), "r")) != NULL)
  877.     {
  878.       while((c = getc(sig)) != EOF)
  879.         putc(c, fpin);
  880.     }
  881.     else
  882.     {
  883.       fprintf(fpin, "signature not available yet...\n");
  884.     }
  885.  
  886.     fclose(fpin);
  887.     fclose(sig);
  888.  
  889.     /* Set number of lines for header entry "Lines: " */
  890.     fpin = xfopen(tempfname, "r");
  891.  
  892.     /* Skip header: */
  893.     while(fgets(buffer, sizeof(buffer), fpin))
  894.       if(buffer[0] == '\n')
  895.         break;
  896.  
  897.     count = 0;
  898.     pos = ftell(fpin) - strlen(buffer);
  899.  
  900.     while(fgets(buffer, sizeof(buffer), fpin))
  901.       count++;
  902.  
  903.     fprintf(fpout, "Lines: %ld\n", count);
  904.  
  905.     (void)fseek(fpin, pos, 0);
  906.  
  907.     /* Copy article to TEMPFILE */
  908.     while((c = getc(fpin)) != EOF)
  909.       putc(c, fpout);
  910.  
  911.     fclose(fpin);
  912.     fclose(fpout);
  913.  
  914.     /* printf("Article will be spooled to the following system(s):\n"); */
  915.     (void) sprintf(buf, "relaynews <%s -i", TEMPOUT);
  916.     status = Execute(buf, 0, 0);
  917.     /* putc('\n', stdout); */
  918.   status = 0;
  919.     if (status)
  920.     {
  921.         printf("Article not posted - exit status %d\n", status);
  922.         return;
  923.     } else
  924.         printf("Article posted successfully.\n");
  925.  
  926.     if (ccname[0])
  927.     {
  928.         printf("A copy has been saved in %s\n", ccname);
  929.         save_article();
  930.     }
  931.  
  932.     (void) UNLINK(tempfname);
  933.     (void) UNLINK(TEMPOUT);
  934.     xxit(0);
  935. }
  936.  
  937. char *gettime(void)
  938. {
  939.   static char *wdays[] =
  940.   {
  941.     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  942.   };
  943.  
  944.   static char *mdays[] =
  945.   {
  946.     "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  947.   };
  948.  
  949.   struct tm *tm;
  950.   char *timestr;
  951.   long t;
  952.  
  953.  
  954.   (void)time(&t);
  955.   tm = gmtime(&t);
  956.  
  957.   if((timestr = malloc(50)) == NULL)
  958.     byebye("No mem free.");
  959.  
  960.   sprintf(timestr, "%s, %ld %s %ld %02ld:%02ld:%02ld",
  961.                             wdays[tm->tm_wday],
  962.                             tm->tm_mday,
  963.                             mdays[tm->tm_mon],
  964.                             tm->tm_year,
  965.                             tm->tm_hour,
  966.                             tm->tm_min,
  967.                             tm->tm_sec);
  968.   return(timestr);
  969. }
  970.  
  971. /*
  972. ** Initialization.
  973. */
  974.  
  975. void init(void)
  976. {
  977.     FILE *fd;
  978.     int i = 0;
  979.     char buffer[256];
  980.  
  981.     references[0] = '\0';
  982.     distribution[0] = '\0';
  983.         approved[0] = '\0';
  984.  
  985. #ifdef AMIGA
  986.         (void)getcwd(curpath, 256);
  987.  
  988.         newsdir    = GetConfigDir(UUNEWS);
  989.         newslibdir = MakeConfigPath(UULIB, "news");
  990.         bugfile    = MakeConfigPath(UUSPOOL, "post");
  991.  
  992.         activefile = malloc(strlen(newslibdir)+10);
  993.         sprintf(activefile, "%s/active", newslibdir);
  994.  
  995.     user = FindConfig(USERNAME);
  996.     realname = FindConfig(REALNAME);
  997.     node = FindConfig(NODENAME);
  998.     domain = FindConfig(DOMAINNAME);
  999.     organization = FindConfig(ORGANIZATION);
  1000.     _TZ = FindConfig("TimeZone");
  1001.  
  1002.     if(user == NULL || realname == NULL || node == NULL
  1003.            || domain == NULL || organization == NULL || _TZ == NULL)
  1004.     {
  1005.         printf("Please set your enviroment\n");
  1006.         printf("Some of these variables are missing:\n");
  1007.         printf("UserName, RealName, NodeName, DomainName, Organization, TimeZone\n");
  1008.         xxit(2);
  1009.     }
  1010. #endif
  1011.  
  1012.         tzset(); /* Set right timezone */
  1013.  
  1014.     sprintf(ccname, "%s/author_copy", newslibdir);
  1015.  
  1016.     /* pathinit(); */
  1017.  
  1018.     (void) sprintf(buf, "%s/distributions", newslibdir);
  1019.  
  1020.     fd = xfopen(buf, "r");
  1021.     for (i=0; i < MAXDISTR; i++)
  1022.     {
  1023.         /* if (fscanf(fd, "%s [%s^\n]", distr[i].abbr, distr[i].descr)
  1024.             != 2) */
  1025.  
  1026.         /* changed by -IF-. See copydists */
  1027.  
  1028.         if(fgets(buffer, sizeof(buffer)-1, fd) == NULL)
  1029.             break;
  1030.  
  1031.         copydists(buffer, distr[i].abbr, distr[i].descr);
  1032.  
  1033.         if (strcmp(distr[i].abbr, "default") == 0)
  1034.             strcpy(def_distr, distr[i--].descr);
  1035.     }
  1036.  
  1037.     fclose(fd);
  1038.     distr[i].abbr[0] = '\0';
  1039.     if (def_distr[0] == '\0')
  1040.         strcpy(def_distr, "world");    /* maybe "local" is better? */
  1041. }
  1042.  
  1043. /*
  1044.  *  copydists - -IF- 12.05.90
  1045.  *  Fuck the Lattice C *scanf routine!
  1046.  */
  1047.  
  1048. void copydists(char *buf, char *ab, char *de)
  1049. {
  1050.   char *ptr;
  1051.  
  1052.   ptr = buf;
  1053.  
  1054.   while(*ptr != ' ' && *ptr != '\t')
  1055.     *ab++ = *ptr++;
  1056.  
  1057.   *ab = '\0';
  1058.  
  1059.   while(*ptr == ' ' || *ptr == '\t')
  1060.     ptr++;
  1061.  
  1062.   strcpy(de, strtok(ptr, "\n\r"));
  1063. }
  1064.  
  1065. /*
  1066.  * Get a yes or no answer to a question.    A default may be used.
  1067.  */
  1068.  
  1069. int askyes(char *msg, char *def)
  1070. {
  1071.     for(;;) {
  1072.         printf("%s", msg);
  1073.         buf[0] = 0;
  1074.         (void) gets(buf);
  1075.         switch(buf[0]) {
  1076.         case 'y':
  1077.         case 'Y':
  1078.             return TRUE;
  1079.         case 'n':
  1080.         case 'N':
  1081.             return FALSE;
  1082.         case '\0':
  1083.             switch(*def) {
  1084.             case 'y':
  1085.             case 'Y':
  1086.                 return TRUE;
  1087.             case 'n':
  1088.             case 'N':
  1089.                 return FALSE;
  1090.             }
  1091.         default:
  1092.             printf("Please answer yes or no.\n");
  1093.         }
  1094.     }
  1095. }
  1096.  
  1097. /*
  1098.  * Get a character string into buf, using prompt msg.
  1099.  */
  1100. void getpr(char *msg, char *bptr)
  1101. {
  1102.     static int numeof = 0;
  1103.     printf("%s", msg);
  1104.     (void) gets(bptr);
  1105.     (void) nstrip(bptr);
  1106.     if (feof(stdin)) {
  1107.         if (numeof++ > 3) {
  1108.             fprintf(stderr,"Too many EOFs\n");
  1109.             xxit(1);
  1110.         }
  1111.         clearerr(stdin);
  1112.     }
  1113. }
  1114.  
  1115. void byebye(char *mesg)
  1116. {
  1117.     printf("%s\n", mesg);
  1118.     xxit(1);
  1119. }
  1120.  
  1121. /*
  1122.  * make a modification to the header of an article
  1123.  *
  1124.  *     fname -- name of article
  1125.  *     field -- header field to modify
  1126.  *     line    -- modification line
  1127.  *     how     -- APPEND or REPLACE
  1128.  *
  1129.  * example:
  1130.  *     modify_article("/tmp/article" , "Subject:" , "new subject" , REPLACE);
  1131.  *
  1132.  *
  1133.  */
  1134. void modify_article(char *fname, char *field, char *line, int how)
  1135. {
  1136.     FILE *fpart, *fptmp;
  1137.     char *temp2fname = "T:post2XXXXXXXX";
  1138.     char lbfr[BUFLEN];
  1139.     int  found = FALSE;
  1140.  
  1141.     MKTEMP(temp2fname);
  1142.  
  1143.     fptmp = xfopen(temp2fname, "w");
  1144.     fpart = xfopen(fname, "r");
  1145.  
  1146.     while (fgets(lbfr, BUFLEN, fpart) != NULL)
  1147.     {
  1148.         if (prefix(lbfr, field))
  1149.         {
  1150.             found = TRUE;
  1151.             (void) nstrip(lbfr);
  1152.             if (how == APPEND)
  1153.             {
  1154.                 /* append to current field */
  1155.                 (void) strcat(lbfr, line);
  1156.                 (void) strcat(lbfr, "\n");
  1157.             }
  1158.             else
  1159.                 /* replace current field */
  1160.                 (void) sprintf(lbfr, "%s%s\n", field, line);
  1161.         }
  1162.         (void) fputs(lbfr, fptmp);
  1163.     }
  1164.  
  1165.     fclose(fpart);
  1166.     fclose(fptmp);
  1167.  
  1168.     fptmp = xfopen(temp2fname, "r");
  1169.     fpart = xfopen(fname, "w");
  1170.  
  1171.     if (!found)
  1172.         fprintf(fpart, "%s%s\n", field, line);
  1173.     while (fgets(buf,BUFLEN,fptmp) != NULL)
  1174.         (void) fputs(buf, fpart);
  1175.  
  1176.     (void) fclose(fpart);
  1177.     (void) fclose(fptmp);
  1178.     (void) UNLINK(temp2fname);
  1179. }
  1180.  
  1181.  
  1182. /* verify that newsgroup exists, and get number of entries */
  1183. int valid_ng(char *ng, long *maxart, long *minart, char *canpost, int exact)
  1184. {
  1185.     char ng_check[BUFLEN], ng_read[BUFLEN], *cp;
  1186.     FILE *fp;
  1187.     int found_ng;
  1188.  
  1189.     fp = xfopen(activefile, "r");
  1190.     while (fgets(ng_read, BUFLEN, fp) != NULL)
  1191.     {
  1192.         switch (sscanf(ng_read, "%s %ld %ld %c", ng_check, maxart, minart, canpost))
  1193.         {
  1194.         case 2:
  1195.             *minart = 1;
  1196.             /* fall through */
  1197.         case 3:
  1198.             *canpost = 'y';
  1199.             /* fall through */
  1200.         case 4:
  1201.             break;
  1202.  
  1203.         default:
  1204.             printf("Active file corrupt: %s", ng_read);
  1205.             byebye("Seek help!");
  1206.         }
  1207.             
  1208.         if (strcmp(ng_check, ng) == 0) {
  1209.             (void) fclose(fp);
  1210.             if (*canpost != 'n') {
  1211.                 return TRUE;
  1212.             } else
  1213.                 return FALSE;
  1214.         }
  1215.     }
  1216.     (void) fclose(fp);
  1217.     *maxart = 0;
  1218.     *minart = 0;
  1219.     *canpost = 'i';
  1220.     if (exact) {
  1221.         return FALSE;
  1222.     }
  1223.     if ((fp = fopen(bugfile, "r")) == NULL)
  1224.     {
  1225.         return FALSE;
  1226.     }
  1227.     found_ng = FALSE;
  1228.     while (!found_ng && fgets(ng_check, BUFLEN, fp) == ng_check) {
  1229.         if (ng_check[0] == '#')
  1230.             continue;
  1231.         cp = index(ng_check, '\n');
  1232.         *cp = '.';
  1233.         if (prefix(ng, ng_check))
  1234.             found_ng = TRUE;
  1235.     }
  1236.     (void) fclose(fp);
  1237.     if (!found_ng)
  1238.         return FALSE;
  1239.     *canpost = 'y';
  1240.     return TRUE;
  1241. }
  1242.  
  1243. /* get the line specified by field from an article */
  1244. int article_line(char *article, char *field, char *line)
  1245. {
  1246.     FILE *fp;
  1247.     char *c;
  1248.  
  1249.     fp = xfopen(article,"r");
  1250.     while ((c=fgets(line,BUFLEN,fp)) != NULL && !prefix(line, field))
  1251.         if (line[0] == '\n') {
  1252.             c = NULL;
  1253.             break;
  1254.         }
  1255.     (void) fclose(fp);
  1256.     if (c != NULL) {
  1257.         (void) nstrip(line);
  1258.         return TRUE;
  1259.     } else {
  1260.         line[0] = '\0';
  1261.         return FALSE;
  1262.     }
  1263. }
  1264.  
  1265. /* get the header information for a followup article */
  1266. void followup(char *baseart)
  1267. {
  1268.     char *p;
  1269.  
  1270.     /* subject */
  1271.     if (article_line(baseart, "Subject: ", buf))
  1272.     {
  1273.         p = buf+9;
  1274.         for ( ; ; )
  1275.         {
  1276.             while (*p == ' ' || *p == '\t')
  1277.                 ++p;
  1278.             if ((*p != 'r' && *p != 'R') ||
  1279.                 (p[1] != 'e' && p[1] != 'E') ||
  1280.                 (p[2] != ':' && p[2] != ' '))
  1281.                     break;
  1282.             p += 3;
  1283.         }
  1284.         (void) sprintf(subject, "Re: %s", p);
  1285.     }
  1286.     else
  1287.     {
  1288.         if (article_line(baseart, "From: ", buf))
  1289.             (void) sprintf(subject, "Re: orphan response from %s", buf);
  1290.         else
  1291.             (void) strcpy(subject, "Re: orphan response");
  1292.     }
  1293.  
  1294.     /* newsgroup */
  1295.     if (article_line(baseart, "Newsgroups: ", buf))
  1296.         (void) strcpy(newsgroups, buf+12);
  1297.     if (ngmatch(newsgroups, "misc.jobs.all,!misc.jobs.misc"))
  1298.     {
  1299.         printf("Your followup has been directed to misc.jobs.misc\n");
  1300.         printf("It is the proper place for followup discussions\n");
  1301.         (void) strcpy(newsgroups,"misc.jobs.misc");
  1302.     }
  1303.  
  1304.     /* distribution */
  1305.     if (article_line(baseart, "Distribution: ", buf))
  1306.         (void) strcpy(distribution, buf+14);
  1307.  
  1308.     /* references */
  1309.     if (article_line(baseart, "References: ", buf))
  1310.     {
  1311.         char *rcp;
  1312.         (void) strcpy(references, buf+12);
  1313.         (void) strcat(references, " ");
  1314.         /* keep the number of references to a reasonable number */
  1315.         rcp = rindex(references, ' '); /* Can not fail */
  1316.         while ((int)(rcp - references) > 70)
  1317.         {
  1318.             while (*--rcp != ' ')
  1319.               ;
  1320.             rcp[1] = '\0';
  1321.         }
  1322.     }
  1323.     if (article_line(baseart, "Message-ID: ", buf)) {
  1324.         (void) strcat(references, buf+12);
  1325.         (void) strcpy(msgid, buf+12);
  1326.     }
  1327.  
  1328.     if (article_line(baseart, "From: ", buf))
  1329.         (void) strcpy(isfrom, buf+6);
  1330.  
  1331.     if (article_line(baseart, "Keywords: ", buf))
  1332.         (void) strcpy(keywords, buf+10);
  1333.  
  1334.     if (article_line(baseart, "Followup-To: ", buf))
  1335.     {
  1336.         (void) strcpy(newsgroups, buf+13);
  1337.         if (strcmp(newsgroups, "poster") == 0)
  1338.             byebye("Mail followups directly to poster.");
  1339.     }
  1340.     get_summary();
  1341. }
  1342.  
  1343. void get_summary(void)
  1344. {
  1345.     char *p;
  1346.     int i;
  1347.  
  1348.     printf("Please enter a short summary of your contribution to the discussion\n");
  1349.     printf("Just one or two lines ...   (end with a blank line)\n");
  1350.     p = summary;
  1351.     for (i = 0; i < 3; i++) {    /* 3 * 80 < 256, should be safe .. */
  1352.         getpr(">\t", p);
  1353.         if (*p == '\0')
  1354.             break;
  1355.         p = index(p, '\0');
  1356.         (void) strcpy(p, "\n\t ");
  1357.         p += 3;
  1358.     }
  1359.     if (p > summary)
  1360.         p[-3] = '\0';
  1361. }
  1362.  
  1363. void encode(char *article)
  1364. {
  1365.     FILE *fpart, *fphead, *fpcoded;
  1366.     char *headerfile = "T:pheadXXXXXXXX";
  1367.     char *codedfile = "T:pcodeXXXXXXXX";
  1368.  
  1369.     MKTEMP(headerfile);
  1370.     MKTEMP(codedfile);
  1371.  
  1372.     fpart = xfopen(article, "r");
  1373.  
  1374.     /* place article header in "headerfile" file */
  1375.     fphead = xfopen(headerfile, "w");
  1376.     while (fgets(buf, BUFLEN, fpart) != NULL)
  1377.     {
  1378.         (void) fputs(buf, fphead);
  1379.         if (buf[0] == '\n')
  1380.             break;
  1381.     }
  1382.     (void) fclose(fphead);
  1383.  
  1384.     /* place article body in "codedfile" file */
  1385.     fpcoded = xfopen(codedfile, "w");
  1386.     while (fgets(buf, BUFLEN, fpart) != NULL)
  1387.         (void) fputs(buf, fpcoded);
  1388.     (void) fclose(fpcoded);
  1389.     (void) fclose(fpart);
  1390.  
  1391.     /* encode body and put back together with header */
  1392.     (void) rename(headerfile, article);
  1393.  
  1394.     (void) sprintf(buf,"%s <%s >>%s 13\n", "caesar", codedfile, article);
  1395.     printf("Encoding article -- please stand by\n");
  1396.     (void) fflush(stdout);
  1397. /*
  1398.     if (Execute(buf, NULL, NULL)) {
  1399.         printf("encoding failed");
  1400.         xxit(2);
  1401.     }
  1402. */
  1403.   Execute(buf, NULL, NULL);
  1404.     (void) UNLINK(codedfile);
  1405. }
  1406.  
  1407.  
  1408. /*
  1409.  * Print a recorded message warning the poor luser what he is doing
  1410.  * and demand that he understands it before proceeding.  Only do
  1411.  * this for newsgroups listed in LIBDIR/recording.
  1412.  */
  1413.  
  1414. int recording(char *ngrps)
  1415. {
  1416.     char recbuf[BUFLEN];
  1417.     FILE *fd;
  1418.     char nglist[BUFLEN], fname[BUFLEN];
  1419.     int  c, n, yes, retval = 0;
  1420.  
  1421.     (void) sprintf(recbuf, "%s/recording", newslibdir);
  1422.     fd = fopen(recbuf, "r");
  1423.     if (fd == NULL)
  1424.         return 0;
  1425.     while ((fgets(recbuf, sizeof recbuf, fd)) != NULL)
  1426.     {
  1427.         (void) sscanf(recbuf, "%s %s", nglist, fname);
  1428.         if (ngmatch(ngrps, nglist))
  1429.         {
  1430.             (void) fclose(fd);
  1431.             if (fname[0] == '/')
  1432.                 (void) strcpy(recbuf, fname);
  1433.             else
  1434.                 (void) sprintf(recbuf, "%s/%s", newslibdir, fname);
  1435.             fd = fopen(recbuf, "r");
  1436.             if (fd == NULL)
  1437.                 return 0;
  1438.             while ((c = getc(fd)) != EOF)
  1439.                 putc(c, stderr);
  1440.             fclose(fd);
  1441.             fprintf(stderr, "Do you understand this?  Hit <return> to proceed, <BREAK> to abort: ");
  1442.             fflush(stderr);
  1443.             n = read(0, recbuf, 100);
  1444.             c = recbuf[0];
  1445.             yes = (c=='y' || c=='Y' || c=='\n' || c=='\n' || c==0);
  1446.             if (n <= 0 || !yes)
  1447.                 retval = -1;
  1448.         }
  1449.     }
  1450.     return retval;
  1451. }
  1452.  
  1453. void xxit(int i)
  1454. {
  1455. #ifdef SERVER
  1456.     (void) UNLINK(original);
  1457.     (void) UNLINK(active_name());
  1458. #endif    /* SERVER */
  1459.     exit(i);
  1460.         chdir(curpath);
  1461. }
  1462.  
  1463.  
  1464. /************** funcs.c ***********/
  1465.  
  1466. /*
  1467.  * This software is Copyright 1986, 1989 by Rick Adams.
  1468.  *
  1469.  * Permission is hereby granted to copy, reproduce, redistribute or
  1470.  * otherwise use this software as long as: there is no monetary
  1471.  * profit gained specifically from the use or reproduction or this
  1472.  * software, it is not sold, rented, traded or otherwise marketed, and
  1473.  * this copyright notice is included prominently in any copy
  1474.  * made.
  1475.  *
  1476.  * The author make no claims as to the fitness or correctness of
  1477.  * this software for any use whatsoever, and it is provided as is. 
  1478.  * Any use of this software is at the user's own risk.
  1479.  *
  1480.  * funcs - functions used by many programs
  1481.  */
  1482.  
  1483.  
  1484. /*
  1485.  * News group matching.
  1486.  *
  1487.  * nglist is a list of newsgroups.
  1488.  * sublist is a list of subscriptions.
  1489.  * sublist may have "meta newsgroups" in it.
  1490.  * All fields are NGDELIM separated,
  1491.  * and there is an NGDELIM at the end of each argument.
  1492.  *
  1493.  * Currently implemented glitches:
  1494.  * sublist uses 'all' like shell uses '*', and '.' like shell '/'.
  1495.  * If subscription X matches Y, it also matches Y.anything.
  1496.  */
  1497.  
  1498. int ngmatch(char *nglist, char *sublist)
  1499. {
  1500.     char *n, *s;
  1501.     int rc;
  1502.  
  1503.     rc = FALSE;
  1504.     for (n = nglist; *n != '\0' && rc == FALSE;)
  1505.     {
  1506.         for (s = sublist; *s != '\0';)
  1507.         {
  1508.             if (*s != NEGCHAR)
  1509.                 rc = rc || ptrncmp(s, n);
  1510.             else
  1511.                 rc = rc && !ptrncmp(s+1, n);
  1512.             while (*s++ != NGDELIM && *s != '\0')
  1513.                 ;
  1514.         }
  1515.         while (*n++ != NGDELIM && *n != '\0')
  1516.             ;
  1517.     }
  1518.     return rc;
  1519. }
  1520.  
  1521. /*
  1522.  * Compare two newsgroups for equality.
  1523.  * The first one may be a "meta" newsgroup.
  1524.  */
  1525. int ptrncmp(char *ng1, char *ng2)
  1526. {
  1527.     while (*ng1 != NGDELIM && *ng1 != '\0')
  1528.     {
  1529.         if (ng1[0]=='a' && ng1[1]=='l' && ng1[2]=='l')
  1530.         {
  1531.             ng1 += 3;
  1532.             while (*ng2 != NGDELIM && *ng2 != '.' && *ng2 != '\0')
  1533.                 if (ptrncmp(ng1, ng2++))
  1534.                     return(TRUE);
  1535.             return ptrncmp(ng1, ng2);
  1536.         } else if (*ng1++ != *ng2++)
  1537.             return FALSE;
  1538.     }
  1539.     return *ng2 == '.' || *ng2 == NGDELIM || *ng2 == '\0';
  1540. }
  1541.  
  1542.  
  1543. /*
  1544.  * Strip trailing newlines, blanks, and tabs from 's'.
  1545.  * Return TRUE if newline was found, else FALSE.
  1546.  */
  1547. int nstrip(char *s)
  1548. {
  1549.     char *p;
  1550.     int rc;
  1551.  
  1552.     rc = FALSE;
  1553.     p = s;
  1554.     while (*p)
  1555.         if (*p++ == '\n')
  1556.             rc = TRUE;
  1557.     while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t'));
  1558.     *++p = '\0';
  1559.     return rc;
  1560. }
  1561.  
  1562. /*
  1563.  * Local open routine.
  1564.  */
  1565. FILE *xfopen(name, fmode)
  1566. char *name, *fmode;
  1567. {
  1568.     FILE *fp;
  1569.  
  1570.     if ((fp = fopen(name, fmode)) == NULL) {
  1571.         xerror("Cannot open %s (%s)", name, fmode, 0);
  1572.     }
  1573.     return fp;
  1574. }
  1575.  
  1576.  
  1577. /* From UC Berkeley @(#)strcasecmp.c    1.3 (Berkeley) 8/3/87 */
  1578.  
  1579. /*
  1580.  * This array is designed for mapping upper and lower case letter
  1581.  * together for a case independent comparison.  The mappings are
  1582.  * based upon ascii character sequences.
  1583.  */
  1584.  
  1585. char charmap[] =
  1586. {
  1587.     '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  1588.     '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  1589.     '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  1590.     '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  1591.     '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  1592.     '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  1593.     '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  1594.     '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  1595.     '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  1596.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  1597.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  1598.     '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  1599.     '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  1600.     '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  1601.     '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  1602.     '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  1603.     '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  1604.     '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  1605.     '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  1606.     '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  1607.     '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  1608.     '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  1609.     '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  1610.     '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  1611.     '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  1612.     '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  1613.     '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  1614.     '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
  1615.     '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  1616.     '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  1617.     '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  1618.     '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  1619. };
  1620.  
  1621. int prefix(char *full, char *pref)
  1622. {
  1623.     char *cm = charmap;
  1624.  
  1625.     while (*pref != '\0') {
  1626.         if (cm[*full++] != cm[*pref++])
  1627.             return FALSE;
  1628.     }
  1629.     return TRUE;
  1630. }
  1631.  
  1632.  
  1633. /*
  1634.  * Return TRUE iff ngname is a valid newsgroup name
  1635.  */
  1636. int validng(char *ngname)
  1637. {
  1638.     FILE *fp;
  1639.     char *p, *q;
  1640.     char abuf[BUFLEN];
  1641.  
  1642.     fp = xfopen(activefile, "r");
  1643.     while(fgets(abuf, BUFLEN, fp) != NULL)
  1644.     {
  1645.         p = abuf;
  1646.         q = ngname;
  1647.         while (*p++ == *q++)
  1648.             ;
  1649.         if (*--q == '\0' && *--p == ' ')
  1650.         {
  1651.             (void) fclose(fp);
  1652.             return TRUE;
  1653.         }
  1654.     }
  1655.     (void) fclose(fp);
  1656.     return FALSE;
  1657. }
  1658.