home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / vsoup128.zip / ownsoup.cc < prev    next >
C/C++ Source or Header  |  1997-01-19  |  8KB  |  294 lines

  1. //  $Id: ownsoup.cc 1.5 1997/01/19 10:35:55 hardy Exp $
  2. //
  3. //  This progam/module was written by Hardy Griech based on ideas and
  4. //  pieces of code from Chin Huang (cthuang@io.org).  Bug reports should
  5. //  be submitted to rgriech@ibm.net.
  6. //
  7. //  This file is part of soup++ for OS/2.  Soup++ including this file
  8. //  is freeware.  There is no warranty of any kind implied.  The terms
  9. //  of the GNU Gernal Public Licence are valid for this piece of software.
  10. //
  11. //
  12. //  Get the messages with a specific pattern in them and put them into a specific
  13. //  newsgroup.
  14. //
  15. //  input:       areas, *.msg
  16. //  output:      modified areas, *.msg, extra .msg
  17. //  parameters:  <pattern> <groupname> <outfile>
  18. //
  19. //  - the input *.msg must be in binary newsgroup format ("B") or USENET format ("u")
  20. //  - matching articles are appended to <outfile> in binary mail format "bn"
  21. //  - the first line of the found article will be "X-ownsoup: <groupname>"
  22. //  - if outfile is found in areas, it is not scanned again...
  23. //  - .MSG is added to outfile
  24. //  - upper/lower case is ignored
  25. //  - 'u' files are read in text mode, 'B' files in binary
  26. //
  27. //  To catch the articles you have to setup a filter, which matches
  28. //  the "X-ownsoup" header
  29. //
  30.  
  31.  
  32.  
  33. #include <getopt.h>
  34. #include <regexp.h>
  35. #include <stdio.h>
  36. #include <stdlib.h>
  37. #include <string.h>
  38. #include <sys/nls.h>
  39.  
  40.  
  41.  
  42. #define AREAS     "./areas"
  43. #define MSGEXT    ".msg"
  44. #define XHEADER   "X-ownsoup: "
  45.  
  46.  
  47.  
  48. static const char *progname;
  49. static const char *outName;
  50. static const char *groupName;
  51. static FILE *outF = NULL;
  52.  
  53. static int scanHeader  = 1;
  54. static int scanBody    = 1;
  55. static int shutUp      = 0;
  56. static int somethingScanned = 0;
  57.  
  58.  
  59.  
  60. static int scanArticle( FILE *msgF, long msgLen, const regexp *pattern )
  61. {
  62.     long startpos = ftell(msgF);
  63.     long endpos = startpos + msgLen;
  64.     char line[BUFSIZ];
  65.     int  match;
  66.     long len;
  67.     int  inHeader = 1;
  68.  
  69.     somethingScanned = 1;
  70.     match = 0;
  71.     len = msgLen;
  72.     while (len > 0) {
  73.     if (fgets( line,sizeof(line),msgF ) == NULL)
  74.         break;
  75.     len -= strlen(line);
  76.  
  77.     if (*line == '\n')
  78.         inHeader = 0;
  79.  
  80.     if ((inHeader && scanHeader)  ||  (!inHeader && scanBody)  ||
  81.         (inHeader && scanBody && strncmp(line,"Subject",7) == 0)) {
  82.         _nls_strlwr( (unsigned char *)line );
  83.         match = regexec( pattern,line );
  84.         if (match)
  85.         break;
  86.     }
  87.     }
  88.  
  89.     if (match) {
  90.     unsigned char len1[4];
  91.     char name[BUFSIZ];
  92.  
  93.     if (outF == NULL) {
  94.         sprintf( name,"%s%s",outName,MSGEXT );
  95.         outF = fopen( name,"ab" );     // append!
  96.     }
  97.     sprintf( name,"%s%s\n",XHEADER,groupName );
  98.  
  99.     len = msgLen + strlen(name );
  100.     len1[3] = (len >>  0) & 0xff;
  101.     len1[2] = (len >>  8) & 0xff;
  102.     len1[1] = (len >> 16) & 0xff;
  103.     len1[0] = (len >> 24) & 0xff;
  104.     fwrite( len1,sizeof(len1),1, outF );
  105.     fputs( name,outF );
  106.  
  107.     fseek( msgF,startpos,SEEK_SET );
  108.     while (msgLen > 0) {
  109.         char buf[4096];
  110.         size_t get;
  111.  
  112.         get = ((unsigned)msgLen > sizeof(buf)) ? sizeof(buf) : msgLen;
  113.         if (fread(buf,1,get,msgF) != get) {
  114.         perror( "fread" );
  115.         exit( EXIT_FAILURE );
  116.         }
  117.         if (fwrite(buf,1,get,outF) != get) {
  118.         perror( "fwrite" );
  119.         exit( EXIT_FAILURE );
  120.         }
  121.         msgLen -= get;
  122.     }
  123.     }
  124.     
  125.     fseek( msgF, endpos,SEEK_SET );
  126.     return match;
  127. }   // scanArticle
  128.  
  129.  
  130.  
  131. static void usage( void )
  132. {
  133.     printf( "\n%s v0.26 (rg190197)\n\tgenerate mail file from news according to <regexp>\n\n", progname );
  134.     printf( "usage:  %s [OPTION] <regexp> <groupname> <outputfile>\n",progname );
  135.     printf( "  -b   scan article body only (subject is part of body)\n" );
  136.     printf( "  -h   scan article header\n" );
  137.     printf( "  -q   be (almost) quiet\n" );
  138.     exit( EXIT_FAILURE );
  139. }   // usage
  140.  
  141.  
  142.  
  143. int main( int argc, char *argv[] )
  144. //
  145. //  principal algo
  146. //  - get command line parameters
  147. //  - open areas file
  148. //  - while not eof(areas)
  149. //  -    read line, identify type, filename
  150. //  -    if type ok, open file
  151. //  -       for each article in file, search for pattern
  152. //  -       if pattern contained, write article to output
  153. //  -    end if
  154. //  - end while
  155. //  - if there was an output article, then file to areas
  156. //
  157. //  Questions:  is it required to change the msgId? (hopefully not...)
  158. //
  159. {
  160.     char buf[BUFSIZ];
  161.     FILE *areasF, *msgF;
  162.     char fname[BUFSIZ], gname[BUFSIZ], stype[BUFSIZ];
  163.     char mname[BUFSIZ];
  164.     unsigned char len1[4];
  165.     long msgLen;
  166.     regexp *pattern;
  167.     int matches = 0;
  168.     int totmatch = 0;
  169.     int outfilefound = 0;
  170.     int c;
  171.  
  172.     progname = strrchr(argv[0], '\\');
  173.     if (progname == NULL)
  174.     progname = argv[0];
  175.     else
  176.     ++progname;
  177.  
  178.     while ((c = getopt(argc, argv, "?bhq")) != EOF) {
  179.             switch (c) {
  180.         case '?':
  181.             usage();
  182.             break;
  183.         case 'q':
  184.             shutUp = 1;
  185.             break;
  186.         case 'h':
  187.             scanHeader  = 1;
  188.             scanBody    = 0;
  189.             break;
  190.         case 'b':
  191.             scanBody    = 1;
  192.             scanHeader  = 0;
  193.             break;
  194.         default:
  195.             printf( "%s: ill option -%c\n", progname,c );
  196.             usage();
  197.             break;
  198.         }
  199.     }
  200.         
  201.     if (argc-optind != 3) {
  202.     printf( "%s: not enough parameters %d %d\n",progname,optind, argc );
  203.     usage();
  204.     }
  205.  
  206.     _nls_strlwr( (unsigned char *)argv[optind] );              // is this legal??
  207.     pattern = regcomp( argv[optind] );
  208.     groupName = argv[optind+1];
  209.     outName = argv[optind+2];
  210.     
  211.     areasF = fopen( AREAS,"rt" );
  212.     if (areasF == NULL) {
  213.     printf( "%s: %s not found\n", progname, AREAS );
  214.     exit( EXIT_FAILURE );
  215.     }
  216.  
  217.     while (fgets(buf,sizeof(buf),areasF) != NULL) {
  218.     matches = 0;
  219.     *fname = *gname = *stype = '\0';
  220.     sscanf( buf,"%[^\t]\t%[^\t]\t%[^\t]%*s", fname,gname,stype );
  221.     if (stricmp(fname,outName) == 0) {
  222.         if ( !shutUp)
  223.         printf( "%s: %s%s skipped\n", progname,fname,MSGEXT );
  224.         outfilefound = 1;
  225.     }
  226.     else if (*stype == 'B') {
  227.         if ( !shutUp)
  228.         printf( "%s: %s in %s%s binary news format\n", progname, gname, fname, MSGEXT );
  229.         sprintf( mname,"%s%s", fname,MSGEXT );
  230.         msgF = fopen( mname,"rb" );
  231.         if (msgF != NULL) {
  232.         while (fread(len1, sizeof(len1),1, msgF) == 1) {
  233.             msgLen = (len1[0] << 24) +
  234.             (len1[1] << 16) +
  235.             (len1[2] <<  8) +
  236.             (len1[3] <<  0);
  237.             if (scanArticle( msgF,msgLen,pattern ))
  238.             ++matches;
  239.         }
  240.         fclose( msgF );
  241.         }
  242.     }
  243.     else if (*stype == 'u') {
  244.         if ( !shutUp)
  245.         printf( "%s: %s in %s%s USENET news format\n", progname, gname, fname, MSGEXT );
  246.         sprintf( mname,"%s%s", fname,MSGEXT );
  247.         msgF = fopen( mname,"rt" );
  248.         if (msgF != NULL) {
  249.         char line[100];
  250.         while (fgets(line,sizeof(line),msgF) != NULL) {
  251.             sscanf( line,"%*s%ld",&msgLen );
  252.             if (scanArticle( msgF,msgLen,pattern ))
  253.             ++matches;
  254.         }
  255.         fclose( msgF );
  256.         }
  257.     }
  258.     if (matches != 0) {
  259.         if ( !shutUp)
  260.         printf( "%s: %d matches\n", progname,matches );
  261.         totmatch += matches;
  262.     }
  263.     }
  264.     fclose( areasF );
  265.     
  266.     if (outF != NULL  &&  !outfilefound) {
  267.     if ( !shutUp)
  268.         printf( "%s: %s%s created\n",progname,outName,MSGEXT );
  269.  
  270.     areasF = fopen( AREAS,"ab" );
  271.     fprintf( areasF,"%s\t%s\tbn\n", outName,groupName );
  272.     fclose( areasF );
  273.     }
  274.     {
  275.     char type[100];
  276.  
  277.     strcpy( type,"" );
  278.     if (scanHeader)
  279.         strcat( type,"header" );
  280.     if (scanBody) {
  281.         if (*type != '\0')
  282.         strcat( type,"/" );
  283.         strcat( type,"body&subject" );
  284.     }
  285.     if (somethingScanned  ||  !shutUp)
  286.         printf( "%s: %d match%s of \"%s\" found in %s\n",progname,totmatch,
  287.             (totmatch != 1) ? "es" : "", argv[optind], type );
  288.     }
  289.     if ( !shutUp)
  290.     printf( "%s: setup filter for \"%s%s\"\n", progname,XHEADER,groupName );
  291.  
  292.     exit( EXIT_SUCCESS );
  293. }   // main
  294.