home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / trn_12.zip / src / respond.c < prev    next >
C/C++ Source or Header  |  1993-12-04  |  26KB  |  973 lines

  1. /* $Id: respond.c,v 4.4.3.1 1992/02/01 03:09:32 sob PATCH_3 sob $
  2.  *
  3.  * $Log: respond.c,v $
  4.  * Revision 4.4.3.1  1992/02/01  03:09:32  sob
  5.  * Release 4.4 Patchlevel 3
  6.  *
  7.  * Revision 4.4.2.1  1991/12/01  18:05:42  sob
  8.  * Patchlevel 2 changes
  9.  *
  10.  * Revision 4.4.1.1  1991/09/25  19:38:08  sob
  11.  * Some adaptions for CNEWS
  12.  *
  13.  * Revision 4.4  1991/09/09  20:27:37  sob
  14.  * release 4.4
  15.  *
  16.  *
  17.  * 
  18.  */
  19. /* This software is Copyright 1991 by Stan Barber. 
  20.  *
  21.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  22.  * use this software as long as: there is no monetary profit gained
  23.  * specifically from the use or reproduction or this software, it is not
  24.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  25.  * included prominently in any copy made. 
  26.  *
  27.  * The author make no claims as to the fitness or correctness of this software
  28.  * for any use whatsoever, and it is provided as is. Any use of this software
  29.  * is at the user's own risk. 
  30.  */
  31.  
  32. #include "EXTERN.h"
  33. #include "common.h"
  34. #include "intrp.h"
  35. #include "head.h"
  36. #include "term.h"
  37. #include "ng.h"
  38. #include "util.h"
  39. #include "rn.h"
  40. #include "artio.h"
  41. #include "final.h"
  42. #include "bits.h"
  43. #include "decode.h"
  44. #include "INTERN.h"
  45. #include "respond.h"
  46.  
  47. static char nullart[] = "\nNull article\n";
  48.  
  49. /*** OS2: we need the variable 'moderated' which is
  50.           defined and initialized in ngdata.c ***/
  51. extern char *moderated;
  52.  
  53. bool cut_line();
  54.  
  55. void
  56. respond_init()
  57. {
  58.     ;
  59. }
  60.  
  61. int
  62. save_article()
  63. {
  64.     bool_int use_pref;
  65.     register char *s, *c;
  66.     char altbuf[CBUFLEN];
  67.     int counter; /** OS2-patch **/
  68.     int iter;
  69.     bool interactive = (buf[1] == FINISHCMD);
  70.     char cmd = *buf;
  71.     
  72.     if (!finish_command(interactive))    /* get rest of command */
  73.     return SAVE_ABORT;
  74.     change_bsl2sl(buf);
  75.     if ((use_pref = isupper(cmd)) != 0)
  76.     cmd = tolower(cmd);
  77. #ifdef ASYNC_PARSE
  78.     parse_maybe(art);
  79. #endif
  80.     savefrom = (cmd == 'w' || cmd == 'e' ? htype[PAST_HEADER].ht_minpos : 0);
  81.     if (artopen(art) == Nullfp) {
  82. #ifdef VERBOSE
  83.     IF(verbose) {
  84.         fputs("\n\
  85. Saving null articles is not very productive!  :-)\n\
  86. ",stdout) ; FLUSH;
  87.     }
  88.     ELSE
  89. #endif
  90. #ifdef TERSE
  91.         fputs(nullart,stdout) ; FLUSH;
  92. #endif
  93.     return SAVE_DONE;
  94.     }
  95.     if (chdir(cwd)) {
  96.     printf(nocd,cwd) ; FLUSH;
  97.     sig_catcher(0);
  98.     }
  99.     if (cmd == 'e') {        /* is this an extract command? */
  100.     static bool custom_extract = FALSE;
  101.     int cnt = 0;
  102.     bool found_cut = FALSE;
  103.     char art_buf[LBUFLEN], *cmdstr;
  104.  
  105.     s = buf+1;        /* skip e */
  106.     while (*s == ' ') s++;    /* skip leading spaces */
  107.     safecpy(altbuf,filexp(s),sizeof altbuf);
  108.     s = altbuf;
  109.     if (*s) {
  110.         cmdstr = cpytill(buf,s,'|');    /* check for | */
  111.         s = buf + strlen(buf)-1;
  112.         while (*s == ' ') s--;        /* trim trailing spaces */
  113.         *++s = '\0';
  114.         if (*cmdstr) {
  115.         s = cmdstr+1;            /* skip | */
  116.         while (*s == ' ') s++;
  117.         if (*s)    {            /* if new command, use it */
  118.             if (extractprog)
  119.             free(extractprog);
  120.             extractprog = savestr(s);    /* put extracter in %e */
  121.         }
  122.         else
  123.             cmdstr = extractprog;
  124.         }
  125.         else
  126.         cmdstr = Nullch;
  127.         s = buf;
  128.     }
  129.     else {
  130.         if (extractdest)
  131.         strcpy(s, extractdest);
  132.         if (custom_extract)
  133.         cmdstr = extractprog;
  134.         else
  135.         cmdstr = Nullch;
  136.     }
  137.     if (cmdstr) {
  138.         if (strEQ(extractprog,"-"))
  139.         cmdstr = Nullch;
  140.         else if (decode_fp != Nullfp)
  141.         decode_end();
  142.     }
  143.     custom_extract = (cmdstr != 0);
  144.  
  145.     fseek(artfp,savefrom,0);
  146.  
  147. /*** OS2: it is not so easy to determine if the filename
  148.           is fully qualified under OS/2 than under Unix ***/
  149.  
  150.     if ((*s != '/') && (*(s+2) != '/') &&
  151.         (*s != '\\') && (*(s+2) != '\\')) {        /* relative path? */
  152.         c = (s==buf ? altbuf : buf);
  153.         interp(c, (sizeof buf), getval("SAVEDIR",SAVEDIR));
  154.         if (makedir(c,MD_DIR))    /* ensure directory exists */
  155.         strcpy(c,cwd);
  156.         if (*s) {
  157.         while (*c) c++;
  158.         *c++ = '/';
  159.         strcpy(c,s);        /* add filename */
  160.         }
  161.         s = (s==buf ? altbuf : buf);
  162.     }
  163.  
  164. /*** OS2: it is not so easy to determine if the filename
  165.           is fully qualified under OS/2 than under Unix ***/
  166.  
  167.     if ((*s != '/') && (*(s+2) != '/') &&
  168.         (*s != '\\') && (*(s+2) != '\\')) {        /* path still relative? */
  169.         c = (s==buf ? altbuf : buf);
  170.         sprintf(c, "%s/%s", cwd, s);
  171.         s = c;            /* absolutize it */
  172.     }
  173.     if (decode_fp != Nullfp) {
  174.         printf("Continuing %s:%s\n", decode_fname,
  175.         cmd != '\0' && strNE(extractdest,s) ?
  176.          " (Ignoring conflicting directory)" : nullstr ) ; FLUSH;
  177.         fflush(stdout);
  178.         if (decode_type == UUDECODE)
  179.         uudecode(artfp);
  180.         else
  181.         unship(artfp);
  182.     }
  183.     else {
  184.         if (extractdest)
  185.         free(extractdest);
  186.         s = extractdest = savestr(s); /* make it handy for %E */
  187.         change_bsl2sl(extractdest);
  188.         if (makedir(s, MD_DIR)) {    /* ensure directory exists */
  189.         int_count++;
  190.         return SAVE_DONE;
  191.         }
  192.         if (chdir(s)) {
  193.         printf(nocd,s) ; FLUSH;
  194.         sig_catcher(0);
  195.         }
  196.         _getcwd2(buf, 512);        /* simplify path for output */
  197.         s = buf;
  198.         while(fgets(art_buf,LBUFLEN,artfp) != Nullch) {
  199.  
  200. /*** OS2: AAAAAAAAHHHHHHHHHHHH, ..... another problem with \r (^M)... **/
  201.  
  202.         for (counter = 0; counter <= strlen(art_buf); counter++)
  203.             if ((art_buf[counter] == '\r') &&
  204.                 (art_buf[counter+1] == '\n')) {
  205.                 for (; art_buf[counter] != '\0'; counter++)
  206.                     art_buf[counter] = art_buf[counter+1];
  207.             }
  208.  
  209.         if (*art_buf <= ' ')
  210.             continue;    /* Ignore empty or initially-whitespace lines */
  211.         if (found_cut && custom_extract) {
  212.             printf("Extracting data into %s using %s:\n",
  213.             s, extractprog) ; FLUSH;
  214.             goto extract_it;
  215.         }
  216.         if (((*art_buf == '#' || *art_buf == ':')
  217.           && (strnEQ(art_buf+1, "! /bin/sh", 9)
  218.            || strnEQ(art_buf+1, "!/bin/sh", 8)
  219.            || strnEQ(art_buf+2, "This is ", 8)))
  220.          || strnEQ(art_buf, "sed ", 4)
  221.          || strnEQ(art_buf, "cat ", 4)
  222.          || strnEQ(art_buf, "echo ", 5)) {
  223.             fseek(artfp,-(long)strlen(art_buf)-NL_SIZE+1,1);
  224.             savefrom = ftell(artfp);
  225.             if (custom_extract) {
  226.             printf("Extracting shar into %s using %s:\n",
  227.                 s, extractprog) ; FLUSH;
  228.             goto extract_it;
  229.             }
  230.             /* Check for special-case of shar'ed-uuencoded file */
  231.             while(fgets(art_buf,LBUFLEN,artfp) != Nullch) {
  232.  
  233. /*** OS2: AAAAAAAAHHHHHHHHHHHH, ..... another problem with \r (^M)... **/
  234.  
  235.             for (counter = 0; counter <= strlen(art_buf); counter++)
  236.                 if ((art_buf[counter] == '\r') &&
  237.                     (art_buf[counter+1] == '\n')) {
  238.                     for (; art_buf[counter] != '\0'; counter++)
  239.                         art_buf[counter] = art_buf[counter+1];
  240.                 }
  241.  
  242.             if (*art_buf == '#' || *art_buf == ':'
  243.              || strnEQ(art_buf, "echo ", 5)
  244.              || strnEQ(art_buf, "sed ", 4))
  245.                 continue;
  246.             if (strnEQ(art_buf, "Xbegin ", 7)) {
  247.                 decode_type = UUDECODE;
  248.                 goto decode_it;
  249.             }
  250.             break;
  251.             }
  252.             printf("Extracting shar into %s:\n", s) ; FLUSH;
  253.             if (extractprog)
  254.             free(extractprog);
  255.             extractprog = savestr(filexp(getval("UNSHAR",UNSHAR)));
  256.           extract_it:
  257.             cnt = 0;
  258.             interp(cmd_buf,(sizeof cmd_buf),getval("EXSAVER",EXSAVER));
  259.             change_sl2bsl(cmd_buf);
  260.             termlib_reset();
  261.             resetty();        /* restore tty state */
  262.             fflush(stdout);
  263.             fflush(stderr);
  264.             doshell(SH,cmd_buf);
  265.             noecho();        /* revert to cbreaking */
  266.             crmode();
  267.             termlib_init();
  268.             break;
  269.         }
  270.         else
  271.         if (!custom_extract
  272.          && (strEQ(art_buf,"$\n")
  273.           || strEQ(art_buf,"$ f\n"))) {
  274.  
  275. /*** OS2: We have to reduce the savefrom-position by 1, because
  276.           we stripped of the \r in our input-line, so strlen(art_buf)
  277.           is 1 character too short. ***/
  278. /*            savefrom = ftell(artfp)-strlen(art_buf)-NL_SIZE+1;   */
  279.             savefrom = ftell(artfp)-strlen(art_buf)-NL_SIZE;
  280.             if (found_cut || (fgets(art_buf,LBUFLEN,artfp) != Nullch)) {
  281.  
  282. /*** OS2: AAAAAAAAHHHHHHHHHHHH, ..... another problem with \r (^M)... **/
  283.  
  284.             for (counter = 0; counter <= strlen(art_buf); counter++)
  285.                 if ((art_buf[counter] == '\r') &&
  286.                     (art_buf[counter+1] == '\n')) {
  287.                     for (; art_buf[counter] != '\0'; counter++)
  288.                         art_buf[counter] = art_buf[counter+1];
  289.                 }
  290.  
  291.                 if ((strnEQ(art_buf, "ship ", 5) ||
  292.                      strnEQ(art_buf, "cont ", 5))) {
  293.                         decode_type = UNSHIP;
  294.                         goto decode_it;
  295.                 }
  296.             }
  297.         }
  298.         else
  299.         if (!custom_extract
  300.          && (strEQ(art_buf,"table\n")
  301.           || strnEQ(art_buf,"begin ", 6))) {
  302.             decode_type = UUDECODE;
  303. /*** OS2: We have to reduce the savefrom-position by 1, because
  304.           we stripped of the \r in our input-line, so strlen(art_buf)
  305.           is 1 character too short. ***/
  306. /*            savefrom = ftell(artfp)-strlen(art_buf)-NL_SIZE+1; */
  307.             savefrom = ftell(artfp)-strlen(art_buf)-NL_SIZE;
  308.          decode_it:
  309.             printf("Extracting %s file into %s:\n",
  310.             decode_type == UNSHIP? "shipped":"uuencoded", s) ; FLUSH;
  311.             if (extractprog)
  312.             free(extractprog);
  313.             extractprog = savestr("-");
  314.             fseek(artfp, savefrom, 0);
  315.             cnt = 0;
  316.             fflush(stdout);
  317.             if (decode_type == UUDECODE) {
  318.             uud_start();
  319.             uudecode(artfp);
  320.             } else
  321.             unship(artfp);
  322.             break;
  323.         }
  324.         else {
  325.             if (cut_line(art_buf)) {
  326.             savefrom = ftell(artfp);
  327.             found_cut = TRUE;
  328.             }
  329.             else if (found_cut || ++cnt == 300) {
  330.             break;
  331.             }
  332.         }
  333.         }/* while */
  334.         if (cnt) {
  335.         if (custom_extract) {
  336.             printf("Didn't find cut line for extraction to '%s'.\n",
  337.             extractprog) ; FLUSH;
  338.         }
  339.         else
  340.             printf("Unable to determine type of file.\n") ; FLUSH;
  341.         }
  342.     }/* if */
  343.     }
  344.     else if ((s = index(buf,'|')) != Nullch) {
  345.                 /* is it a pipe command? */
  346.     s++;            /* skip the | */
  347.     while (*s == ' ') s++;
  348.     safecpy(altbuf,filexp(s),sizeof altbuf);
  349.     if (savedest)
  350.         free(savedest);
  351.     savedest = savestr(altbuf);
  352.     interp(cmd_buf, (sizeof cmd_buf), getval("PIPESAVER",PIPESAVER));
  353.     change_sl2bsl(cmd_buf);
  354.                 /* then set up for command */
  355.     termlib_reset();
  356.     resetty();        /* restore tty state */
  357.     fflush(stdout);
  358.     if (use_pref)        /* use preferred shell? */
  359.         doshell(Nullch,cmd_buf);
  360.                 /* do command with it */
  361.     else
  362.         doshell(sh,cmd_buf);    /* do command with sh */
  363.     noecho();        /* and stop echoing */
  364.     crmode();        /* and start cbreaking */
  365.     termlib_init();
  366.     }
  367.     else {            /* normal save */
  368.     bool there, mailbox;
  369.     char *savename = getval("SAVENAME",SAVENAME);
  370.  
  371.     s = buf+1;        /* skip s or S */
  372.     if (*s == '-') {    /* if they are confused, skip - also */
  373. #ifdef VERBOSE
  374.         IF(verbose) {
  375.         fputs("Warning: '-' ignored.  This isn't readnews.\n",stdout)
  376.           ; FLUSH;
  377.         }
  378.         ELSE
  379. #endif
  380. #ifdef TERSE
  381.         fputs("'-' ignored.\n",stdout) ; FLUSH;
  382. #endif
  383.         s++;
  384.     }
  385.     for (; *s == ' '; s++);    /* skip spaces */
  386.     safecpy(altbuf,filexp(s),sizeof altbuf);
  387.     s = altbuf;
  388.     change_bsl2sl(s);
  389. /*** OS2: we must not only look for '/' but also for '\\' to
  390.           determine if there is a directory specified ***/
  391.     if ((!index(s,'/')) && (!index(s,'\\'))) {
  392.         interp(buf, (sizeof buf), getval("SAVEDIR",SAVEDIR));
  393.         if (makedir(buf,MD_DIR))    /* ensure directory exists */
  394.         strcpy(buf,cwd);
  395.         if (*s) {
  396.         for (c = buf; *c; c++) ;
  397.         *c++ = '/';
  398.         strcpy(c,s);        /* add filename */
  399.         }
  400.         s = buf;
  401.     }
  402.     for (iter = 0;
  403.         (there = stat(s,&filestat) >= 0) &&
  404.         (filestat.st_mode & S_IFDIR);
  405.         iter++) {            /* is it a directory? */
  406.  
  407.         c = (s+strlen(s));
  408.         *c++ = '/';            /* put a slash before filename */
  409.         interp(c, s==buf?(sizeof buf):(sizeof altbuf),
  410.         iter ? "News" : savename );
  411.                 /* generate a default name somehow or other */
  412.     }
  413.     makedir(s,MD_FILE);
  414. /*** OS2: The test, if s contains a relytive path is not so easy
  415.           under an operatingsystem which has drives in the path ***/
  416.     if ((*s != '/') && (*(s+2) != '/') &&
  417.         (*s != '\\') && (*(s+2) != '\\')) {  /* relative path? */
  418.         c = (s==buf ? altbuf : buf);
  419.         sprintf(c, "%s/%s", cwd, s);
  420.         s = c;            /* absolutize it */
  421.     }
  422.     if (savedest)
  423.         free(savedest);
  424.     s = savedest = savestr(s);    /* doesn't move any more */
  425.                     /* make it handy for %b */
  426.     if (!there) {
  427.         if (mbox_always)
  428.         mailbox = TRUE;
  429.         else if (norm_always)
  430.         mailbox = FALSE;
  431.         else {
  432.         char *dflt = (instr(savename,"%a", TRUE) ? "nyq" : "ynq");
  433.         
  434.         sprintf(cmd_buf,
  435.         "\nFile %s doesn't exist--\n    use mailbox format? [%s] ",
  436.           s,dflt);
  437.           reask_save:
  438.         in_char(cmd_buf, 'M');
  439.         putchar('\n') ; FLUSH;
  440.         setdef(buf,dflt);
  441. #ifdef VERIFY
  442.         printcmd();
  443. #endif
  444.         if (*buf == 'h') {
  445. #ifdef VERBOSE
  446.             IF(verbose) {
  447.             printf("\n\
  448. Type y to create %s as a mailbox.\n\
  449. Type n to create it as a normal file.\n\
  450. Type q to abort the save.\n\
  451. ",s) ; FLUSH;
  452.             }
  453.             ELSE
  454. #endif
  455. #ifdef TERSE
  456.             fputs("\n\
  457. y to create mailbox.\n\
  458. n to create normal file.\n\
  459. q to abort.\n\
  460. ",stdout) ; FLUSH;
  461. #endif
  462.             goto reask_save;
  463.         }
  464.         else if (*buf == 'n') {
  465.             mailbox = FALSE;
  466.         }
  467.         else if (*buf == 'y') {
  468.             mailbox = TRUE;
  469.         }
  470.         else if (*buf == 'q') {
  471.             goto s_bomb;
  472.         }
  473.         else {
  474.             fputs(hforhelp,stdout) ; FLUSH;
  475.             settle_down();
  476.             goto reask_save;
  477.         }
  478.         }
  479.     }
  480.     else if (filestat.st_mode & S_IFCHR)
  481.         mailbox = FALSE;
  482.     else {
  483.         int tmpfd;
  484.         
  485.         tmpfd = open(s,0);
  486.         if (tmpfd == -1)
  487.         mailbox = FALSE;
  488.         else {
  489.         if (read(tmpfd,buf,LBUFLEN)) {
  490.             c = buf;
  491.             if (!isspace(MBOXCHAR))   /* if non-zero, */
  492.             while (isspace(*c))   /* check the first character */
  493.                 c++;
  494.             mailbox = (*c == MBOXCHAR) || (*c == '\x01');
  495.         } else {
  496.             mailbox = mbox_always;    /* if zero length, recheck -M */
  497.         }
  498.         close(tmpfd);
  499.         }
  500.     }
  501.  
  502. /*** OS2: we don't not use shell-scripts or batch-files,
  503.           we use our own little saver-function ***/
  504. /*    safecpy(cmd_buf, filexp(mailbox ?                      */
  505. /*        getval("MBOXSAVER",MBOXSAVER) :                    */
  506. /*        getval("NORMSAVER",NORMSAVER) ), sizeof cmd_buf);  */
  507.                 /* format the command */
  508. /*    termlib_reset();                                       */
  509. /*    resetty();      /* make terminal behave */
  510. /*    if (doshell(use_pref?Nullch:SH,cmd_buf)) {       */
  511.     if (article_saver(mailbox,NULL,NULL)) {
  512.         termlib_init();
  513.         fputs("Not saved",stdout);
  514.     } else {
  515.         termlib_init();
  516.         printf("%s to %s %s",
  517.           there?"Appended":"Saved",
  518.           mailbox?"mailbox":"file",
  519.           s);
  520.     }
  521.     if (interactive)
  522.         putchar('\n') ; FLUSH;
  523.     noecho();        /* make terminal do what we want */
  524.     crmode();
  525.     }
  526. s_bomb:
  527. #ifdef SERVER
  528.     if (chdir(spool)) {
  529. #else /* not SERVER */
  530.     if (chdir(spool) || chdir(ngdir)) {
  531. #endif /* SERVER */
  532.     printf(nocd,ngdir) ; FLUSH;
  533.     sig_catcher(0);
  534.     }
  535.     return SAVE_DONE;
  536. }
  537.  
  538. int
  539. cancel_article()
  540. {
  541.     char *artid_buf;
  542.     char *ngs_buf;
  543.     char *from_buf;
  544.     char *reply_buf;
  545.     int myuid = getuid();
  546.     int r = -1;
  547.  
  548.     if (artopen(art) == Nullfp) {
  549. #ifdef VERBOSE
  550.     IF(verbose) {
  551.         fputs("\n\
  552. Cancelling null articles is your idea of fun?  :-)\n\
  553. ",stdout) ; FLUSH;
  554.     }
  555.     ELSE
  556. #endif
  557. #ifdef TERSE
  558.         fputs(nullart,stdout) ; FLUSH;
  559. #endif
  560.     return r;
  561.     }
  562.     reply_buf = fetchlines(art,REPLY_LINE);
  563.     from_buf = fetchlines(art,FROM_LINE);
  564.     artid_buf = fetchlines(art,ARTID_LINE);
  565.     ngs_buf = fetchlines(art,NGS_LINE);
  566.     if (!instr(from_buf,sitename,FALSE) ||
  567.     (!instr(from_buf,logname,TRUE) &&
  568.      !instr(reply_buf,logname,TRUE) &&
  569. #ifdef NEWSADMIN
  570.      myuid != newsuid &&
  571. #endif
  572.      myuid != ROOTID ) ) {
  573. #ifdef DEBUGGING
  574.         if (debug)
  575.         printf("\n%s@%s != %s\n",logname,sitename,from_buf) ; FLUSH;
  576. #endif
  577. #ifdef VERBOSE
  578.         IF(verbose) {
  579.         fputs("\nYou can't cancel someone else's article\n",stdout)
  580.           ; FLUSH;
  581.         }
  582.         ELSE
  583. #endif
  584. #ifdef TERSE
  585.         fputs("\nNot your article\n",stdout) ; FLUSH;
  586. #endif
  587.     }
  588.     else {
  589.     tmpfp = fos2open(headname,"w");    /* open header file */
  590.     if (tmpfp == Nullfp) {
  591.         printf(cantcreate,headname) ; FLUSH;
  592.         goto no_cancel;
  593.     }
  594.     interp(buf, (sizeof buf), getval("CANCELHEADER",CANCELHEADER));
  595.     fputs(buf,tmpfp);
  596.     fclose(tmpfp);
  597.     fputs("\nCanceling...\n",stdout) ; FLUSH;
  598.     r = doshell(sh,filexp(getval("CANCEL",CANCEL)));
  599.     }
  600. no_cancel:
  601.     free(artid_buf);
  602.     free(ngs_buf);
  603.     free(from_buf);
  604.     free(reply_buf);
  605.     return r;
  606. }
  607.  
  608. int
  609. supersede_article()        /* Supersedes: */
  610. {
  611.     char *artid_buf;
  612.     char *ngs_buf;
  613.     char *from_buf;
  614.     char *reply_buf;
  615.     int myuid = getuid();
  616.     int r = -1;
  617.     bool incl_body = (*buf == 'Z');
  618.  
  619.     if (artopen(art) == Nullfp) {
  620. #ifdef VERBOSE
  621.     IF(verbose) {
  622.         fputs("\n\
  623. Superceding null articles is your idea of fun?  :-)\n\
  624. ",stdout) ; FLUSH;
  625.     }
  626.     ELSE
  627. #endif
  628. #ifdef TERSE
  629.         fputs(nullart,stdout) ; FLUSH;
  630. #endif
  631.     return r;
  632.     }
  633.     reply_buf = fetchlines(art,REPLY_LINE);
  634.     from_buf = fetchlines(art,FROM_LINE);
  635.     artid_buf = fetchlines(art,ARTID_LINE);
  636.     ngs_buf = fetchlines(art,NGS_LINE);
  637.     if (!instr(from_buf,sitename,FALSE) ||
  638.     (!instr(from_buf,logname,TRUE) &&
  639.      !instr(reply_buf,logname,TRUE) &&
  640. #ifdef NEWSADMIN
  641.      myuid != newsuid &&
  642. #endif
  643.      myuid != ROOTID ) ) {
  644. #ifdef DEBUGGING
  645.         if (debug)
  646.         printf("\n%s@%s != %s\n",logname,sitename,from_buf) ; FLUSH;
  647. #endif
  648. #ifdef VERBOSE
  649.         IF(verbose) {
  650.         fputs("\nYou can't supersede someone else's article\n",stdout)
  651.           ; FLUSH;
  652.         }
  653.         ELSE
  654. #endif
  655. #ifdef TERSE
  656.         fputs("\nNot your article\n",stdout) ; FLUSH;
  657. #endif
  658.     }
  659.     else {
  660.     tmpfp = fos2open(headname,"w");    /* open header file */
  661.     if (tmpfp == Nullfp) {
  662.         printf(cantcreate,headname) ; FLUSH;
  663.         goto no_commute;
  664.     }
  665.     interp(buf, (sizeof buf), getval("SUPERSEDEHEADER",SUPERSEDEHEADER));
  666.     fputs(buf,tmpfp);
  667.     if (incl_body && artfp != Nullfp) {
  668. #ifdef ASYNC_PARSE
  669.         parse_maybe(art);
  670. #endif
  671.         fseek(artfp,(long)htype[PAST_HEADER].ht_minpos,0);
  672.         while (fgets(buf,LBUFLEN,artfp) != Nullch) {
  673.         fputs(buf,tmpfp);
  674.         }
  675.     }
  676.     fclose(tmpfp);
  677.         safecpy(cmd_buf,filexp(getval("NEWSPOSTER",NEWSPOSTER)),
  678.         sizeof cmd_buf);
  679.         invoke(cmd_buf,origdir);
  680.     r = 0;
  681.     }
  682. no_commute:
  683.     free(artid_buf);
  684.     free(ngs_buf);
  685.     free(from_buf);
  686.     free(reply_buf);
  687.     return r;
  688. }
  689.  
  690. void
  691. reply()
  692. {
  693.     bool incl_body = (*buf == 'R');
  694.     char *maildoer = savestr(filexp(getval("MAILPOSTER",MAILPOSTER)));
  695.     int counter;  /** OS2-patch **/
  696.     time_t timeinseconds;
  697.  
  698.     artopen(art);
  699. /*** OS2: at the moment the header is opened in binarymode,
  700.           perhaps we must change that to textmode.
  701.           Yeah, done ! ***/
  702.     tmpfp = fopen(headname,"w");    /* open header file */
  703.     if (tmpfp == Nullfp) {
  704.     printf(cantcreate,headname) ; FLUSH;
  705.     goto no_reply;
  706.     }
  707.     fprintf(tmpfp,"From: %s@%s (%s)\n",uupc_rc_settings.user,
  708.                                        uupc_rc_settings.domain,
  709.                                        uupc_rc_settings.name);
  710.     timeinseconds = time(NULL);
  711.     fprintf(tmpfp,"Date: %s",ctime(&timeinseconds));
  712.     interp(buf, (sizeof buf), getval("MAILHEADER",MAILHEADER));
  713.     fputs(buf,tmpfp);
  714.     if (!instr(maildoer,"%h",TRUE))
  715. #ifdef VERBOSE
  716.     IF(verbose) {
  717.         printf("\n%s\n(Above lines saved in file %s)\n",buf,headname)
  718.           ; FLUSH;
  719.     }
  720.     ELSE
  721. #endif
  722. #ifdef TERSE
  723.         printf("\n%s\n(Header in %s)\n",buf,headname) ; FLUSH;
  724. #endif
  725.     if (incl_body && artfp != Nullfp) {
  726.     interp(buf, (sizeof buf), getval("YOUSAID",YOUSAID));
  727.     fprintf(tmpfp,"%s\n",buf);
  728. #ifdef ASYNC_PARSE
  729.     parse_maybe(art);
  730. #endif
  731.     fseek(artfp,(long)htype[PAST_HEADER].ht_minpos,0);
  732.     while (fgets(buf,LBUFLEN,artfp) != Nullch) {
  733.  
  734. /*** OS2: We need another CTRL-M-Killer. Please fix, when fseek works
  735.           fine with text files ***/
  736.  
  737.             for (counter = 0; counter <= strlen(buf); counter++)
  738.                 if ((buf[counter] == '\r') &&
  739.                     (buf[counter+1] == '\n')) {
  740.                     for (; buf[counter] != '\0'; counter++)
  741.                         buf[counter] = buf[counter+1];
  742.                 }
  743.  
  744.         fprintf(tmpfp,"%s%s",indstr,buf);
  745.     }
  746.     fprintf(tmpfp,"\n");
  747.     }
  748.     fclose(tmpfp);
  749. /*** OS2: we will not invoke a shell, which would execute
  750.           the Rnmail shellscript, we use our own function ***/
  751. /*    interp(cmd_buf, (sizeof cmd_buf), maildoer);  */
  752. /*    invoke(cmd_buf,origdir); */
  753.     mail_reply();
  754.     UNLINK(headname);        /* kill the header file */
  755. no_reply:
  756.     free(maildoer);
  757. }
  758.  
  759. void
  760. followup()
  761. {
  762.     bool incl_body = (*buf == 'F');
  763.     char hbuf[4*LBUFLEN];    /* four times the old size */
  764.     ART_NUM oldart = art;
  765.     int counter;    /** OS2-patch **/
  766.  
  767.     if (strlen(moderated) > 3) {
  768.         printf("\nCannot post, group is moderated!\n");
  769.         return;
  770.     }
  771.  
  772.     if (!incl_body && art <= lastart) {
  773.     in_char("\n\nAre you starting an unrelated topic? [yn] ", 'F');
  774.     setdef(buf,"y");
  775.     puts("\n");
  776.     if (*buf != 'n')
  777.         art = lastart + 1;
  778.     }
  779.     artopen(art);
  780. /*** OS2: we must open the header in textmode, so use fopen ***/
  781.     tmpfp = fopen(headname,"w");
  782.     if (tmpfp == Nullfp) {
  783.     printf(cantcreate,headname) ; FLUSH;
  784.     art = oldart;
  785.     return;
  786.     }
  787.     interp(hbuf, (sizeof hbuf), getval("NEWSHEADER",NEWSHEADER));
  788.     fprintf(tmpfp,"%s",hbuf);
  789.     if (incl_body && artfp != Nullfp) {
  790. #ifdef VERBOSE
  791.     if (verbose)
  792.         fputs("\n\
  793. (Be sure to double-check the attribution against the signature, and\n\
  794. trim the quoted article down as much as possible.)\n\
  795. ",stdout) ; FLUSH;
  796. #endif
  797.     interp(buf, (sizeof buf), getval("ATTRIBUTION",ATTRIBUTION));
  798.     fprintf(tmpfp,"%s\n",buf);
  799. #ifdef ASYNC_PARSE
  800.     parse_maybe(art);
  801. #endif
  802.     fseek(artfp,(long)htype[PAST_HEADER].ht_minpos,0);
  803.     while (fgets(buf,LBUFLEN,artfp) != Nullch) {
  804.  
  805. /*** OS2: We need another CTRL-M-Killer. Please fix, when fseek works
  806.           fine with text files ***/
  807.  
  808.             for (counter = 0; counter <= strlen(buf); counter++)
  809.                 if ((buf[counter] == '\r') &&
  810.                     (buf[counter+1] == '\n')) {
  811.                     for (; buf[counter] != '\0'; counter++)
  812.                         buf[counter] = buf[counter+1];
  813.                 }
  814.  
  815.         fprintf(tmpfp,"%s%s",indstr,buf);
  816.     }
  817.     fprintf(tmpfp,"\n");
  818.     }
  819.     fclose(tmpfp);
  820. /*** OS2: OK, we will take our own function and not
  821.           the unix-shellscript (or any other shellscript) ***/
  822. /*    safecpy(cmd_buf,filexp(getval("NEWSPOSTER",NEWSPOSTER)),sizeof cmd_buf);*/
  823. /*    invoke(cmd_buf,origdir);  */
  824.     article_poster();
  825.     UNLINK(headname);
  826.     art = oldart;
  827. }
  828.  
  829. void
  830. invoke(cmd,dir)
  831. char *cmd,*dir;
  832. {
  833.     if (chdir(dir)) {
  834.     printf(nocd,dir) ; FLUSH;
  835.     return;
  836.     }
  837.     termlib_reset();
  838. #ifdef VERBOSE
  839.     IF(verbose) {
  840.     printf("\n(leaving cbreak mode; cwd=%s)\nInvoking command: %s\n\n",
  841.         dir,cmd) ; FLUSH;
  842.     }
  843.     ELSE
  844. #endif
  845. #ifdef TERSE
  846.     printf("\n(-cbreak; cwd=%s)\nInvoking: %s\n\n",dir,cmd) ; FLUSH;
  847. #endif
  848.     resetty();            /* make terminal well-behaved */
  849.     fflush(stdout);
  850.     doshell(sh,cmd);        /* do the command */
  851.     noecho();            /* set no echo */
  852.     crmode();            /* and cbreak mode */
  853. #ifdef VERBOSE
  854.     IF(verbose) {
  855.     fputs("\n(re-entering cbreak mode)\n",stdout) ; FLUSH;
  856.     }
  857.     ELSE
  858. #endif
  859. #ifdef TERSE
  860.     fputs("\n(+cbreak)\n",stdout) ; FLUSH;
  861. #endif
  862.     termlib_init();
  863. #ifdef SERVER
  864.     if (chdir(spool)) {
  865. #else /* not SERVER */
  866.     if (chdir(spool) || chdir(ngdir)) {
  867. #endif /* SERVER */
  868.     printf(nocd,ngdir) ; FLUSH;
  869.     sig_catcher(0);
  870.     }
  871. }
  872.  
  873. /*
  874. ** cut_line() determines if a line is meant as a "cut here" marker.
  875. ** Some examples that we understand:
  876. **
  877. **  BEGIN--cut here--cut here
  878. **
  879. **  ------------------ tear at this line ------------------
  880. **
  881. **  #----cut here-----cut here-----cut here-----cut here----#
  882. */
  883. bool
  884. cut_line(str)
  885. char *str;
  886. {
  887.     char *cp, got_flag;
  888.     char word[80];
  889.     int  dash_cnt, equal_cnt, other_cnt;
  890.  
  891.     /* Disallow any single-/double-quoted, parenthetical or c-commented
  892.     ** string lines.  Make sure it has the cut-phrase and at least six
  893.     ** '-'s or '='s.  If only four '-'s are present, check for a duplicate
  894.     ** of the cut phrase.  If over 20 unknown characters are encountered,
  895.     ** assume it isn't a cut line.  If we succeed, return TRUE.
  896.     */
  897.     for (cp = str, dash_cnt = equal_cnt = other_cnt = 0; *cp; cp++) {
  898.     switch (*cp) {
  899.     case '-':
  900.         dash_cnt++;
  901.         break;
  902.     case '=':
  903.         equal_cnt++;
  904.         break;
  905.     case '/':
  906.         if(*(cp+1) != '*') {
  907.         break;
  908.         }
  909.     case '"':
  910.     case '\'':
  911.     case '(':
  912.     case ')':
  913.     case '[':
  914.     case ']':
  915.     case '{':
  916.     case '}':
  917.         return FALSE;
  918.     default:
  919.         other_cnt++;
  920.         break;
  921.     }
  922.     }
  923.     if (dash_cnt < 4 && equal_cnt < 6)
  924.     return FALSE;
  925.  
  926.     got_flag = 0;
  927.  
  928.     for (*(cp = word) = '\0'; *str; str++) {
  929.     if (islower(*str))
  930.         *cp++ = *str;
  931.     else if (isupper(*str))
  932.         *cp++ = tolower(*str);
  933.     else {
  934.         if (*word) {
  935.         *cp = '\0';
  936.         switch (got_flag) {
  937.         case 2:
  938.             if (!strcmp(word, "line")
  939.              || !strcmp(word, "here"))
  940.             if ((other_cnt -= 4) <= 20)
  941.                 return TRUE;
  942.             break;
  943.         case 1:
  944.             if (!strcmp(word, "this")) {
  945.             got_flag = 2;
  946.             other_cnt -= 4;
  947.             }
  948.             else if (!strcmp(word, "here")) {
  949.             other_cnt -= 4;
  950.             if ((dash_cnt >= 6 || equal_cnt >= 6)
  951.              && other_cnt <= 20)
  952.                 return TRUE;
  953.             dash_cnt = 6;
  954.             got_flag = 0;
  955.             }
  956.             break;
  957.         case 0:
  958.             if (!strcmp(word, "cut")
  959.              || !strcmp(word, "snip")
  960.              || !strcmp(word, "tear")) {
  961.             got_flag = 1;
  962.             other_cnt -= strlen(word);
  963.             }
  964.             break;
  965.         }
  966.         *(cp = word) = '\0';
  967.         }
  968.     }
  969.     } /* for *str */
  970.  
  971.     return FALSE;
  972. }
  973.