home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * Module : Segment --- Find the segments of the posted file.
- *
- * Author : John W. M. Stevens
- ******************************************************************************/
-
- #include "compiler.h"
-
- #include "unpost.h"
- #include "list.h"
- #include "modflnm.h"
- #include "parse.h"
- #include "decode.h"
- #include "uudec.h"
- #include "segment.h"
- #include "utils.h"
-
- /* Segment types. */
- typedef enum {
- SEG_USED, /* Used in succesful decoding. */
- SEG_TEXT, /* Pure text segment. */
- SEG_INCOMP, /* Segment that is part of incomplete posting. */
- SEG_DESC /* Segment is a description. */
- } SEG_TYPE;
-
- /* Segment list structure. */
- typedef struct {
- long LnOfs; /* Byte offset to start of SEGMENT. */
- int CopyFlag; /* Copy out flag. */
- } SEG_LIST;
-
- /* Line and string buffers. */
- char SegLine[BFR_SIZE];
- char IDLine[BFR_SIZE];
- char UULine[BFR_SIZE];
- char InBfr[BFR_SIZE];
- BYTE OutBfr[BFR_SIZE];
-
- /*-----------------------------------------------------------------------------
- | Routine : UUDecode() --- Decode a UU encoded file.
- |
- | Inputs : FlName - Name of input file.
- -----------------------------------------------------------------------------*/
-
- void UUDecode(char *InFlNm)
- {
- auto FILE *InFlPtr;
- auto FILE *OutFlPtr;
- auto int OutLen;
- auto char **RetStrs;
- auto char FlName[FL_NM_SZ];
-
- /* Externals used by this function. */
- extern FILE *ErrFile;
-
- /* Open file. */
- if ((InFlPtr = fopen(InFlNm, BIN_READ)) == NULL)
- {
- fprintf(ErrFile,
- "%s %d : Error - could not open file '%s' for reading.\n",
- __FILE__,
- __LINE__,
- InFlNm);
- return;
- }
-
- /* Get all uuencoded files from single file. */
- while (! feof( InFlPtr ))
- {
- /* Search forwards through the file for the first
- * UU encoded line.
- */
- do
- {
- /* Get a line from the file. */
- if (ReadLine(InFlPtr, InBfr, BFR_SIZE) == EOF)
- {
- fclose( InFlPtr );
- return;
- }
- } while (! MatchBegin(InBfr, &RetStrs));
-
- /* Get the binary file name. */
- GetBinFlNm(InFlPtr, RetStrs, FlName);
-
- /* Check to make sure that file does not already exist. */
- if ( FileExists( FlName ) )
- {
- fprintf(ErrFile,
- "%s %d : Error - file '%s' already exists.\n",
- __FILE__,
- __LINE__,
- FlName);
- fclose( InFlPtr );
- return;
- }
-
- /* Open the file. */
- if ((OutFlPtr = fopen(FlName, BIN_WRITE)) == NULL)
- {
- fprintf(ErrFile,
- "%s %d : Error - %s\n\t'%s'\n",
- __FILE__,
- __LINE__,
- sys_errlist[errno],
- FlName);
- fclose( InFlPtr );
- return;
- }
-
- /* It exists, is open, and ready to roll. Now decode to
- * end line.
- */
- while (ReadLine(InFlPtr, InBfr, BFR_SIZE) != EOF)
- {
- /* Test for end line. */
- if ( MatchEnd( InBfr ) )
- break;
-
- /* Space pad line, if necesary. */
- DecTruncUULn(InBfr, &OutLen, OutBfr);
-
- /* Are there any bytes to write? */
- if (OutLen < 1)
- continue;
-
- /* Write the buffer to the output file. */
- if (fwrite(OutBfr, 1, OutLen, OutFlPtr) != OutLen)
- {
- fprintf(ErrFile,
- "\t%s %d : Error - Bad write to binary file.\n",
- __FILE__,
- __LINE__);
- exit( 1 );
- }
- }
-
- /* Close output file. */
- fclose( OutFlPtr );
- }
-
- /* Close input file. */
- fclose( InFlPtr );
- }
-
- /*-----------------------------------------------------------------------------
- | Routine : Single() --- Decode binarys, assumed to be in sorted order.
- | already.
- |
- | Inputs : FileNm - Name of file that contains single binary.
- -----------------------------------------------------------------------------*/
-
- void Single(char *FileNm)
- {
- auto long LnOfs;
- auto CHK_UU_ENC UULnType;
- auto char **RetStrs;
- auto int OutLen;
- auto FILE *InFlPtr;
- auto FILE *OutFlPtr;
- auto char FlName[FL_NM_SZ];
-
- /* Externals used by this function. */
- extern FILE *ErrFile;
-
- /* Open file. */
- if ((InFlPtr = fopen(FileNm, BIN_READ)) == NULL)
- {
- fprintf(ErrFile,
- "%s %d : Error - could not open file '%s' for reading.\n",
- __FILE__,
- __LINE__,
- FileNm);
- return;
- }
-
-
- /* Get all uuencoded files from single file. */
- while (! feof( InFlPtr ))
- {
- /* Search forwards through the file for the first UU encoded line. */
- do
- {
- /* Get the current file offset. */
- LnOfs = ftell( InFlPtr );
-
- /* Get a line from the file. */
- if (ReadLine(InFlPtr, InBfr, BFR_SIZE) == EOF)
- {
- fclose( InFlPtr );
- return;
- }
-
- /* Check to see if this is a UUencoded line. */
- UULnType = ChkUULine(InBfr, &RetStrs, &OutLen);
-
- } while (UULnType != UU_BEGIN);
-
- /* Get the binary file name. */
- UnExpectedBegin:
- GetBinFlNm(InFlPtr, RetStrs, FlName);
-
- /* Check to make sure that file does not already exist. */
- if ( FileExists( FlName ) )
- {
- fprintf(ErrFile,
- "%s %d : Error - file '%s' already exists.\n",
- __FILE__,
- __LINE__,
- FlName);
- continue;
- }
-
- /* Open the file. */
- if ((OutFlPtr = fopen(FlName, BIN_WRITE)) == NULL)
- {
- fprintf(ErrFile,
- "%s %d : Error - %s\n\t'%s'\n",
- __FILE__,
- __LINE__,
- sys_errlist[errno],
- FlName);
- continue;
- }
-
- /* Now munch and crunch until done with file. */
- do
- {
- /* Decode a segment. */
- DecSeg(InFlPtr, OutFlPtr, &UULnType);
-
- /* Check for proper exit conditions. */
- if (UULnType == UU_BEGIN ||
- UULnType == UU_END)
- break;
-
- /* Scan to next UU encoded line. */
- do
- {
- /* Get the current file offset. */
- LnOfs = ftell( InFlPtr );
-
- /* Get next line. */
- if (ReadLine(InFlPtr, InBfr, BFR_SIZE) == EOF)
- {
- fprintf(ErrFile,
- "%s %d : Error - Unexpected end of file.\n",
- __FILE__,
- __LINE__);
- fclose( InFlPtr );
- fclose( OutFlPtr );
- return;
- }
-
- /* Check to see if this is a UUencoded line. */
- UULnType = ChkUULine(InBfr, &RetStrs, &OutLen);
-
- } while (UULnType == NOT_UU_LINE || UULnType == UU_SPACE);
-
- /* Reset file pointer to begining of UU line. */
- if (fseek(InFlPtr, LnOfs, SEEK_SET) != 0)
- {
- fprintf(ErrFile,
- "%s %d : Error - %s\n",
- __FILE__,
- __LINE__,
- sys_errlist[errno]);
- exit( 1 );
- }
-
- } while (UULnType == IS_UU_LINE);
-
- /* Close the output file pointer. */
- fclose( OutFlPtr );
-
- /* Check the various types. */
- if (UULnType == UU_BEGIN)
- {
- fprintf(ErrFile,
- "%s %d : Error - Unexpected UU begin line.\n",
- __FILE__,
- __LINE__);
- goto UnExpectedBegin;
- }
- }
-
- /* Close the files. */
- fclose( InFlPtr );
- }
-
- /*-----------------------------------------------------------------------------
- | Routine : CmpFl() --- Compare two file list entries.
- |
- | Inputs : File1 - File entry one.
- | File2 - File entry two.
- -----------------------------------------------------------------------------*/
-
- static
- int CmpFl(void *File1,
- void *File2)
- {
- return( strcmp(((FL_LIST *) File1)->IDString,
- ((FL_LIST *) File2)->IDString) );
- }
-
- /*-----------------------------------------------------------------------------
- | Routine : DumpSeg() --- Dump a segment to a file.
- |
- | Inputs : InFlPtr - File to read segment from (source file).
- | OutFlPtr - File to write segment to.
- | NextSeg - Start of next segment.
- -----------------------------------------------------------------------------*/
-
- static
- void DumpSeg(FILE *InFlPtr,
- FILE *OutFlPtr,
- long NextSeg)
- {
- /* Dump segment to output file. */
- while (ReadLine(InFlPtr, SegLine, BFR_SIZE) != EOF)
- {
- /* Print line. */
- fprintf(OutFlPtr, "%s\n", SegLine);
-
- /* Get next line offset. */
- if (ftell( InFlPtr ) == NextSeg)
- break;
- }
- }
-
- /*-----------------------------------------------------------------------------
- | Routine : Multiple() --- Extract multiple postings from one file.
- |
- | Inputs : FileNm - Name of file to unpost.
- -----------------------------------------------------------------------------*/
-
- void Multiple(char *FileNm)
- {
- register int i;
- register int j;
- auto FILE *InFlPtr;
- auto FILE *OutFlPtr;
- auto long LnOfs;
- auto int InsPt;
- auto SEG_INFO SegInfo;
- auto FL_LIST *FlPtr;
- auto FL_LIST NewFile;
- auto SEG_LIST *SegPtr;
- auto SEG_LIST NewSeg;
-
- /* Buffers for input and output. */
- static LIST *FileList;
- static LIST *SegList;
- extern int MsDosFileNms;
- extern int DumpDesc;
- extern int SepIncomps;
- extern FILE *ErrFile;
- extern FILE *TextFile;
- extern FILE *IncompFile;
-
- /* Open file. */
- if ((InFlPtr = fopen(FileNm, BIN_READ)) == NULL)
- {
- fprintf(ErrFile,
- "%s %d : Error - could not open file '%s' for reading.\n",
- __FILE__,
- __LINE__,
- FileNm);
- return;
- }
-
- /* Allocate a file and a segment list. */
- FileList = CrtList( sizeof( FL_LIST ) );
- SegList = CrtList( sizeof( SEG_LIST ) );
-
- /* Search for all ID lines, building a list of all
- * files and their segments as we go.
- */
- while (! feof( InFlPtr ))
- {
- /* Parse article information out of the file. */
- memset(&SegInfo, 0, sizeof( SEG_INFO ));
- LnOfs = Parse(InFlPtr,
- SegLine,
- IDLine,
- &SegInfo);
-
- #if defined(UNPOST_DEBUG)
- printf("\n\tSegInfo:\n");
- printf("\t--------\n");
- printf("\tNumber of Segments: %d\n", SegInfo.NoSegs);
- printf("\tSegment Number : %d\n", SegInfo.SegNo);
- printf("\tSegment Offset : %ld\n", SegInfo.SegOfs);
- printf("\tUUencode Offset : %ld\n", SegInfo.UUOfs);
- printf("\tBinary ID String : '%s'\n",
- (SegInfo.IDString == NULL) ? "NULL POINTER"
- : SegInfo.IDString);
- printf("\tBinary File Name : '%s'\n\n",
- (SegInfo.FlName == NULL) ? "NULL POINTER"
- : SegInfo.FlName);
-
- switch ( LnOfs )
- {
- case -1L:
- printf("\tPRS_NO_SEGMENT\n");
- break;
- case -2L:
- printf("\tPRS_NO_ID_STR\n");
- break;
- case -3L:
- printf("\tPRS_NO_UU_LN\n");
- break;
- case -4L:
- printf("\tPRS_NO_BEGIN\n");
- break;
- case -5L:
- printf("\tPRS_NO_SEG_NUM\n");
- break;
- case -6L:
- printf("\tPRS_NO_NUM_SEGS\n");
- break;
- case -7L:
- printf("\tPRS_UNX_END_SEG\n");
- break;
- }
- #endif
-
- /* Save the segment data. */
- NewSeg.LnOfs = SegInfo.SegOfs;
-
- /* Check for errors. */
- if (LnOfs == PRS_NO_SEGMENT)
- break;
- else if (LnOfs == PRS_NO_UU_LN)
- {
- /* Check to see if this is a description segment. */
- if (SegInfo.IDString &&
- *SegInfo.IDString &&
- SegInfo.SegNo == 0 &&
- SegInfo.NoSegs > 0)
- {
- /* This has part numbering info, and the part number
- * is zero, but it has no uuencoded data, so this
- * must be a description segement.
- */
- NewSeg.CopyFlag = SEG_DESC;
- }
- else
- {
- /* Save as text segment. */
- NewSeg.CopyFlag = SEG_TEXT;
- SegList = AppList(SegList, &NewSeg);
-
- /* If the file name or ID string exist, deallocate. */
- if ( SegInfo.IDString )
- free( SegInfo.IDString );
- continue;
- }
- }
- else if (LnOfs == PRS_NO_SEG_NUM ||
- LnOfs == PRS_NO_NUM_SEGS ||
- SegInfo.IDString == NULL ||
- *SegInfo.IDString == '\0')
- {
- /* Something important is missing. Do NOT attempt to
- * put one of these in the file list.
- */
- NewSeg.CopyFlag = SEG_INCOMP;
- SegList = AppList(SegList, &NewSeg);
-
- /* If the file name or ID string exist, deallocate. */
- if ( SegInfo.IDString )
- free( SegInfo.IDString );
- continue;
- }
- else
- NewSeg.CopyFlag = SEG_INCOMP;
-
- /* Add segment to list. */
- SegList = AppList(SegList, &NewSeg);
-
- /* Search file list for ID string. */
- NewFile.IDString = SegInfo.IDString;
- if (SrchList(FileList, &NewFile, CmpFl, &InsPt) == FALSE)
- {
- /* Did not find file in list, add a new file. First,
- * allocate segments buffer.
- */
- if ((NewFile.Segs = (SEGS *)
- calloc(SegInfo.NoSegs + 1, sizeof( SEGS ))) == NULL)
- {
- fprintf(ErrFile,
- "%s %d : Error - out of memory.\n",
- __FILE__,
- __LINE__);
- exit( 1 );
- }
-
- /* We have a valid ID line, and at least one UUencoded
- * line, so add this segment to the list.
- */
- NewFile.NoSegs = SegInfo.NoSegs;
- NewFile.FlName = NULL;
- NewFile.Success = 0;
- FileList = AddList(FileList, &NewFile, InsPt);
- }
- else
- free( SegInfo.IDString );
- FlPtr = ListIdx(FileList, InsPt);
-
- /* Check for irreconcilable differences. */
- if (FlPtr->NoSegs < SegInfo.SegNo)
- {
- fprintf(ErrFile,
- "%s %d : Error - Segment number #%d greater than number",
- __FILE__,
- __LINE__,
- SegInfo.SegNo);
- fprintf(ErrFile,
- " of segments in:\n\tSegment: '%s'\n",
- SegLine);
- }
- else
- {
- /* Save the offset in the proper segment location. */
- if (FlPtr->Segs[SegInfo.SegNo].SegNo != 0)
- {
- fprintf(ErrFile,
- "%s %d : Warning - duplicate segment #%d in:\n",
- __FILE__,
- __LINE__,
- SegInfo.SegNo);
- fprintf(ErrFile,
- "\tBinary ID: '%s'\n",
- FlPtr->IDString);
- }
-
- /* Set up file descriptor segment. */
- FlPtr->Segs[SegInfo.SegNo].Exists = 1;
- FlPtr->Segs[SegInfo.SegNo].SegNo = SegInfo.SegNo;
- FlPtr->Segs[SegInfo.SegNo].SegOfs = SegInfo.SegOfs;
- FlPtr->Segs[SegInfo.SegNo].UUOfs = SegInfo.UUOfs;
- FlPtr->Segs[SegInfo.SegNo].SegLstOrd = SegList->NoElems - 1;
- }
-
- /* Add the file name string, if it isn't already present. */
- if ( FlPtr->FlName )
- free( SegInfo.FlName );
- else if ( SegInfo.FlName )
- FlPtr->FlName = SegInfo.FlName;
- }
-
- /* Dump Table. */
- fprintf(ErrFile, "File ID Segments\n");
- fprintf(ErrFile, "----------------------------------------\n");
- for (i = 0; i < FileList->NoElems; i++)
- {
- FlPtr = ListIdx(FileList, i);
- fprintf(ErrFile,
- "%-30.30s %d\n",
- FlPtr->IDString,
- FlPtr->NoSegs);
- for (j = 1; j <= FlPtr->NoSegs; j++)
- fprintf(ErrFile, "\t%d %ld\n",
- FlPtr->Segs[j].SegNo,
- FlPtr->Segs[j].SegOfs);
- }
- fprintf(ErrFile, "\n");
-
- /* Decode the files. */
- for (i = 0; i < FileList->NoElems; i++)
- {
- /* Get pointer to file list entry. */
- FlPtr = ListIdx(FileList, i);
-
- /* Report binary id you are attempting to decode. */
- fprintf(ErrFile,
- "Decoding Binary ID: '%s'\n",
- FlPtr->IDString);
-
- /* Attempt to decode the file. */
- if (DeCode(InFlPtr, FlPtr) == OK)
- {
- /* Scan segment list, marking all segments as having been
- * successfully used.
- */
- FlPtr->Success = 1;
- for (j = 1; j <= FlPtr->NoSegs; j++)
- {
- SegPtr = ListIdx(SegList, FlPtr->Segs[j].SegLstOrd);
- SegPtr->CopyFlag = SEG_USED;
- }
- }
- }
-
- /* Do we want to save incomplete pieces? */
- if (IncompFile || SepIncomps)
- {
- /* Write incomplete binaries to uuencoded file in sorted
- * order.
- */
- for (i = 0; i < FileList->NoElems; i++)
- {
- auto long EndOfs;
-
- /* Get pointer to file. */
- FlPtr = ListIdx(FileList, i);
- if ( FlPtr->Success )
- continue;
-
- /* Open file to write segments to, or use incompletes
- * file.
- */
- if (SepIncomps && FlPtr->IDString && *FlPtr->IDString)
- {
- /* Use the binary ID string to create a .uue file name.
- */
- if ( MsDosFileNms )
- ModifyFlNm(FlPtr->IDString, ".uue", InBfr);
- else
- ModExten(FlPtr->IDString, ".uue", InBfr);
-
- /* Open incompletes file. */
- if ((OutFlPtr = fopen(InBfr, TXT_APPEND)) == NULL)
- {
- fprintf(ErrFile,
- "%s %d : Error - File '%s' cannot be opened ",
- __FILE__,
- __LINE__,
- InBfr);
- fprintf(ErrFile,
- "for appending.\n");
- continue;
- }
- }
- else
- OutFlPtr = IncompFile;
-
- /* This file was NOT successfully converted, write it's
- * segments out to the incomplete file.
- */
- for (j = 0; j <= FlPtr->NoSegs; j++)
- {
- /* If this segment does not exist, do not copy it. */
- if (! FlPtr->Segs[j].Exists)
- continue;
- else if (j == 0 && ! DumpDesc)
- continue;
-
- /* Position file pointer to first line of segment. */
- if (fseek(InFlPtr, FlPtr->Segs[j].SegOfs, SEEK_SET) != 0)
- {
- fprintf(ErrFile,
- "%s %d : Error - %s\n",
- __FILE__,
- __LINE__,
- sys_errlist[errno]);
- exit( 1 );
- }
-
- /* Mark this segment as having been dumped out. */
- SegPtr = ListIdx(SegList, FlPtr->Segs[j].SegLstOrd);
- SegPtr->CopyFlag = SEG_USED;
-
- /* Get offset for end of segment. */
- if (FlPtr->Segs[j].SegLstOrd + 1 < SegList->NoElems)
- EndOfs = SegPtr[1].LnOfs;
- else
- EndOfs = -1L;
-
- /* Write all of segment to file. */
- DumpSeg(InFlPtr, OutFlPtr, EndOfs);
- }
-
- /* Check to see if we need to close the file. */
- if (OutFlPtr != IncompFile)
- fclose( OutFlPtr );
- }
- }
-
- /* Check to make sure that the user has requested that unused
- * segments be dumped out to ANY file.
- */
- if (TextFile || IncompFile)
- {
- /* Dump unused segments to file. */
- for (i = 0, SegPtr = ListIdx(SegList, 0);
- i < SegList->NoElems;
- i++, SegPtr++)
- {
- /* If this segment was successfully converted, do not
- * copy it.
- */
- if (SegPtr->CopyFlag == SEG_USED)
- continue;
-
- /* Position file pointer to first UUencoded
- * line of segment.
- */
- if (fseek(InFlPtr, SegPtr->LnOfs, SEEK_SET) != 0)
- {
- fprintf(ErrFile,
- "%s %d : Error - %s\n",
- __FILE__,
- __LINE__,
- sys_errlist[errno]);
- exit( 1 );
- }
-
- /* Read and write lines. */
- if (SegPtr->CopyFlag == SEG_TEXT && TextFile)
- {
- /* Dump the segment out to the text file. */
- DumpSeg(InFlPtr,
- TextFile,
- (i < SegList->NoElems - 1)
- ? SegPtr[1].LnOfs
- : -1L);
- }
- else if (SegPtr->CopyFlag == SEG_INCOMP && IncompFile)
- {
- /* Dump the segment out to the text file. */
- DumpSeg(InFlPtr,
- IncompFile,
- (i < SegList->NoElems - 1)
- ? SegPtr[1].LnOfs
- : -1L);
- }
- }
- }
-
- /* Deallocate file descriptor list. */
- for (i = 0; i < FileList->NoElems; i++)
- {
- /* Get pointer to file list entry. */
- FlPtr = ListIdx(FileList, i);
-
- /* Deallocate the heap memory. */
- free( FlPtr->Segs );
- free( FlPtr->FlName );
- free( FlPtr->IDString );
- }
-
- /* Free the list. */
- free( FileList );
- free( SegList );
- }
-