home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / rn_4_3_blars.lzh / Pnews.c < prev    next >
C/C++ Source or Header  |  1991-12-21  |  17KB  |  625 lines

  1. /* Pnews.c created from Pnews.SH by blarson@usc.edu */
  2. /* warning: this has some OSK and C-news specific code in it */
  3.  
  4. /*
  5. syntax: Pnews -h headerfile            or
  6.     Pnews -h headerfile oldarticle        or
  7.     Pnews newsgroup title            or just
  8.     Pnews
  9.     Pnews -h headerfile -s
  10. */
  11.  
  12. #include "EXTERN.H"
  13. #include "common.h"
  14. #include <stdio.h>
  15. #include <modes.h>
  16. #include <varargs.h>
  17. #include <signal.h>
  18. #include <setjmp.h>
  19. #include <errno.h>
  20. #include <time.h>
  21. #include <pwd.h>
  22.  
  23. char *getenv();
  24. char *malloc();
  25. char *index();
  26. char *strtok();
  27. FILE *popen();
  28.  
  29. static jmp_buf jmpbuf;
  30.  
  31. char WHITE[] = " \t\n";
  32.  
  33. char *strsave(str)
  34. char *str;
  35. {
  36.     register char *cp;
  37.  
  38.     cp = malloc(strlen(str) + 1);
  39.     if(cp == NULL) {
  40.         fprintf(stderr, "Malloc failed\n");
  41.     exit(errno);
  42.     }
  43.     strcpy(cp, str);
  44.     return cp;
  45. }
  46.  
  47. char *buildstring(va_alist)
  48. va_dcl
  49. {
  50.     register int length = 1;
  51.     register char *cp, *rp;
  52.     va_list va;
  53.  
  54.     va_start(va);
  55.     while((cp = va_arg(va, char *)) != NULL)
  56.     length += strlen(cp);
  57.     va_end(va);
  58.  
  59.     if((rp = malloc(length)) == NULL) {
  60.         fprintf(stderr, "Malloc failed\n");
  61.     exit(errno);
  62.     }
  63.     *rp = '\0';
  64.  
  65.     va_start(va);
  66.     while((cp = va_arg(va, char *)) != NULL) {
  67.         strcat(rp, cp);
  68.     }
  69.     va_end(va);
  70.  
  71.     return rp;
  72. }
  73.  
  74. int strpfx(s, p)
  75. register char *s, *p;
  76. {
  77.     return strncmp(s, p, strlen(p)) == 0;
  78. }
  79.  
  80. sigrescue() {
  81.     longjmp(jmpbuf, 1);
  82. }
  83.  
  84. main(argc, argv)
  85. int argc;
  86. char **argv;
  87. {
  88.     register char *cp;
  89.     register FILE *temp, *fp;
  90.     char *dotdir, *tmpart, *headerfile, *oldart;
  91.     int expert, f, count, artnum;
  92.     char buf[1024];
  93.     enum {ask, edit, send, cleanup, rescue} state;
  94.     char *ng, *dist, *subject, *logname, *orgname, *editor;
  95.     int sendit = 0;
  96.     struct passwd *pw;
  97.  
  98.     dotdir = getenv("DOTDIR");
  99.     if(dotdir == NULL) dotdir = getenv("HOME");
  100.     if(dotdir == NULL) dotdir = getenv("LOGDIR");
  101.     tmpart = buildstring(dotdir, "/.article", (char *)NULL);
  102.     if ((pw = getpwuid(getuid())) != NULL) {
  103.         logname = pw->pw_name;
  104.     } else {
  105.         logname = getenv("USER");
  106.         if(logname == NULL) logname = "";
  107.     }
  108.  
  109.  
  110.     cp = buildstring(dotdir, "/.pnewsexpert", (char *)NULL);
  111.     if((f = create(cp, 0, S_IREAD | S_IWRITE)) < 0) {
  112.         expert = (errno == E_CEF);
  113.     } else {
  114.         expert = 0;
  115.     close(f);
  116.     }
  117.     free(cp);
  118.     if(!expert) {
  119.     printf("\
  120. I see you've never used this version of Pnews before.  I will give you extra\n\
  121. help this first time through, but then you must remember what you learned.\n\
  122. If you don't understand any question, type h and a CR (carriage return) for\n\
  123. help.\n\n");
  124.     printf("\
  125. If you've never posted an article to the net before, it is HIGHLY recommended\n\
  126. that you read the netiquette document found in news.announce.newusers so\n\
  127. that you'll know to avoid the commonest blunders.  To do that, interrupt\n\
  128. Pnews, and get to the top-level prompt of rn.  Type \"g news.announce.newusers\"\n\
  129. and you are on your way.\n\n");
  130.     }
  131.  
  132.     headerfile="";
  133.     oldart = "";
  134.     if(argc > 1) {
  135.         if(strcmp(argv[1], "-h") == 0) {
  136.         headerfile = argv[2];
  137.         argc -= 2;
  138.         argv += 2;
  139.         if(argc > 1 && strcmp(argv[1], "-s") == 0) {
  140.             sendit = 1;
  141.         argc--;
  142.         argv++;
  143.         }
  144.         if(argc > 1) {
  145.             oldart = argv[1];
  146.         argc--;
  147.         argv++;
  148.         }
  149.     }
  150.     }
  151.  
  152.     if((temp = fopen(tmpart, "w")) == NULL) {
  153.         fprintf(stderr, "Could not open '%s' error %d\n", tmpart, errno);
  154.     exit(errno);
  155.     }
  156.     if(*headerfile == '\0') {
  157.     if(argc <= 1) {
  158.         for(;;) {
  159.         printf("\nNewsgroup(s): ");
  160.             fflush(stdout);
  161.         fgets(buf, sizeof buf, stdin);
  162.         if(strcmp(buf, "h\n") != 0) break;
  163.         printf("\n\n\
  164. Type the name of one or more newsgroups to which you wish to post an article.\n\
  165. If you want to post to multiple newsgroups, it is better to do them all at\n\
  166. once than to post to each newsgroup individually, which defeats the news\n\
  167. reading programs' strategies of eliminating duplicates.\n\
  168. \n\
  169. Separate multiple newsgroup names with commas.\n");
  170.         }
  171.         ng = strsave(buf);
  172.     } else {
  173.         ng = buildstring(argv[1], "\n", (char *)NULL);
  174.         argc--;
  175.         argv++;
  176.     }
  177.     for(;;) {
  178.         cp = buildstring(LIB, "/distributions", (char *)NULL);
  179.         if((fp = fopen(cp, "r")) != NULL) {
  180.             printf("\n\Your local distribution prefixes are:\n");
  181.         while((count = fread(buf, 1, sizeof buf, fp)) > 0) {
  182.             fwrite(buf, 1, count, stdout);
  183.         }
  184.         printf("\n");
  185.         fclose(fp);
  186.         } else {
  187.             printf("\n\n\
  188. Your local distribution prefixes are:\n\
  189.     Local organization:    %s\n\
  190.     Organization:    %s\n\
  191.     City:        %s\n\
  192.     State:          %s\n\
  193.     Country:        %s\n\
  194.     Continent:        %s\n\
  195.     Everywhere:        %s\n\
  196. \n", LOC, ORG, CITY, STATE, CNTRY, CONT, WORLD);
  197.         }
  198.         free(cp);
  199.         if(strpfx(ng, LOC)) cp = LOC;
  200.         else if(strpfx(ng, ORG)) cp = ORG;
  201.         else if(strpfx(ng, CITY)) cp = CITY;
  202.         else if(strpfx(ng, STATE)) cp = STATE;
  203.         else if(strpfx(ng, CNTRY)) cp = CNTRY;
  204.         else if(strpfx(ng, CONT)) cp = CONT;
  205.         else cp = WORLD;
  206.         printf("Distribution [%s]: ", cp);
  207.         fgets(buf, sizeof buf, stdin);
  208.         if(strcmp(buf, "h\n") != 0) break;
  209.         printf("\n\n\
  210. The Distribution line may be used to limit the distribution of an article\n\
  211. to some subset of the systems that would receive the article based only on\n\
  212. the Newsgroups line.  For example, if you want to sell your car in talk.auto,\n\
  213. and you live in New Jersey, you might want to put \"nj\" on the Distribution\n\
  214. line to avoid advertising in California, which has enough problems of its own.\n\
  215. The actual area designators to use depend on where you are, of course.\n");
  216.     }
  217.     if(buf[0] == '\n') dist = buildstring(cp, "\n", (char *)NULL);
  218.     else dist = strsave(buf);
  219.  
  220.     if(argc <= 1) {
  221.         for(;;) {
  222.             printf("\n\Subject: ");
  223.         fflush(stdout);
  224.         fgets(buf, sizeof buf, stdin);
  225.         if(strcmp(buf, "h\n") != 0) break;
  226.         printf("\n\
  227. Type the title for your article.  Please make it as informative as possible\n\
  228. (within reason) so that people who aren't interested won't have to read the\n\
  229. article to find out they aren't interested.  This includes marking movie\n\
  230. spoilers as (spoiler), and rotated jokes as (rot 13).\n");
  231.         }
  232.         subject = strsave(buf);
  233.     } else {
  234.         subject = buildstring(argv[1], "\n", (char *)NULL);
  235.     }
  236.  
  237. /*  now build a file with a header for them to edit */
  238.  
  239.     orgname = getenv("ORGANIZATION");
  240.     if(orgname == NULL) orgname = ORGNAME;
  241.     
  242.     if (pw != NULL) {
  243.         fprintf(temp, "From: %s@%s (%s)\n", logname, SITENAME, pw->pw_gecos);
  244.     } else {
  245.         fprintf(temp, "From: %s@%s\n", logname, SITENAME);
  246.     }
  247.     fprintf(temp, "\
  248. Newsgroups: %s\
  249. Subject: %s\
  250. Distribution: %s\
  251. Organization: %s\n\
  252. Keywords: \n\
  253. ", ng, subject, dist, orgname);
  254.     free(ng);
  255.     free(subject);
  256.     free(dist);
  257.     } else {
  258.         if(strcmp(headerfile, "-") == 0) fp = stdin;
  259.     else fp = fopen(headerfile, "r");
  260.     if(fp == NULL) {
  261.         fprintf(stderr, "Could not open '%s' error %d!\n", headerfile, errno);
  262.     } else {
  263.         while((count = fread(buf, 1, sizeof buf, fp)) > 0) {
  264.             fwrite(buf, 1, count, temp);
  265.         }
  266.         if(fp != stdin) fclose(fp);
  267.     }
  268.     }
  269.     fprintf(temp, "\n");
  270.  
  271.     if(setjmp(jmpbuf)) goto rescuer;
  272.     signal(SIGINT, sigrescue);
  273.     signal(SIGHUP, sigrescue);
  274.  
  275.     if(!sendit) for(;;) {
  276.         printf("\nPrepared file to include [none]: ");
  277.     fflush(stdout);
  278.     fgets(buf, sizeof buf, stdin);
  279.     if(strcmp(buf, "h\n") != 0) break;
  280.     printf("\n\n\
  281. If you have already produced the body of your article, type the filename\n\
  282. for it here.  If you just want to proceed directly to the editor, type a\n\
  283. RETURN.  In any event, you will be allowed to edit as many times as you\n\
  284. want before you send off the article.\n");
  285.     }
  286.     if(sendit) {
  287.         state = send;
  288.     } else {
  289.         if(buf[0] == '\n') {
  290.             state = edit;
  291.         } else {
  292.             buf[strlen(buf) - 1] = '\0';
  293.         if((fp = fopen(buf, "r")) == NULL) {
  294.             fprintf(stderr, "Could not open '%s' error %d!!\n", buf, errno);
  295.         } else {
  296.             while((count = fread(buf, 1, sizeof buf, fp)) > 0) {
  297.                 fwrite(buf, 1, count, temp);
  298.             }
  299.             fclose(fp);
  300.         }
  301.         state = ask;
  302.         }
  303.     }
  304.     fclose(temp);
  305.  
  306.     if((editor = getenv("VISUAL")) == NULL &&
  307.             (editor = getenv("EDITOR")) == NULL) editor = DEFEDITOR;
  308.     for(;;) {
  309.         switch(state) {
  310.  
  311.     case edit:
  312.     if(!expert) {
  313.         printf("\n\
  314. A temporary file has been created for you to edit.  Be sure to leave at\n\
  315. least one blank line between the header and the body of your message.\n\
  316. (And until a certain bug is fixed all over the net, don't start the body of\n\
  317. your message with any indentation, or it may get eaten.)\n");
  318.         printf("\n\
  319. Within the header may be fields that you don't understand.  If you don't\n\
  320. understand a field (or even if you do), you can simply leave it blank, and\n\
  321. it will go away when the article is posted.\n\
  322. \n\
  323. Type return to get the default editor, or type the name of your favorite\n\
  324. editor.\n\n");
  325.         for(;;) {
  326.         printf("Editor [%s]: ", editor);
  327.         fflush(stdout);
  328.         fgets(buf, sizeof buf, stdin);
  329.         if(strcmp(buf, "h\n") != 0) break;
  330.         printf("\n\
  331. Type a return to get the default editor, or type the name of the editor you\n\
  332. prefer.  The default editor depends on the VISUAL and EDITOR environment\n\
  333. variables.\n\n");
  334.         }
  335.     }
  336.     cp = buildstring(editor, " ", oldart, " ", tmpart, (char *)NULL);
  337.     system(cp);
  338.     free(cp);
  339.     state = ask;
  340.  
  341.     /* fallthrough */
  342.     
  343.     case ask:
  344.         printf("\n\Send, abort, edit, or list? ");
  345.         fflush(stdout);
  346.         fgets(buf, sizeof buf, stdin);
  347.         switch(buf[0]) {
  348.         case 'a': case 'A':
  349.         state = rescue;
  350.         break;
  351.         case 'e': case 'E':
  352.             strtok(buf, WHITE);
  353.             if((cp = strtok((char *)NULL, WHITE)) != NULL && *cp!='\0') {
  354.             editor = strsave(cp);
  355.         }
  356.         state = edit;
  357.             break;
  358.         case 'l': case 'L':
  359.         cp = buildstring(PAGER, " ", tmpart, (char *)NULL);
  360.         system(cp);
  361.         free(cp);
  362.         state = ask;
  363.         break;
  364.         case 's': case 'S':
  365.         state = send;
  366.         break;
  367.         case 'h': case 'H':
  368.         printf("\n\
  369. Type s to send the article, a to abort and append the article to dead.article,\n\
  370. e to edit the article again, or l to list the article.\n\
  371. \n\
  372. To invoke an alternate editor, type 'e editor'.\n\n");
  373.         break;
  374.         }
  375.         break;
  376.  
  377.     case send:
  378.         state = rescue;
  379.         if((temp = fopen(tmpart, "r")) != NULL) {
  380.             ng = NULL;
  381.         while(fgets(buf, sizeof buf, temp) != NULL) {
  382.             if(buf[0] == '\n') break;
  383.             if(strpfx(buf, "Newsgroups:")) {
  384.                 strtok(buf, WHITE);
  385.                 ng = strsave(strtok((char *)NULL, WHITE));
  386.             break;
  387.             }
  388.         }
  389.         if(ng != NULL && *ng != '\0') {
  390.             cp = buildstring(LIB, "/active", (char *)NULL);
  391.             if((fp = fopen(cp, "r")) != NULL) {
  392.                 int count, ngmax;
  393.             char **ngl;
  394.             char *modgroup = NULL;
  395.  
  396.                 free(cp);
  397.                 ngmax = 16;
  398.             if((ngl = (char **) malloc(ngmax * sizeof(char *))) == NULL) {
  399.                 fprintf(stderr, "Malloc failed\n");
  400.                 goto rescuer;
  401.             }
  402.             ngl[count = 0] = strtok(ng, ",");
  403.             while(ngl[count] != NULL) {
  404.                 if(count++ > ngmax) {
  405.                     if((ngl = (char **) realloc(ngl, (ngmax += 8) * (sizeof (char **)))) == NULL) {
  406.                     fprintf(stderr, "Malloc failed\n");
  407.                     goto rescuer;
  408.                 }
  409.                 }
  410.                 ngl[count] = strtok((char *)NULL, ",");
  411.             }
  412.             while(count && fgets(buf, sizeof buf, fp) != NULL) {
  413.                 cp = strtok(buf, WHITE);
  414.                 if(cp != NULL) {
  415.                     int i;
  416.  
  417.                 for(i = 0; i < count; i++) {
  418.                     if(strcmp(ngl[i], cp) == 0) {
  419.                         strtok((char *)NULL, WHITE); /* max */
  420.                     strtok((char *)NULL, WHITE); /* min */
  421.                     cp = strtok((char *)NULL, WHITE);
  422.                     if(cp != NULL && *cp == 'm') {
  423.                         modgroup = ngl[i];
  424.                     }
  425.                     if(i < --count) {
  426.                         ngl[i] = ngl[count];
  427.                     }
  428.                         break;
  429.                     }
  430.                 }
  431.                 }
  432.             }
  433.             free(ngl);
  434.             fclose(fp);
  435.             if(modgroup != NULL) {
  436.                 char *modaddr = NULL;
  437.  
  438.                 printf("%s is a moderated group, mailing to moderator\n", modgroup);
  439.                 cp = buildstring(LIB, "/moderators", (char *)NULL);
  440.                 if((fp = fopen(cp, "r")) != NULL) {
  441.                 while(fgets(buf, sizeof buf, fp) != NULL) {
  442.                     if(strcmp(strtok(buf, WHITE), modgroup) == 0) {
  443.                     modaddr = strsave(strtok((char *)NULL, WHITE));
  444.                     break;
  445.                     }
  446.                 }
  447.                 fclose(fp);
  448.                 }
  449.                 free(cp);
  450.                 if(modaddr == NULL) {
  451.                     cp = modgroup;
  452.                     while((cp = index(cp, '.')) != NULL) {
  453.                     *cp++ = '-';
  454.                 }
  455.                 modaddr = buildstring(modgroup, "@", MODFORWARD, (char *)NULL);
  456.                 }
  457.                 if((fp = popen("mail -h", "w")) != NULL) {
  458.                     fprintf(fp, "To: %s\n", modaddr);
  459.                 fseek(temp, 0, 0);
  460.                 while((count = fread(buf, 1, sizeof buf, temp)) > 0) {
  461.                     fwrite(buf, 1, count, fp);
  462.                 }
  463.                 fclose(temp);
  464.                 free(cp);
  465.                 cp = buildstring(dotdir, "/.signature", (char *)NULL);
  466.                 if((temp = fopen(cp, "r")) != NULL) {
  467.                     fprintf(fp, "\n-- \n");
  468.                     while((count = fread(buf, 1, sizeof buf, temp)) > 0) {
  469.                         fwrite(buf, 1, count, fp);
  470.                     }
  471.                     fclose(temp);
  472.                 }
  473.                     pclose(fp);
  474.                 }
  475.                 free(cp);
  476.                 free(modaddr);
  477.             } else {
  478.                 fseek(temp, 0, 0);
  479.                 cp = buildstring(LIB, "/artnum", (char *)NULL);
  480.                 if((fp = fopen(cp, "r+")) != NULL) {
  481.                     fgets(buf, sizeof buf, fp);
  482.                 artnum = atoi(buf) + 1;
  483.                 fseek(fp, 0, 0);
  484.                 fprintf(fp, "%d\n", artnum);
  485.                 fclose(fp);
  486.                 free(cp);
  487.                 sprintf(buf, "%d", artnum);
  488.                 cp = buildstring(INCOMING, "/0local", buf, (char *)NULL);
  489.                 if((fp = fopen(cp, "w")) != NULL) {
  490.                     int skipping;
  491.                     char *from = NULL;
  492.                     time_t *now;
  493.  
  494.                     free(cp);
  495.                     state = cleanup;
  496.                     time(&now);
  497.                     cp = asctime(gmtime(&now));
  498.                     fprintf(fp, "\
  499. Path: %s\n\
  500. Message-ID: <%d@%s>\n\
  501. Date: %.3s, %.2s %.3s %.4s %.8s GMT\n\
  502. ", logname, artnum, SITENAME, cp, cp+8, cp+4, cp+20, cp+11);
  503.                     while(fgets(buf, sizeof buf, temp) != NULL) {
  504.                         if((count = strspn(buf, WHITE)) != 0) {
  505.                         if(count == strlen(buf)) break;
  506.                         if(!skipping) fputs(buf, fp);
  507.                         continue;
  508.                     }
  509.                     if(strpfx(buf, "Path:") ||
  510.                         strpfx(buf, "Message-ID:") ||
  511.                         strpfx(buf, "Sender:") ||
  512.                         strpfx(buf, "Date:")) {
  513.                         skipping = 1;
  514.                         continue;
  515.                     }
  516.                     cp = index(buf, ':');
  517.                     if(cp == NULL) {
  518.                         printf("Malformed header line ignored: %s",
  519.                                 buf);
  520.                         skipping = 1;
  521.                         continue;
  522.                     }
  523.                     cp++;
  524.                     if(strspn(cp, WHITE) == strlen(cp)) {
  525.                         skipping = 1;
  526.                         continue;
  527.                     }
  528.                     if(strpfx(buf, "From:"))
  529.                         from = strsave(cp + strspn(cp,
  530.                                 WHITE));
  531.                     skipping = 0;
  532.                     fputs(buf, fp);
  533.                     }
  534.                     if(from != NULL) {
  535.                         cp = buildstring(logname, "@", SITENAME, "\n", (char *)NULL);
  536.                         if(strcmp(from, cp) != 0)
  537.                             fprintf(fp, "Sender: %s\n", cp);
  538.                     free(cp);
  539.                     } else {
  540.                         fprintf(fp, "From: %s@%s\n",
  541.                         logname, SITENAME);
  542.                     }
  543.                     fputs("\n", fp);
  544.                     while((count = fread(buf, 1, sizeof buf, temp)) > 0) {
  545.                         fwrite(buf, 1, count, fp);
  546.                     }
  547.                     fclose(temp);
  548.                     cp = buildstring(dotdir, "/.signature", (char *)NULL);
  549.                     if((temp = fopen(cp, "r")) != NULL) {
  550.                         fprintf(fp, "\n-- \n");
  551.                         while((count = fread(buf, 1, sizeof buf, temp)) > 0) {
  552.                             fwrite(buf, 1, count, fp);
  553.                         }
  554.                         fclose(temp);
  555.                     }
  556.                 } else {
  557.                     fclose(temp);
  558.                     printf("Could not open '%s' error %d!!!\n",
  559.                             cp, errno);
  560.                     state = rescue;
  561.                 }
  562.                 } else {
  563.                     fclose(temp);
  564.                     printf("Could not open '%s' error %d!!!!\n",
  565.                     cp, errno);
  566.                 state = rescue;
  567.                 }
  568.                 free(cp);
  569.             }
  570.             } else {
  571.                 printf("Could not open '%s' error %d!!!!!\n", cp, errno);
  572.             free(cp);
  573.             fclose(temp);
  574.             state = rescue;
  575.             }
  576.         } else {
  577.             printf("\nMalformed Newsgroups line.\n\n");
  578.             fclose(temp);
  579.             sleep(1);
  580.             state = edit;
  581.         }
  582.         } else {
  583.             fprintf(stderr, "Could not open '%s' error %d!!!!!!\n",
  584.             tmpart, errno);
  585.         state = rescue;
  586.         }
  587.         break;
  588.  
  589.     case rescue:
  590. rescuer:
  591.         if((temp = fopen(tmpart, "r")) != NULL) {
  592.             cp = buildstring(dotdir, "/dead.article", (char *)NULL);
  593.             if((fp = fopen(cp, "a")) != NULL) {
  594.             while((count = fread(buf, 1, sizeof buf, temp)) > 0) {
  595.                 fwrite(buf, 1, count, fp);
  596.             }
  597.             fclose(fp);
  598.             printf("\
  599. Article appended to %s\n\
  600. A copy may be temporarily found in %s\n", cp, tmpart);
  601.         }
  602.         free(cp);
  603.         fclose(temp);
  604.         }
  605.         exit(0);
  606.  
  607.     case cleanup:
  608.         if((cp = getenv("AUTHORCOPY")) != NULL) {
  609.         if((fp = fopen(cp, "a")) != NULL) {
  610.             if((temp = fopen(tmpart, "r")) != NULL) {
  611.                 while((count = fread(buf, 1, sizeof buf, temp)) > 0) {
  612.                 fwrite(buf, 1, count, fp);
  613.             }
  614.             fclose(temp);
  615.             fprintf(fp, "\n\n");
  616.             printf("Article appended to %s\n", cp);
  617.             }
  618.             fclose(fp);
  619.         }
  620.         }
  621.         exit(0);
  622.     }
  623.     }
  624. }
  625.