/* * shsinfo - Extracts the SHS info from a text file * * Created by: Jack C Lipton (see http://www.asstr.org/~CupaSoup/ * * Some notes: * * Source code copied from fmtr and then mangled until no good. * * * * =========================================================================== * * Portability: * This program should be relatively easy to port to any * system that handles the file namespace in a reasonably * Unix-like way. * * =========================================================================== * * $Id: $ * * $Author: $ * * $Log: $ * * =========================================================================== * */ #include #include #include #include #define INBUFSIZE 4096 /* * SHS Formats for publication * * |Author: * |Title: * |Part: * |Universe: * |Summary: * |Keywords: * |Revision: $Revision: 1.9 $ * |Archive: * |Mailing List: * |FAQ: * |RCS: $Id: fmtr.c,v 1.9 2003/08/11 22:58:54 jcl Exp jcl $ * */ char shs_authorname[1024]; char shs_title[1024]; char shs_part[1024]; char shs_universe[1024]; char shs_summary[4096]; char shs_keywords[1024]; char shs_revision[1024]; char shs_archive[1024]; char shs_mailinglist[1024]; char shs_faq[1024]; char shs_rcs[1024]; /* * Here's the structure I use to map the tag names and point to * the buffers, above; This makes the logic to fill the buffers * that much easier. * * Yes, this is awkward and I might have been able to do better. */ struct MapItems { char *label; /* label part of SHS line */ int lablen, /* length of label to check */ buflen; /* length of the buffer */ char *buffer; /* pointer to buffer */ }; struct MapItems shsInfo[] = { { "Author:", 7, 1024, shs_authorname }, { "Title:", 6, 1024, shs_title }, { "Part:", 5, 1024, shs_part }, { "Universe:", 9, 1024, shs_universe }, { "Summary:", 8, 4096, shs_summary }, { "Keywords:", 9, 1024, shs_keywords }, { "Revision:", 9, 1024, shs_revision }, { "Archive:", 8, 1024, shs_archive }, { "Mailing List:", 13, 1024, shs_mailinglist }, { "FAQ:", 4, 1024, shs_faq }, { "RCS:", 4, 1024, shs_rcs }, { NULL, 0, 0, NULL } }; /* * Some things really want to have function prototypes to shut * up all of the warning messages I keep getting... */ extern char *basename( char *); extern char *strchr( char *, char); extern char *strrchr( char *, char); extern char *dirname( char *); /* * Here are the function prototypes so that all forward references * won't bitch and moan about function typing... */ int procSHS( FILE *); /* read in SHS heading part */ main( argc, argv, envp) /* formatter utility */ int argc; char *argv[]; char *envp[]; { int a; /* arglist index */ unsigned long age, /* age of file in seconds */ fmt, /* timestamp of file */ now; /* timestamp of this run */ struct stat f_stat; char textpath[1024], /* path name of input file */ corename[512]; /* name w/o dirs or ext */ char repbuf[16384]; /* output report buffer */ FILE *textfile; /* input file handle/pointer */ /* * Set up any required variables */ time( &now); /* get current time */ /* * Work through the arglist, handling options that change * the behavior of this text file filter. */ for ( a = 1 ; a < argc ; a++ ) { int rc; char *cp; char cmdline[512]; /* * We need to synthesize the target named from * the input name. */ strcpy( textpath, argv[a]); /* copy in the name */ /* * capture the name of the file w/o extensions * (ie. no .txt, .x, or whatnot) and without * the directory part (should it be present). */ strcpy( corename, basename(textpath)); cp = strrchr( corename, '.'); if ( cp && *cp ) { *cp = 0x00; } /* * Get the age of the file at the time of this job */ if ( stat( textpath, &f_stat) != 0 ) break; fmt = f_stat.st_mtime; /* file modification time */ age = now - fmt; /* hope the clock is right */ /* * Open the file and grab the SHS information */ textfile = fopen( textpath, "r"); if ( !textfile ) /* detect failure of opening */ { fprintf( stderr, "Could not open [%s] for reading.\n", textpath); fflush( stderr); exit( 1); } procSHS( textfile); fclose( textfile); /* close file when done */ /* * Next we'll report on the SHS information */ /* * $AGE|$CORENAME|$UNIVERSE|$MAINTTL|$PART|$SUBTTL|$CODES|$SUMMARY|$WORDS|$INCOMPLETE|$RCSINFO * 1 2 3 4 5 6 7 8 9 10 11 */ sprintf( repbuf, "%ld|%s|", age, corename); /* 1, 2 */ strcat( repbuf, shs_universe); strcat( repbuf, "|"); /* 3 */ strcat( repbuf, shs_title); strcat( repbuf, "|"); /* 4 */ strcat( repbuf, shs_part); strcat( repbuf, "|"); /* 5 */ strcat( repbuf, "-"); strcat( repbuf, "|"); /* 6 */ strcat( repbuf, shs_keywords); strcat( repbuf, "|"); /* 7 */ strcat( repbuf, shs_summary); strcat( repbuf, "|"); /* 8 */ strcat( repbuf, ""); strcat( repbuf, "|"); /* 9 */ strcat( repbuf, ""); strcat( repbuf, "|"); /* 10 */ strcat( repbuf, shs_rcs); /* 11 */ fprintf( stdout, "%s\n", repbuf); fflush( stdout); } exit( 0); } /* shsinfo main */ /* * procSHS - This function reads in the source file's SHS * (Standard Header Sequence) for ASSTR which is * intended to keep the story meta-information in * proximity to the actual story content. It is * hoped this will not be clipped since it keeps * the most useful information in a recognizable * form. */ int procSHS( si) /* process SHS headers and populate table */ FILE *si; { int i, /* index into SHS map table */ llen; /* line length as seen */ char *cp; /* utility pointer */ char inbuf[4096]; /* input buffer */ /* * Before processing the open file we need to clear the * target buffers */ for ( i = 0 ; shsInfo[i].buflen > 0 ; i++ ) /* clear previous */ { strcpy( shsInfo[i].buffer, ""); } /* * Read lines from the file and scan them for leadin * SHS lines... */ while ( fgets( inbuf, 4095, si) ) { llen = strlen( inbuf); if ( llen == 0 ) break; inbuf[--llen] = 0x00; /* drop the newline */ /* * Detect changes that will indicate the end of * the heading section... */ if ( llen == 0 ) break; if ( inbuf[0] == ' ' ) break; if ( inbuf[0] == '\t' ) break; /* * OK, scan the input buffer against the list of * labels we're looking to deal with. */ for ( i = 0 ; shsInfo[i].buflen > 0 ; i++ ) { struct MapItems *map; map = &shsInfo[i]; /* * If the label matches, we'll process it * properly by finding the data part... */ if ( strncmp( inbuf, map->label, map->lablen ) == 0 ) { char *cp; cp = strchr( inbuf, ':'); if ( cp && *cp ) cp++; if ( cp && *cp ) cp++; strncpy( map->buffer, cp, map->buflen); break; } } } } /* procSHS */