home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / UUPC11XT.ZIP / UTIL / GENSIG.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-14  |  21.2 KB  |  562 lines

  1. /*--------------------------------------------------------------------*/
  2. /*       Program:    gensig.c             24 July 1991                */
  3. /*       Author:     Andrew H. Derbyshire                             */
  4. /*       Address:    ahd@kew.com                                      */
  5. /*       Function:   Append a random quote to an electronic           */
  6. /*                   mail signature file                              */
  7. /*       Language:   Borland C++ 2.0 (in ANSI C mode)                 */
  8. /*       Arguments:  Name of file with fixed text input               */
  9. /*                   Name of file with variable quotes                */
  10. /*                   Name of file to be written                       */
  11. /*--------------------------------------------------------------------*/
  12.  
  13. /*--------------------------------------------------------------------*/
  14. /*                          RCS Information                           */
  15. /*--------------------------------------------------------------------*/
  16.  
  17. /*
  18.  *    $Header: E:\SRC\UUPC\UTIL\RCS\GENSIG.C 1.1 1992/11/15 04:29:22 ahd Exp $
  19.  *
  20.  *    Revision history:
  21.  *    $Log: GENSIG.C $
  22.  * Revision 1.1  1992/11/15  04:29:22  ahd
  23.  * Initial revision
  24.  *
  25.  */
  26.  
  27. static char rcsid[] = "$Id: GENSIG.C 1.1 1992/11/15 04:29:22 ahd Exp $";
  28.  
  29. /*--------------------------------------------------------------------*/
  30. /*                       Standard include files                       */
  31. /*--------------------------------------------------------------------*/
  32.  
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <io.h>
  36. #include <direct.h>
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #include <string.h>
  40. #include <time.h>
  41.  
  42. /*--------------------------------------------------------------------*/
  43. /*                    UUPC/extended include files                     */
  44. /*--------------------------------------------------------------------*/
  45.  
  46. #include "lib.h"
  47. #include "timestmp.h"
  48.  
  49. /*--------------------------------------------------------------------*/
  50. /*                            Local macros                            */
  51. /*--------------------------------------------------------------------*/
  52.  
  53. #define bitsper(s) (8 * (sizeof s))
  54.  
  55. #define bitflag(x, s) (1 << ((bitsper(s) - 1) - x))
  56.  
  57. #define biton( s, offset ) \
  58.                (( s[ (size_t) (offset / bitsper(*s)) ] ) & \
  59.                 bitflag(offset % bitsper( *s ), *s))
  60.  
  61. #define bitoff( s, offset) (!biton(s, offset))
  62.  
  63. /*--------------------------------------------------------------------*/
  64. /*                    Internal function prototypes                    */
  65. /*--------------------------------------------------------------------*/
  66.  
  67. static void usage( void );
  68.  
  69. static long chooseit( struct stat *current_status,
  70.        const char *lookaside,
  71.                  const char *quoteused,
  72.                  const char *fname );
  73.  
  74. static long getquote( const char *data);
  75.  
  76. static void CopyQuote( const char *fname, long where, FILE *stream);
  77.  
  78. static void CopyFixed( const char *fname, FILE *stream );
  79.  
  80. static long chooseavailable( const char *quoteused, long quotes );
  81.  
  82. currentfile();
  83.  
  84. /*--------------------------------------------------------------------*/
  85. /*    m a i n                                                         */
  86. /*                                                                    */
  87. /*    main program                                                    */
  88. /*--------------------------------------------------------------------*/
  89.  
  90. void main( int argc, char **argv)
  91. {
  92.  
  93.    long where;
  94.    FILE *stream;
  95.  
  96.    banner( argv );
  97.  
  98. /*--------------------------------------------------------------------*/
  99. /*                  Validate the number of arguments                  */
  100. /*--------------------------------------------------------------------*/
  101.  
  102.       if ( argc !=  4 )
  103.          usage();
  104.  
  105. /*--------------------------------------------------------------------*/
  106. /*    Determine the number of the quotes available, and then          */
  107. /*    select one                                                      */
  108. /*--------------------------------------------------------------------*/
  109.  
  110.       where = getquote( argv[2] );
  111.  
  112. /*--------------------------------------------------------------------*/
  113. /*                      Open up our output file                       */
  114. /*--------------------------------------------------------------------*/
  115.  
  116.       stream = fopen( argv[3] , "w");
  117.       if ( stream == NULL )
  118.       {
  119.          perror( argv[3] );
  120.          exit(1);
  121.       }
  122.  
  123. /*--------------------------------------------------------------------*/
  124. /*           Copy the fixed and variable parts of the file            */
  125. /*--------------------------------------------------------------------*/
  126.  
  127.       CopyFixed( argv[1], stream );
  128.       CopyQuote( argv[2], where, stream );
  129.  
  130. /*--------------------------------------------------------------------*/
  131. /*                   Close up and return to caller                    */
  132. /*--------------------------------------------------------------------*/
  133.  
  134.       fclose( stream );
  135.       exit( 0 );
  136.  
  137. } /* main */
  138.  
  139. /*--------------------------------------------------------------------*/
  140. /*    u s a g e                                                       */
  141. /*                                                                    */
  142. /*    Report program usage and then exit                              */
  143. /*--------------------------------------------------------------------*/
  144.  
  145. static void usage( void )
  146. {
  147.    printf("Usage:\tgensig\taddr-file quote-file output-file\n");
  148.    printf("\taddr-file\tFixed portion of signature file\n");
  149.    printf("\tquote-file\tFile of quotes, separated by delimiter lines\n");
  150.    printf("\toutput-file\tOutput file with fixed portion and single quote\n");
  151.    exit( 2 );
  152. } /* usage */
  153.  
  154. /*--------------------------------------------------------------------*/
  155. /*    g e t q u o t e                                                 */
  156. /*                                                                    */
  157. /*    Select a quote to process                                       */
  158. /*--------------------------------------------------------------------*/
  159.  
  160. static long getquote( const char *data)
  161. {
  162.    struct stat current_status;
  163.    long where;
  164.  
  165.    char lookaside[FILENAME_MAX];
  166.    char quoteused[FILENAME_MAX];
  167.    char drive[FILENAME_MAX], dir[FILENAME_MAX], file[FILENAME_MAX], ext[FILENAME_MAX];
  168.  
  169. /*--------------------------------------------------------------------*/
  170. /*       Get size and data information on the quotes data file        */
  171. /*--------------------------------------------------------------------*/
  172.  
  173.    if(stat((char *) data, ¤t_status ) <0)
  174.    {
  175.       perror( data );         /* If no data file, panic gracefully   */
  176.       exit( 3 );
  177.    } /* if */
  178.  
  179. /*--------------------------------------------------------------------*/
  180. /*       Build the lookaside file name from the data file name        */
  181. /*--------------------------------------------------------------------*/
  182.  
  183. #ifdef __TURBOC__
  184.    fnsplit( data, drive, dir, file, ext);
  185.    fnmerge( lookaside, drive, dir, file, ".las");
  186.    fnmerge( quoteused, drive, dir, file, ".qus");
  187. #else
  188.    _splitpath( data, drive, dir, file, ext);
  189.    _makepath( lookaside, drive, dir, file, ".las");
  190.    _makepath( quoteused, drive, dir, file, ".qus");
  191. #endif /* __TURBOC__ */
  192.  
  193. /*--------------------------------------------------------------------*/
  194. /*    Now get the location of the quote; if it fails the first        */
  195. /*    time, then the lookaside buffer is updated and we can try       */
  196. /*    again                                                           */
  197. /*--------------------------------------------------------------------*/
  198.  
  199.    where = chooseit( ¤t_status, lookaside, quoteused, data );
  200.    if  (where == -1 )
  201.    {
  202.       where = chooseit( ¤t_status, lookaside, quoteused, data );
  203.       if ( where == - 1)
  204.       {
  205.          printf("Unable to create lookaside file \"%s\"!\n",
  206.                   lookaside );
  207.          exit( 4 );
  208.       } /* if ( where == - 1) */
  209.    } /* if ( where == - 1) */
  210.  
  211. /*--------------------------------------------------------------------*/
  212. /*                          Return to caller                          */
  213. /*--------------------------------------------------------------------*/
  214.  
  215.    return where;
  216.  
  217. } /* getquote */
  218.  
  219. /*--------------------------------------------------------------------*/
  220. /*    c h o o s e i t                                                 */
  221. /*                                                                    */
  222. /*    Returns number of quotes in file                                */
  223. /*--------------------------------------------------------------------*/
  224.  
  225. static long chooseit( struct stat *current_status,
  226.                  const char *lookaside,
  227.                  const char *quoteused,
  228.                  const char *fname )
  229. {
  230.    FILE *stream;
  231.    FILE *data;
  232.    long where;
  233.    long quotes = 0;
  234.    long quote;
  235.  
  236.    char buf[BUFSIZ];
  237.    char delimiter[BUFSIZ];
  238.  
  239. /*--------------------------------------------------------------------*/
  240. /*    Open up the lookaside file and determine if it is up to         */
  241. /*    date.  If so, choose an entry and return it.                    */
  242. /*--------------------------------------------------------------------*/
  243.  
  244.    stream = fopen( lookaside , "rb" );
  245.    if ( stream != NULL )
  246.    {
  247.       struct stat status;
  248.       fread( &status, sizeof status, 1, stream);
  249.       if ((status.st_size == current_status->st_size) &&
  250.           (status.st_mtime == current_status->st_mtime))
  251.       {                       /* Lookaside file up to date, use it   */
  252.          if( stat((char *) lookaside, &status ) < 0)
  253.          {
  254.             perror( lookaside );
  255.             exit( 5 );
  256.          } /* if */
  257.  
  258.          quotes = (status.st_size - sizeof status) / sizeof where;
  259.                               /* Determine number of quote pointers
  260.                                  in lookaside file from the file's
  261.                                  length                              */
  262.  
  263.          quote = chooseavailable( quoteused, quotes);
  264.  
  265.          fseek( stream, quote * sizeof where , SEEK_CUR );
  266.                               /* Step required number of quotes
  267.                                  into the file                       */
  268.          fread( &where, sizeof where, 1, stream);
  269.                               /* Read offset in data file of quote   */
  270.          printf("Chose quote %ld of %ld starting at byte %ld of file %s:\n\n",
  271.                   quote + 1 , quotes, where, fname);
  272.                               /* Announce number of quote of the day */
  273.          fclose( stream );    /* Done with lookaside file, of course */
  274.          return where;        /* Return position in file to caller   */
  275.       } /* if */
  276.       else
  277.          fclose( stream );
  278.    } /* if ( stream != NULL ) */
  279.    else
  280.       perror( lookaside );
  281.  
  282. /*--------------------------------------------------------------------*/
  283. /*               We have to rewrite the lookaside file                */
  284. /*--------------------------------------------------------------------*/
  285.  
  286.    unlink( quoteused );          /* Make all quotes available        */
  287.  
  288.    data   = fopen( fname, "rt");          /* Open data file to scan  */
  289.    if ( data == NULL )                    /* Did it open?            */
  290.    {
  291.       perror( fname );                    /* No --> Error            */
  292.       exit( 6 );
  293.    }
  294.  
  295.    stream = fopen( lookaside , "wb" );    /* Open lookaside file     */
  296.    if ( stream == NULL )                  /* Did it open?            */
  297.    {
  298.       perror( lookaside );                /* No --> Error            */
  299.       exit( 7 );
  300.    }
  301.  
  302. /*--------------------------------------------------------------------*/
  303. /*    Start the new lookaside file with the status of the data        */
  304. /*    file for later comparisons                                      */
  305. /*--------------------------------------------------------------------*/
  306.  
  307.    fwrite( current_status, sizeof *current_status, 1, stream);
  308.  
  309. /*--------------------------------------------------------------------*/
  310. /*    Get the first line of the file, which will contain the          */
  311. /*    delimiter line                                                  */
  312. /*--------------------------------------------------------------------*/
  313.  
  314.    fgets(delimiter, BUFSIZ, data );
  315.    where = ftell( data );  /* Get location of possible first quote   */
  316.  
  317. /*--------------------------------------------------------------------*/
  318. /*                  Now process the rest of the file                  */
  319. /*--------------------------------------------------------------------*/
  320.  
  321.    while( fgets(buf, BUFSIZ, data ) != NULL )
  322.    {
  323.       if ( strcmp( buf, delimiter ))   /* Delimiter line?            */
  324.       {                                /* No --> data line           */
  325.          if ( where != -1L )  /* First line of new quote?            */
  326.          {                    /* Yes --> Write location to lookaside */
  327.             quotes ++ ;
  328.             fwrite( &where, sizeof where, 1, stream);
  329.             where = -1L;
  330.          } /* if */
  331.       } /* if */
  332.       else
  333.          where = ftell( data );        /* Delimiter line, remember
  334.                                           location of NEXT line in
  335.                                           file                       */
  336.    } /* while */
  337.  
  338. /*--------------------------------------------------------------------*/
  339. /*                 Close up shop and return to caller                 */
  340. /*--------------------------------------------------------------------*/
  341.  
  342.    fclose( stream );
  343.    fclose( data );
  344.  
  345.    if ( quotes == 1 )
  346.    {
  347.       printf("Invalid data file; first line not a delimiter line!");
  348.       exit( 99 );
  349.    }
  350.  
  351.    printf("Updated lookaside file %s with %d quotes.\n",
  352.                lookaside , quotes);
  353.  
  354.    return -1;                 /* Inform caller that lookaside
  355.                                  file was updated                    */
  356. } /* chooseit */
  357.  
  358. /*--------------------------------------------------------------------*/
  359. /*    c h o o s e a v a i l a b l e                                   */
  360. /*                                                                    */
  361. /*    Select a quote from available list                              */
  362. /*--------------------------------------------------------------------*/
  363.  
  364. static long chooseavailable( const char *quoteused, long quotes )
  365. {
  366.    FILE *stream;
  367.    unsigned char *quotelist;
  368.  
  369.    size_t listsize = (size_t) (( quotes + bitsper(*quotelist) - 1 ) /
  370.                               bitsper(*quotelist));
  371.    long quote;
  372.    long available = quotes;
  373.    long select;
  374.  
  375. /*--------------------------------------------------------------------*/
  376. /*                 Initialize the bit array of quotes                 */
  377. /*--------------------------------------------------------------------*/
  378.  
  379.    quotelist = malloc( listsize );
  380.    checkref( quotelist );
  381.  
  382. /*--------------------------------------------------------------------*/
  383. /*             Open up the used quoted file, if possible              */
  384. /*--------------------------------------------------------------------*/
  385.  
  386.    stream = fopen( quoteused, "rb");
  387.  
  388. /*--------------------------------------------------------------------*/
  389. /*              Determine the number of available quotes              */
  390. /*--------------------------------------------------------------------*/
  391.  
  392.    if ( stream != NULL )
  393.    {
  394.  
  395.       if (fread (&available, sizeof available, 1 , stream) < 1 )
  396.       {
  397.          perror(  quoteused );
  398.          available = 0;
  399.       }
  400.       else if ( quotes <= available )
  401.          available = 0;
  402.       else if (fread (quotelist, sizeof *quotelist, listsize , stream) <
  403.                   listsize)
  404.       {
  405.          available = 0;
  406.          perror( quoteused );
  407.       }
  408.  
  409.       fclose( stream );
  410.    } /* if */
  411.    else
  412.       available = 0;
  413.  
  414.    if ( available <= ( quotes / 10 ))
  415.    {
  416.       memset( quotelist, '\0', listsize );
  417.       printf("Resetting available quotes list\n");
  418.       available = quotes;
  419.    }
  420.  
  421. /*--------------------------------------------------------------------*/
  422. /*                       Now, choose the quote                        */
  423. /*--------------------------------------------------------------------*/
  424.  
  425.    srand ( time( NULL ));     /* Initialize the generator      */
  426.    select = rand() % available ;
  427.                         /* ... Lucky seven?                    */
  428.  
  429. /*--------------------------------------------------------------------*/
  430. /*                         end debugging info                         */
  431. /*--------------------------------------------------------------------*/
  432.  
  433.    quote = 0;
  434.    while( quote < quotes )
  435.    {
  436.       if ( bitoff( quotelist, quote ))
  437.          select--;
  438.  
  439.       if ( select > 0 )
  440.          quote++;
  441.       else
  442.          break;
  443.    }
  444.  
  445.    if ( quote == quotes )           /* Did we overflow the array?    */
  446.       panic();                      /* Must have a bug!              */
  447.  
  448. /*--------------------------------------------------------------------*/
  449. /*                Now update our data and write it out                */
  450. /*--------------------------------------------------------------------*/
  451.  
  452.    stream = fopen( quoteused, "wb");
  453.    if ( stream == NULL )
  454.    {
  455.       perror( quoteused );
  456.       panic();
  457.    }
  458.  
  459.    quotelist[ (size_t) (quote / bitsper(*quotelist)) ] |=
  460.                bitflag( quote % bitsper(*quotelist), *quotelist );
  461.  
  462.    available -= 1;
  463.  
  464.    fwrite(&available, sizeof available, 1 , stream);
  465.    fwrite(quotelist,  sizeof *quotelist, listsize , stream);
  466.    fclose( stream );
  467.  
  468. /*--------------------------------------------------------------------*/
  469. /*                   Return the quote to the caller                   */
  470. /*--------------------------------------------------------------------*/
  471.  
  472.    return quote;
  473.  
  474. } /* chooseavailable */
  475.  
  476. /*--------------------------------------------------------------------*/
  477. /*    C o p y F i x e d                                               */
  478. /*                                                                    */
  479. /*    Copy fixed input text (user name and address) to output file    */
  480. /*--------------------------------------------------------------------*/
  481.  
  482. static void CopyFixed( const char *fname, FILE *stream )
  483. {
  484.    FILE *input;
  485.    char buf[BUFSIZ];
  486.  
  487. /*--------------------------------------------------------------------*/
  488. /*                    Open input file for copying                     */
  489. /*--------------------------------------------------------------------*/
  490.  
  491.    input = fopen( fname, "r");
  492.    if ( input == NULL )
  493.    {
  494.       perror( fname );
  495.       exit ( 8 );
  496.    }
  497.  
  498. /*--------------------------------------------------------------------*/
  499. /*             Copy the fixed input to the signature file             */
  500. /*--------------------------------------------------------------------*/
  501.  
  502.    while( fgets( buf, BUFSIZ, input ) != NULL)
  503.       fputs( buf, stream );
  504.  
  505. /*--------------------------------------------------------------------*/
  506. /*                 Close up shop and return to caller                 */
  507. /*--------------------------------------------------------------------*/
  508.  
  509.    fclose( input );
  510.  
  511. } /* CopyFixed */
  512.  
  513. /*--------------------------------------------------------------------*/
  514. /*    C o p y Q u o t e                                               */
  515. /*                                                                    */
  516. /*    Write a quote to the output file                                */
  517. /*--------------------------------------------------------------------*/
  518.  
  519. static void CopyQuote( const char *fname, long where, FILE *stream)
  520. {
  521.    FILE *input;
  522.    char buf[BUFSIZ];
  523.    char delimiter[BUFSIZ];
  524.  
  525. /*--------------------------------------------------------------------*/
  526. /*         Open up the quotes file and get the delimiter line         */
  527. /*--------------------------------------------------------------------*/
  528.  
  529.    input = fopen( fname, "r");
  530.    if ( input == NULL )
  531.    {
  532.       perror( fname );
  533.       exit ( 9 );
  534.    }
  535.  
  536.    fgets(delimiter, BUFSIZ, input );
  537.  
  538. /*--------------------------------------------------------------------*/
  539. /*   Position to the beginning of the actual quote to be processed    */
  540. /*--------------------------------------------------------------------*/
  541.  
  542.    fseek( input, where , SEEK_SET );
  543.  
  544. /*--------------------------------------------------------------------*/
  545. /*      Copy the quote to both the signature file and the screen      */
  546. /*--------------------------------------------------------------------*/
  547.  
  548.    while( fgets( buf, BUFSIZ, input ) != NULL)
  549.    {
  550.       if (!strcmp( delimiter, buf ))   /* Delimiter line?            */
  551.          break;                        /* Yes --> End of quote       */
  552.       fputs( buf, stream );   /* Copy quote to signature file        */
  553.       fputs( buf, stdout );   /* Copy quote to screen                */
  554.    } /* while( fgets( buf, BUFSIZ, input ) != NULL) */
  555.  
  556. /*--------------------------------------------------------------------*/
  557. /*                 Close up shop and return to caller                 */
  558. /*--------------------------------------------------------------------*/
  559.  
  560.    fclose( input );
  561. } /* CopyQuote */
  562.