home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume23 / trn / part08 / respond.c next >
Encoding:
C/C++ Source or Header  |  1991-08-22  |  15.9 KB  |  684 lines

  1. /* $Header: respond.c,v 4.3.3.2 91/01/16 03:28:40 davison Trn $
  2.  *
  3.  * $Log:    respond.c,v $
  4.  * Revision 4.3.3.2  91/01/16  03:28:40  davison
  5.  * Integrated rn patches 48-54.  Changed fseek to allow for NL_SIZE.
  6.  * 
  7.  * Revision 4.3.3.1  90/07/21  20:30:18  davison
  8.  * Initial Trn Release
  9.  * 
  10.  * Revision 4.3.2.4  90/11/22  16:09:04  sob
  11.  * Added changes to accomodate pickly C preprocessors
  12.  * 
  13.  * Revision 4.3.2.3  90/03/22  23:05:19  sob
  14.  * Fixes provided by Wayne Davison <drivax!davison>
  15.  * 
  16.  * Revision 4.3.2.2  89/11/26  18:25:10  sob
  17.  * Enlarged the size of the header buffer to accomodate long references lines.
  18.  * Fix provided by Joe Buck.
  19.  * 
  20.  * Revision 4.3.2.1  89/11/06  01:00:26  sob
  21.  * Added RRN support from NNTP 1.5
  22.  * 
  23.  * Revision 4.3.1.5  85/09/10  11:05:00  lwall
  24.  * Improved %m in in_char().
  25.  * 
  26.  * Revision 4.3.1.4  85/05/23  17:24:49  lwall
  27.  * Now allows 'r' and 'f' on null articles.
  28.  * 
  29.  * Revision 4.3.1.3  85/05/15  14:42:32  lwall
  30.  * Removed duplicate include of intrp.h.
  31.  * 
  32.  * Revision 4.3.1.2  85/05/14  08:55:15  lwall
  33.  * Default for normal/mailbox question was applied to wrong buffer.
  34.  * 
  35.  * Revision 4.3.1.1  85/05/10  11:37:33  lwall
  36.  * Branch for patches.
  37.  * 
  38.  * Revision 4.3  85/05/01  11:47:04  lwall
  39.  * Baseline for release with 4.3bsd.
  40.  * 
  41.  */
  42.  
  43. #include "EXTERN.h"
  44. #include "common.h"
  45. #include "intrp.h"
  46. #include "head.h"
  47. #include "term.h"
  48. #include "ng.h"
  49. #include "util.h"
  50. #include "rn.h"
  51. #include "artio.h"
  52. #include "final.h"
  53. #include "uudecode.h"
  54. #include "INTERN.h"
  55. #include "respond.h"
  56.  
  57. static char nullart[] = "\nNull article\n";
  58.  
  59. void
  60. respond_init()
  61. {
  62.     ;
  63. }
  64.  
  65. int
  66. save_article()
  67. {
  68.     bool use_pref, cut_line();
  69.     register char *s, *c;
  70.     char altbuf[CBUFLEN];
  71.     int iter;
  72.     bool interactive = (buf[1] == FINISHCMD);
  73.     char cmd = *buf;
  74.     
  75.     if (!finish_command(interactive))    /* get rest of command */
  76.     return SAVE_ABORT;
  77.     if ((use_pref = isupper(cmd)) != 0)
  78.     cmd = tolower(cmd);
  79. #ifdef ASYNC_PARSE
  80.     parse_maybe(art);
  81. #endif
  82.     savefrom = (cmd == 'w' || cmd == 'e' ? htype[PAST_HEADER].ht_minpos : 0);
  83.     if (artopen(art) == Nullfp) {
  84. #ifdef VERBOSE
  85.     IF(verbose)
  86.         fputs("\n\
  87. Saving null articles is not very productive!  :-)\n\
  88. ",stdout) FLUSH;
  89.     ELSE
  90. #endif
  91. #ifdef TERSE
  92.         fputs(nullart,stdout) FLUSH;
  93. #endif
  94.     return SAVE_DONE;
  95.     }
  96.     if (chdir(cwd)) {
  97.     printf(nocd,cwd) FLUSH;
  98.     sig_catcher(0);
  99.     }
  100.     if (cmd == 'e') {        /* is this an extract command? */
  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 (extractprog) {
  110.         free(extractprog);
  111.         extractprog = Nullch;
  112.     }
  113.     if (*s) {
  114.         cmdstr = cpytill(buf,s,'|');    /* check for | */
  115.         s = buf + strlen(buf)-1;
  116.         while (*s == ' ') s--;        /* trim trailing spaces */
  117.         *++s = '\0';
  118.         if (*cmdstr) {
  119.         s = cmdstr+1;            /* skip | */
  120.         while (*s == ' ') s++;
  121.         if (strEQ(s,"-"))
  122.             cmdstr = Nullch;
  123.         else {
  124.             extractprog = savestr(s);    /* put extracter in %e */
  125.             if (uu_out != Nullfp)
  126.             uud_end();
  127.         }
  128.         } else
  129.         cmdstr = Nullch;
  130.         s = buf;
  131.     } else
  132.         cmdstr = Nullch;
  133.  
  134.     fseek(artfp,savefrom,0);
  135.     if ((cmd = *s) == '\0')
  136.         interp(s = buf, (sizeof buf), getval("SAVEDIR",SAVEDIR));
  137.     if (*s != '/') {        /* relative path? */
  138.         c = (s==buf ? altbuf : buf);
  139.         sprintf(c, "%s/%s", cwd, s);
  140.         s = c;            /* absolutize it */
  141.     }
  142.     if (uu_out != Nullfp) {
  143.         printf("Continuing %s:%s\n", uu_fname,
  144.         cmd != '\0' && strNE(savedest,s) ?
  145.          " (Ignoring conflicting directory)" : nullstr );
  146.         uudecode(artfp);
  147.     }
  148.     else {
  149.         if (savedest)
  150.         free(savedest);
  151.         s = savedest = savestr(s);    /* make it handy for %b */
  152.         if (makedir(s, MD_DIR)) {    /* ensure directory exists */
  153.         int_count++;
  154.         return SAVE_DONE;
  155.         }
  156.         if (chdir(s)) {
  157.         printf(nocd,s) FLUSH;
  158.         sig_catcher(0);
  159.         }
  160.         s = getwd(buf);        /* simplify path for output */
  161.         while(fgets(art_buf,LBUFLEN,artfp) != Nullch) {
  162.         if (*art_buf <= ' ')
  163.             continue;    /* Ignore empty or initially-whitespace lines */
  164.         if (found_cut && cmdstr) {
  165.             printf("Extracting data into %s using %s:\n",
  166.             s, extractprog);
  167.             goto extract_it;
  168.         }
  169.         if (((*art_buf == '#' || *art_buf == ':')
  170.           && (strnEQ(art_buf+1, "! /bin/sh", 9)
  171.            || strnEQ(art_buf+1, "!/bin/sh", 8)
  172.            || strnEQ(art_buf+2, "This is ", 8)))
  173.          || strnEQ(art_buf, "sed ", 4)
  174.          || strnEQ(art_buf, "cat ", 4)
  175.          || strnEQ(art_buf, "echo ", 5)) {
  176.             fseek(artfp,(long)-strlen(art_buf)-NL_SIZE+1,1);
  177.             savefrom = ftell(artfp);
  178.             if (cmdstr) {
  179.             printf("Extracting shar into %s using %s:\n",
  180.                 s, extractprog);
  181.             goto extract_it;
  182.             }
  183.             /* Check for special-case of shar'ed-uuencoded file */
  184.             while(fgets(art_buf,LBUFLEN,artfp) != Nullch) {
  185.             if (*art_buf == '#' || *art_buf == ':'
  186.              || strnEQ(art_buf, "echo ", 5)
  187.              || strnEQ(art_buf, "sed ", 4))
  188.                 continue;
  189.             if (strnEQ(art_buf, "Xbegin ", 7))
  190.                 goto uu_decode;
  191.             break;
  192.             }
  193.             printf("Extracting shar into %s:\n", s);
  194.             extractprog = savestr(filexp(getval("UNSHAR",UNSHAR)));
  195.           extract_it:
  196.             cnt = 0;
  197.             interp(cmd_buf,(sizeof cmd_buf),getval("EXSAVER",EXSAVER));
  198.             resetty();        /* restore tty state */
  199.             doshell(SH,cmd_buf);
  200.             noecho();        /* revert to cbreaking */
  201.             crmode();
  202.             break;
  203.         }
  204.         else
  205.         if (!cmdstr
  206.          && (strnEQ(art_buf,"table ", 6)
  207.           || strnEQ(art_buf,"table\n", 6)
  208.           || strnEQ(art_buf,"begin ", 6))) {
  209.          uu_decode:
  210.             printf("Extracting uuencoded file into %s:\n", s);
  211.             extractprog = savestr("-");
  212.             cnt = 0;
  213.             fseek(artfp,(long)-strlen(art_buf)-NL_SIZE+1,1);
  214.             savefrom = ftell(artfp);
  215.             uud_start(s);
  216.             uudecode(artfp);
  217.             break;
  218.         }
  219.         else {
  220.             if (cut_line(art_buf)) {
  221.             savefrom = ftell(artfp);
  222.             found_cut = TRUE;
  223.             }
  224.             else if (found_cut || ++cnt == 200) {
  225.             break;
  226.             }
  227.         }
  228.         }/* while */
  229.         if (cnt) {
  230.         if (!cmdstr)
  231.             extractprog = savestr("-");
  232.         printf("Unable to determine type of file.\n");
  233.         }
  234.     }/* if */
  235.     }
  236.     else if ((s = index(buf,'|')) != Nullch) {
  237.                 /* is it a pipe command? */
  238.     s++;            /* skip the | */
  239.     while (*s == ' ') s++;
  240.     safecpy(altbuf,filexp(s),sizeof altbuf);
  241.     if (savedest)
  242.         free(savedest);
  243.     savedest = savestr(altbuf);
  244.     interp(cmd_buf, (sizeof cmd_buf), getval("PIPESAVER",PIPESAVER));
  245.                 /* then set up for command */
  246.     resetty();        /* restore tty state */
  247.     if (use_pref)        /* use preferred shell? */
  248.         doshell(Nullch,cmd_buf);
  249.                 /* do command with it */
  250.     else
  251.         doshell(sh,cmd_buf);    /* do command with sh */
  252.     noecho();        /* and stop echoing */
  253.     crmode();        /* and start cbreaking */
  254.     }
  255.     else {            /* normal save */
  256.     bool there, mailbox;
  257.     char *savename = getval("SAVENAME",SAVENAME);
  258.  
  259.     s = buf+1;        /* skip s or S */
  260.     if (*s == '-') {    /* if they are confused, skip - also */
  261. #ifdef VERBOSE
  262.         IF(verbose)
  263.         fputs("Warning: '-' ignored.  This isn't readnews.\n",stdout)
  264.           FLUSH;
  265.         ELSE
  266. #endif
  267. #ifdef TERSE
  268.         fputs("'-' ignored.\n",stdout) FLUSH;
  269. #endif
  270.         s++;
  271.     }
  272.     for (; *s == ' '; s++);    /* skip spaces */
  273.     safecpy(altbuf,filexp(s),sizeof altbuf);
  274.     s = altbuf;
  275.     if (! index(s,'/')) {
  276.         interp(buf, (sizeof buf), getval("SAVEDIR",SAVEDIR));
  277.         if (makedir(buf,MD_DIR))    /* ensure directory exists */
  278.         strcpy(buf,cwd);
  279.         if (*s) {
  280.         for (c = buf; *c; c++) ;
  281.         *c++ = '/';
  282.         strcpy(c,s);        /* add filename */
  283.         }
  284.         s = buf;
  285.     }
  286.     for (iter = 0;
  287.         (there = stat(s,&filestat) >= 0) &&
  288.         (filestat.st_mode & S_IFDIR);
  289.         iter++) {            /* is it a directory? */
  290.  
  291.         c = (s+strlen(s));
  292.         *c++ = '/';            /* put a slash before filename */
  293.         interp(c, s==buf?(sizeof buf):(sizeof altbuf),
  294.         iter ? "News" : savename );
  295.                 /* generate a default name somehow or other */
  296.         if (index(c,'/')) {        /* yikes, a '/' in the filename */
  297.         makedir(s,MD_FILE);
  298.         }
  299.     }
  300.     if (*s != '/') {        /* relative path? */
  301.         c = (s==buf ? altbuf : buf);
  302.         sprintf(c, "%s/%s", cwd, s);
  303.         s = c;            /* absolutize it */
  304.     }
  305.     if (savedest)
  306.         free(savedest);
  307.     s = savedest = savestr(s);    /* doesn't move any more */
  308.                     /* make it handy for %b */
  309.     if (!there) {
  310.         if (mbox_always)
  311.         mailbox = TRUE;
  312.         else if (norm_always)
  313.         mailbox = FALSE;
  314.         else {
  315.         char *dflt = (instr(savename,"%a") ? "nyq" : "ynq");
  316.         
  317.         sprintf(cmd_buf,
  318.         "\nFile %s doesn't exist--\n    use mailbox format? [%s] ",
  319.           s,dflt);
  320.           reask_save:
  321.         in_char(cmd_buf, 'M');
  322.         putchar('\n') FLUSH;
  323.         setdef(buf,dflt);
  324. #ifdef VERIFY
  325.         printcmd();
  326. #endif
  327.         if (*buf == 'h') {
  328. #ifdef VERBOSE
  329.             IF(verbose)
  330.             printf("\n\
  331. Type y to create %s as a mailbox.\n\
  332. Type n to create it as a normal file.\n\
  333. Type q to abort the save.\n\
  334. ",s) FLUSH;
  335.             ELSE
  336. #endif
  337. #ifdef TERSE
  338.             fputs("\n\
  339. y to create mailbox.\n\
  340. n to create normal file.\n\
  341. q to abort.\n\
  342. ",stdout) FLUSH;
  343. #endif
  344.             goto reask_save;
  345.         }
  346.         else if (*buf == 'n') {
  347.             mailbox = FALSE;
  348.         }
  349.         else if (*buf == 'y') {
  350.             mailbox = TRUE;
  351.         }
  352.         else if (*buf == 'q') {
  353.             goto s_bomb;
  354.         }
  355.         else {
  356.             fputs(hforhelp,stdout) FLUSH;
  357.             settle_down();
  358.             goto reask_save;
  359.         }
  360.         }
  361.     }
  362.     else if (filestat.st_mode & S_IFCHR)
  363.         mailbox = FALSE;
  364.     else {
  365.         int tmpfd;
  366.         
  367.         tmpfd = open(s,0);
  368.         if (tmpfd == -1)
  369.         mailbox = FALSE;
  370.         else {
  371.         read(tmpfd,buf,LBUFLEN);
  372.         c = buf;
  373.         if (!isspace(MBOXCHAR))
  374.             while (isspace(*c))
  375.             c++;
  376.         mailbox = (*c == MBOXCHAR);
  377.         close(tmpfd);
  378.         }
  379.     }
  380.  
  381.     safecpy(cmd_buf, filexp(mailbox ?
  382.         getval("MBOXSAVER",MBOXSAVER) :
  383.         getval("NORMSAVER",NORMSAVER) ), sizeof cmd_buf);
  384.                 /* format the command */
  385.     resetty();        /* make terminal behave */
  386.     if (doshell(use_pref?Nullch:SH,cmd_buf))
  387.         fputs("Not saved",stdout);
  388.     else
  389.         printf("%s to %s %s",
  390.           there?"Appended":"Saved",
  391.           mailbox?"mailbox":"file",
  392.           s);
  393.     if (interactive)
  394.         putchar('\n') FLUSH;
  395.     noecho();        /* make terminal do what we want */
  396.     crmode();
  397.     }
  398. s_bomb:
  399. #ifdef SERVER
  400.     if (chdir(spool)) {
  401. #else /* not SERVER */
  402.     if (chdir(spool) || chdir(ngdir)) {
  403. #endif /* SERVER */
  404.     printf(nocd,ngdir) FLUSH;
  405.     sig_catcher(0);
  406.     }
  407.     return SAVE_DONE;
  408. }
  409.  
  410. int
  411. cancel_article()
  412. {
  413.     char *artid_buf;
  414.     char *ngs_buf;
  415.     char *from_buf;
  416.     char *reply_buf;
  417.     int myuid = getuid();
  418.     int r = -1;
  419.  
  420.     if (artopen(art) == Nullfp) {
  421. #ifdef VERBOSE
  422.     IF(verbose)
  423.         fputs("\n\
  424. Cancelling null articles is your idea of fun?  :-)\n\
  425. ",stdout) FLUSH;
  426.     ELSE
  427. #endif
  428. #ifdef TERSE
  429.         fputs(nullart,stdout) FLUSH;
  430. #endif
  431.     return r;
  432.     }
  433.     reply_buf = fetchlines(art,REPLY_LINE);
  434.     from_buf = fetchlines(art,FROM_LINE);
  435.     artid_buf = fetchlines(art,ARTID_LINE);
  436.     ngs_buf = fetchlines(art,NGS_LINE);
  437.     if (!instr(from_buf,sitename) ||
  438.     (!instr(from_buf,logname) &&
  439.      !instr(reply_buf,logname) &&
  440. #ifdef NEWSADMIN
  441.      myuid != newsuid &&
  442. #endif
  443.      myuid != ROOTID ) )
  444. #ifdef VERBOSE
  445.         IF(verbose)
  446.         fputs("\nYou can't cancel someone else's article\n",stdout)
  447.           FLUSH;
  448.         ELSE
  449. #endif
  450. #ifdef TERSE
  451.         fputs("\nNot your article\n",stdout) FLUSH;
  452. #endif
  453.     else {
  454.     tmpfp = fopen(headname,"w");    /* open header file */
  455.     if (tmpfp == Nullfp) {
  456.         printf(cantcreate,headname) FLUSH;
  457.         goto no_cancel;
  458.     }
  459.     interp(buf, (sizeof buf), getval("CANCELHEADER",CANCELHEADER));
  460.     fputs(buf,tmpfp);
  461.     fclose(tmpfp);
  462.     fputs("\nCanceling...\n",stdout) FLUSH;
  463.     r = doshell(sh,filexp(getval("CANCEL",CANCEL)));
  464.     }
  465. no_cancel:
  466.     free(artid_buf);
  467.     free(ngs_buf);
  468.     free(from_buf);
  469.     free(reply_buf);
  470.     return r;
  471. }
  472.  
  473. void
  474. reply()
  475. {
  476.     bool incl_body = (*buf == 'R');
  477.     char *maildoer = savestr(filexp(getval("MAILPOSTER",MAILPOSTER)));
  478.  
  479.     artopen(art);
  480.     tmpfp = fopen(headname,"w");    /* open header file */
  481.     if (tmpfp == Nullfp) {
  482.     printf(cantcreate,headname) FLUSH;
  483.     goto no_reply;
  484.     }
  485.     interp(buf, (sizeof buf), getval("MAILHEADER",MAILHEADER));
  486.     fputs(buf,tmpfp);
  487.     if (!instr(maildoer,"%h"))
  488. #ifdef VERBOSE
  489.     IF(verbose)
  490.         printf("\n%s\n(Above lines saved in file %s)\n",buf,headname)
  491.           FLUSH;
  492.     ELSE
  493. #endif
  494. #ifdef TERSE
  495.         printf("\n%s\n(Header in %s)\n",buf,headname) FLUSH;
  496. #endif
  497.     if (incl_body && artfp != Nullfp) {
  498.     interp(buf, (sizeof buf), getval("YOUSAID",YOUSAID));
  499.     fprintf(tmpfp,"%s\n",buf);
  500. #ifdef ASYNC_PARSE
  501.     parse_maybe(art);
  502. #endif
  503.     fseek(artfp,(long)htype[PAST_HEADER].ht_minpos,0);
  504.     while (fgets(buf,LBUFLEN,artfp) != Nullch) {
  505.         fprintf(tmpfp,"%s%s",indstr,buf);
  506.     }
  507.     fprintf(tmpfp,"\n");
  508.     }
  509.     fclose(tmpfp);
  510.     interp(cmd_buf, (sizeof cmd_buf), maildoer);
  511.     invoke(cmd_buf,origdir);
  512.     UNLINK(headname);        /* kill the header file */
  513. no_reply:
  514.     free(maildoer);
  515. }
  516.  
  517. void
  518. followup()
  519. {
  520.     bool incl_body = (*buf == 'F');
  521.     char hbuf[4*LBUFLEN];    /* four times the old size */
  522.  
  523.     artopen(art);
  524.     tmpfp = fopen(headname,"w");
  525.     if (tmpfp == Nullfp) {
  526.     printf(cantcreate,headname) FLUSH;
  527.     return;
  528.     }
  529.     interp(hbuf, (sizeof hbuf), getval("NEWSHEADER",NEWSHEADER));
  530.     fprintf(tmpfp,"%s",hbuf);
  531.     if (incl_body && artfp != Nullfp) {
  532. #ifdef VERBOSE
  533.     if (verbose)
  534.         fputs("\n\
  535. (Be sure to double-check the attribution against the signature, and\n\
  536. trim the quoted article down as much as possible.)\n\
  537. ",stdout) FLUSH;
  538. #endif
  539.     interp(buf, (sizeof buf), getval("ATTRIBUTION",ATTRIBUTION));
  540.     fprintf(tmpfp,"%s\n",buf);
  541. #ifdef ASYNC_PARSE
  542.     parse_maybe(art);
  543. #endif
  544.     fseek(artfp,(long)htype[PAST_HEADER].ht_minpos,0);
  545.     while (fgets(buf,LBUFLEN,artfp) != Nullch) {
  546.         fprintf(tmpfp,"%s%s",indstr,buf);
  547.     }
  548.     fprintf(tmpfp,"\n");
  549.     }
  550.     fclose(tmpfp);
  551.     safecpy(cmd_buf,filexp(getval("NEWSPOSTER",NEWSPOSTER)),sizeof cmd_buf);
  552.     invoke(cmd_buf,origdir);
  553.     UNLINK(headname);
  554. }
  555.  
  556. void
  557. invoke(cmd,dir)
  558. char *cmd,*dir;
  559. {
  560.     if (chdir(dir)) {
  561.     printf(nocd,dir) FLUSH;
  562.     return;
  563.     }
  564. #ifdef VERBOSE
  565.     IF(verbose)
  566.     printf("\n(leaving cbreak mode; cwd=%s)\nInvoking command: %s\n\n",
  567.         dir,cmd) FLUSH;
  568.     ELSE
  569. #endif
  570. #ifdef TERSE
  571.     printf("\n(-cbreak; cwd=%s)\nInvoking: %s\n\n",dir,cmd) FLUSH;
  572. #endif
  573.     resetty();            /* make terminal well-behaved */
  574.     doshell(sh,cmd);        /* do the command */
  575.     noecho();            /* set no echo */
  576.     crmode();            /* and cbreak mode */
  577. #ifdef VERBOSE
  578.     IF(verbose)
  579.     fputs("\n(re-entering cbreak mode)\n",stdout) FLUSH;
  580.     ELSE
  581. #endif
  582. #ifdef TERSE
  583.     fputs("\n(+cbreak)\n",stdout) FLUSH;
  584. #endif
  585. #ifdef SERVER
  586.     if (chdir(spool)) {
  587. #else /* not SERVER */
  588.     if (chdir(spool) || chdir(ngdir)) {
  589. #endif /* SERVER */
  590.     printf(nocd,ngdir) FLUSH;
  591.     sig_catcher(0);
  592.     }
  593. }
  594.  
  595. /*
  596. ** cut_line() determines if a line is meant as a "cut here" marker.
  597. ** Some examples that we understand:
  598. **
  599. **  BEGIN--cut here--cut here
  600. **
  601. **  ------------------ tear at this line ------------------
  602. **
  603. **  #----cut here-----cut here-----cut here-----cut here----#
  604. */
  605. bool
  606. cut_line(str)
  607. char *str;
  608. {
  609.     char *cp, got_flag;
  610.     char word[80];
  611.     int  dash_cnt, equal_cnt;
  612.  
  613.     /* Disallow any single-/double-quoted, parenthetical or c-commented
  614.     ** string lines.  Make sure it has the cut-phrase and at least 20
  615.     ** '-'s or '='s.  If only four '-'s are present, check for a duplicate
  616.     ** of the cut phrase.  If we succeed, return TRUE.
  617.     */
  618.     for (cp = str, dash_cnt = equal_cnt = 0; *cp; cp++) {
  619.     switch (*cp) {
  620.     case '-':
  621.         dash_cnt++;
  622.         break;
  623.     case '=':
  624.         equal_cnt++;
  625.         break;
  626.     case '/':
  627.         if( *(cp+1) != '*' ) {
  628.         break;
  629.         }
  630.     case '"':
  631.     case '\'':
  632.     case '(':
  633.     case ')':
  634.     case '[':
  635.     case ']':
  636.     case '{':
  637.     case '}':
  638.         return FALSE;
  639.     }
  640.     }
  641.     if (dash_cnt < 4 && equal_cnt < 20)
  642.     return FALSE;
  643.  
  644.     got_flag = 0;
  645.  
  646.     for (*(cp = word) = '\0'; *str; str++) {
  647.     if (islower(*str))
  648.         *cp++ = *str;
  649.     else if (isupper(*str))
  650.         *cp++ = tolower(*str);
  651.     else {
  652.         if (*word) {
  653.         *cp = '\0';
  654.         switch (got_flag) {
  655.         case 2:
  656.             if (!strcmp(word, "line")
  657.              || !strcmp(word, "here"))
  658.             return TRUE;
  659.             break;
  660.         case 1:
  661.             if (!strcmp(word, "this"))
  662.             got_flag = 2;
  663.             if (!strcmp(word, "here")) {
  664.             if (dash_cnt >= 20 || equal_cnt >= 20)
  665.                 return TRUE;
  666.             dash_cnt = 20;
  667.             got_flag = 0;
  668.             }
  669.             break;
  670.         case 0:
  671.             if (!strcmp( word, "cut")
  672.              || !strcmp( word, "snip")
  673.              || !strcmp( word, "tear"))
  674.             got_flag = 1;
  675.             break;
  676.         }
  677.         *(cp = word) = '\0';
  678.         }
  679.     }
  680.     } /* for *str */
  681.  
  682.     return FALSE;
  683. }
  684.