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