home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Hack-Phreak Scene Programs
/
cleanhpvac.zip
/
cleanhpvac
/
HPACK78S.ZIP
/
script.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-03
|
15KB
|
472 lines
/****************************************************************************
* *
* HPACK Multi-System Archiver *
* =========================== *
* *
* Script File Handling Code *
* SCRIPT.C Updated 20/07/92 *
* *
* This program is protected by copyright and as such any use or copying of *
* this code for your own purposes directly or indirectly is highly uncool *
* and if you do so there will be....trubble. *
* And remember: We know where your kids go to school. *
* *
* Copyright 1991 - 1992 Peter C.Gutmann. All rights reserved *
* *
****************************************************************************/
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#ifdef __MAC__
#include "defs.h"
#include "choice.h"
#include "error.h"
#include "filesys.h"
#include "flags.h"
#include "frontend.h"
#include "hpacklib.h"
#include "hpaktext.h"
#include "system.h"
#include "wildcard.h"
#include "fastio.h"
#include "hpackio.h"
#else
#include "defs.h"
#include "choice.h"
#include "error.h"
#include "filesys.h"
#include "flags.h"
#include "frontend.h"
#include "hpacklib.h"
#include "system.h"
#include "wildcard.h"
#include "io/fastio.h"
#include "io/hpackio.h"
#include "language/hpaktext.h"
#endif /* __MAC__ */
/****************************************************************************
* *
* Build/Free List of Files to Handle *
* *
****************************************************************************/
/* The start of the list of fileSpecs */
FILEPATHINFO *filePathListStart = NULL;
/* Add a filespec to the list of files to handle */
void addFilespec( char *fileSpec )
{
FILEPATHINFO *theNode, *prevNode, *newNode;
FILENAMEINFO *fileNamePtr, *prevFileNamePtr;
char fileCode[ MATCH_DEST_LEN ], pathCode[ MATCH_DEST_LEN ];
char pathName[ MAX_PATH ];
int pathNameEnd, nonMatch, fileCodeLen, pathCodeLen;
BOOLEAN fileHasWildcards, pathHasWildcards;
#if defined( __AMIGA__ ) || defined( __ARC__ ) || defined( __ATARI__ ) || \
defined( __MAC__ ) || defined( __MSDOS__ ) || defined( __OS2__ ) || \
defined( __VMS__ )
int count;
#endif /* __AMIGA__ || __ARC__ || __ATARI__ || __MAC__ || __MSDOS__ || __OS2__ || __VMS__ */
#if defined( __ARC__ ) || defined( __VMS__ )
int nodeNameEnd = 0;
#endif /* __ARC__ || __VMS__ */
/* Check the path is of a legal length */
if( strlen( fileSpec ) > MAX_PATH - 1 )
error( PATH_s_TOO_LONG, fileSpec );
/* Extract the pathname and convert it into an OS-compatible format */
pathNameEnd = extractPath( fileSpec, pathName );
/* Compile the file spec.and path spec.into a form acceptable by the
wildcard-matching finite-state machine */
fileCodeLen = compileString( fileSpec + pathNameEnd, fileCode );
pathCodeLen = compileString( pathName, pathCode );
fileHasWildcards = strHasWildcards( fileSpec + pathNameEnd );
pathHasWildcards = strHasWildcards( pathName );
/* Complain if it's an external path with wildcards. This is the case
for Add and the add portion of an Update */
if( pathHasWildcards && ( choice == ADD || choice == UPDATE ) )
error( CANNOT_USE_WILDCARDS_s, pathName );
/* Now sort the file names by path as they are added, in order to make disk
accesses more efficient. This can be done by a simple insertion sort
since there are only a small number of names to sort, and it can be done
on the fly. Note that there is one case in which the files won't be
sorted: If there drive specs, normal files/paths, and files/paths
beginning with letters lower than ':' then they will be put before the
drive specs, with the rest of the normal files/paths being placed
after the drive specs. However the occurrence of filenames containing
these characters is virtually unheard-of so no special actions are
taken for them */
theNode = filePathListStart;
if( filePathListStart == NULL )
{
/* Create the initial list node */
if( ( filePathListStart = newNode = ( FILEPATHINFO * ) hmalloc( sizeof( FILEPATHINFO ) ) ) == NULL )
error( OUT_OF_MEMORY );
}
else
{
/* Find the correct position to insert the new pathname */
prevNode = filePathListStart;
while( theNode != NULL && ( nonMatch = strcmp( pathName, theNode->filePath ) ) > 0 )
{
prevNode = theNode;
theNode = theNode->next;
}
/* Don't insert the pathname if it's already in the list */
if( !nonMatch )
{
/* Find the end of the list of fileNames and add a new node */
for( prevFileNamePtr = fileNamePtr = theNode->fileNames; \
fileNamePtr != NULL; prevFileNamePtr = fileNamePtr, \
fileNamePtr = fileNamePtr->next )
/* Leave now if the fileName is already in the list */
if( !strncmp( fileNamePtr->fileName, fileCode, fileCodeLen ) )
return;
fileNamePtr = prevFileNamePtr;
if( ( fileNamePtr->next = ( FILENAMEINFO * ) hmalloc( sizeof( FILENAMEINFO ) ) ) == NULL )
error( OUT_OF_MEMORY );
fileNamePtr = fileNamePtr->next;
goto nodeExists;
}
/* Create the new node and link it into the list */
if( ( newNode = ( FILEPATHINFO * ) hmalloc( sizeof( FILEPATHINFO ) ) ) == NULL )
error( OUT_OF_MEMORY );
if( prevNode == filePathListStart )
{
/* Insert at start of list */
filePathListStart = newNode;
theNode = prevNode;
}
else
/* Insert in middle/end of list */
prevNode->next = newNode;
}
newNode->next = theNode;
/* Seperate out the node/path component and make sure we're not trying
to override an existing base path */
#if defined( __ATARI__ ) || defined( __MSDOS__ ) || defined( __OS2__ )
/* Look for a drive spec in the filename */
newNode->device = NULL;
if( ( ( count = ( *pathName && pathName[ 1 ] == ':' ) ? \
toupper( *pathName ) : 0 ) && *basePath ) || \
( *basePath && basePath[ 1 ] == ':' && basePath[ 2 ] && \
*pathName == SLASH ) )
error( CANNOT_OVERRIDE_BASEPATH, basePath );
/* If there is a drive spec, save it */
if( count )
{
if( ( newNode->device = ( char * ) hmalloc( 3 ) ) == NULL )
error( OUT_OF_MEMORY );
newNode->device[ 0 ] = count;
newNode->device[ 1 ] = ':';
newNode->device[ 2 ] = '\0';
}
#elif defined( __AMIGA__ ) || defined( __MAC__ )
/* Look for a drive spec in the pathname */
newNode->device = NULL;
for( count = 0; count < pathNameEnd; count++ )
if( pathName[ count ] == ':' )
{
/* Save the drive spec */
if( ( newNode->device = ( char * ) hmalloc( count + 2 ) ) == NULL )
error( OUT_OF_MEMORY );
strncpy( newNode->device, pathName, count + 1 );
newNode->device[ count + 1 ] = '\0';
break; /* Exit while loop */
}
if( *basePath && *pathName == SLASH )
error( CANNOT_OVERRIDE_BASEPATH, basePath );
#elif defined( __ARC__ )
/* Look for a node name in the pathname */
newNode->node = NULL;
for( count = 1; count < pathNameEnd; count++ )
if( pathName[ count - 1 ] == ':' && pathName[ count ] == ':' )
{
/* Save the node name */
if( ( newNode->node = ( char * ) hmalloc( count + 2 ) ) == NULL )
error( OUT_OF_MEMORY );
strncpy( newNode->node, pathName, ++count );
newNode->node[ count ] = '\0';
nodeNameEnd = count;
break; /* Exit while loop */
}
/* Archimedes drives are handled funny */
newNode->device = NULL;
#elif defined( __UNIX__ )
if( *basePath && *pathName == SLASH )
error( CANNOT_OVERRIDE_BASEPATH, basePath );
#elif defined( __VMS__ )
/* Look for a node name in the pathname */
newNode->node = NULL;
for( count = 1; count < pathNameEnd; count++ )
if( pathName[ count - 1 ] == ':' && pathName[ count ] == ':' )
{
/* Save the node name */
if( ( newNode->node = ( char * ) hmalloc( count + 2 ) ) == NULL )
error( OUT_OF_MEMORY );
strncpy( newNode->node, pathName, ++count );
newNode->node[ count ] = '\0';
nodeNameEnd = count;
break; /* Exit while loop */
}
/* Look for a device name in the pathname */
newNode->device = NULL;
for( count = nodeNameEnd; count < pathNameEnd; count++ )
if( pathName[ count ] == ':' )
{
/* Save the device name */
count -= nodeNameEnd;
if( ( newNode->device = ( char * ) hmalloc( count + 2 ) ) == NULL )
error( OUT_OF_MEMORY );
strncpy( newNode->device, pathName + nodeNameEnd, ++count );
newNode->device[ count ] = '\0';
break; /* Exit while loop */
}
if( *basePath && *pathName == SLASH )
error( CANNOT_OVERRIDE_BASEPATH, basePath );
#endif /* Various OS-specific device handling */
if( ( newNode->filePath = ( char * ) hmalloc( pathCodeLen ) ) == NULL )
error( OUT_OF_MEMORY );
memcpy( newNode->filePath, pathCode, pathCodeLen );
newNode->hasWildcards = pathHasWildcards;
if( ( newNode->fileNames = ( FILENAMEINFO * ) hmalloc( sizeof( FILENAMEINFO ) ) ) == NULL )
error( OUT_OF_MEMORY );
fileNamePtr = newNode->fileNames;
nodeExists:
fileNamePtr->next = NULL;
/* Add the compiled filespec to the list of filespecs */
if( ( fileNamePtr->fileName = ( char * ) hmalloc( fileCodeLen ) ) == NULL )
error( OUT_OF_MEMORY );
memcpy( fileNamePtr->fileName, fileCode, fileCodeLen );
fileNamePtr->hasWildcards = fileHasWildcards;
}
#if !defined( __MSDOS__ ) || defined( GUI )
/* Free up the memory used by the list of filespecs. See the comment in
freeArchiveNames() for why we use this complex double-stepping way of
freeing the headers */
void freeFilespecs( void )
{
FILEPATHINFO *pathHeaderCursor = filePathListStart, *pathHeaderPtr;
FILENAMEINFO *nameHeaderCursor, *nameHeaderPtr;
/* Free the nodes of the filePath list */
while( pathHeaderCursor != NULL )
{
/* Free the nodes of the fileName list */
nameHeaderCursor = pathHeaderCursor->fileNames;
while( nameHeaderCursor != NULL )
{
nameHeaderPtr = nameHeaderCursor;
nameHeaderCursor = nameHeaderCursor->next;
hfree( nameHeaderPtr->fileName );
hfree( ( void * ) nameHeaderPtr ); /* ThinkC needs this */
}
pathHeaderPtr = pathHeaderCursor;
pathHeaderCursor = pathHeaderCursor->next;
hfree( pathHeaderPtr->filePath );
hfree( ( void * ) pathHeaderPtr ); /* ThinkC again */
}
}
#endif /* !__MSDOS__ || GUI */
/****************************************************************************
* *
* Process a List-File *
* *
****************************************************************************/
/* The types of error we check for */
enum { NO_ERROR, ILLEGAL_CHAR_ERROR, PATH_ERROR };
#define CPM_EOF 0x1A /* ^Z = CPM EOF char */
#define MAX_ERRORS 10 /* Max.no.errors before we give up */
void processListFile( const char *listFileName )
{
FD listFileFD;
int ch = 0, theCh;
int errType, errPos, errCount = 0, line = 1;
BOOLEAN firstError = TRUE, seenCR = FALSE;
#ifdef GUI
char string[ 10 ];
#endif /* GUI */
if( ( listFileFD = hopen( listFileName, O_RDONLY | S_DENYWR | A_SEQ ) ) == IO_ERROR )
{
#ifdef GUI
alert( ALERT_CANNOT_OPEN_SCRIPTFILE, listFileName );
#else
hprintf( WARN_CANNOT_OPEN_SCRIPTFILE_s, listFileName );
#endif /* GUI */
return;
}
#ifndef GUI
hprintfs( MESG_PROCESSING_SCRIPTFILE_s, listFileName );
#endif /* !GUI */
setInputFD( listFileFD );
resetFastIn();
/* Process each line in the listFile */
while( ch != FEOF )
{
/* If we've just seen a CR and now we see a LF, skip to next line */
if( ( ch = fgetByte() ) == '\n' && seenCR )
ch = fgetByte();
seenCR = FALSE;
/* Skip whitespace */
while( ( ch == ' ' || ch == '\t' ) && ch != FEOF )
ch = fgetByte();
/* Get a line into the mrglBuffer */
mrglBufCount = 0;
errType = NO_ERROR;
while( ch != '\r' && ch != '\n' && ch != CPM_EOF && ch != FEOF )
{
/* Check for an illegal char in the data */
if( ( ch < ' ' || ch > '~' ) && ch != '\r' && ch != '\n' && \
ch != CPM_EOF && ch != FEOF )
{
if( errType == NO_ERROR )
/* Save position of first illegal char */
errPos = mrglBufCount;
errType = ILLEGAL_CHAR_ERROR;
}
#if defined( __ATARI__ ) || defined( __MSDOS__ ) || defined( __OS2__ )
if( ch == '\\' )
ch = SLASH; /* Get dir.seperator in correct format */
#endif /* __ATARI__ || __MSDOS__ || __OS2__ */
/* Make sure the path is of the correct length. Note that the
code is ordered so that a PATH_ERROR takes precedence over
an ILLEGAL_CHAR_ERROR */
if( mrglBufCount > MAX_PATH )
errType = PATH_ERROR;
else
mrglBuffer[ mrglBufCount++ ] = ch;
if( ( ch = fgetByte() ) == '#' )
{
/* Skip comment section and trailing whitespace */
while( ch != '\r' && ch != '\n' && ch != CPM_EOF && ch != FEOF )
ch = fgetByte();
break;
}
}
/* Remember we've just passed a CR if necessary */
if( ch == '\r' )
seenCR = TRUE;
/* Skip trailing whitespace and add der terminador */
while( mrglBufCount && \
( ( theCh = mrglBuffer[ mrglBufCount - 1 ] ) == ' ' || theCh == '\t' ) )
mrglBufCount--;
mrglBuffer[ mrglBufCount ] = '\0';
/* Process the line unless its a blank or comment line */
if( mrglBufCount && *mrglBuffer != '#' )
{
/* At the first error we must print a newline to get the text
away from the HPACK title message unless we've already
printed one as part of the listFile message */
if( ( errType != NO_ERROR ) && firstError )
{
firstError = FALSE;
#ifndef GUI
hputchar( '\n' );
#endif /* !GUI */
}
switch( errType )
{
case PATH_ERROR:
mrglBuffer[ screenWidth - strlen( MESG_PATH_s__TOO_LONG_LINE_d ) - 3 ] = '\0';
/* Truncate to fit screen size (3 = '%s' + 1) */
#ifdef GUI
itoa( line, string, 10 );
alert( ALERT_PATH_TOO_LONG_LINE, string );
#else
hprintf( MESG_PATH_s__TOO_LONG_LINE_d, mrglBuffer, line );
#endif /* GUI */
errCount++;
break;
case ILLEGAL_CHAR_ERROR:
#ifdef GUI
itoa( line, string, 10 );
alert( ALERT_BAD_CHAR_IN_FILENAME_LINE, string );
if( errPos ); /* Get rid of "Not used" warning */
#else
hprintf( "> %s\n ", mrglBuffer );
while( errPos-- )
hputchar( ' ' );
hprintf( MESG_BAD_CHAR_IN_FILENAME_LINE_d, line );
#endif /* GUI */
errCount++;
break;
default:
addFilespec( ( char * ) mrglBuffer );
}
}
else
/* It may be a script language command */
if( strlen( ( char * ) mrglBuffer ) > 2 && mrglBuffer[ 1 ] != ' ' )
{
/* At the moment just complain about it */
#ifdef GUI
alert( ALERT_UNKNOWN_SCRIPT_COMMAND, ( char * ) mrglBuffer );
#else
hprintf( WARN_UNKNOWN_SCRIPT_COMMAND_s, mrglBuffer );
#endif /* GUI */
errCount++;
}
/* Handle special-case of ^Z if listFile came off an MSDOS system */
if( ch == CPM_EOF )
ch = FEOF;
/* Exit if there are too many errors */
if( errCount >= MAX_ERRORS )
break;
line++;
}
hclose( listFileFD );
/* Exit if there were errors */
if( errCount )
error( N_ERRORS_DETECTED_IN_SCRIPTFILE, ( errCount >= MAX_ERRORS ) ? \
MESG_MAXIMUM_LEVEL_OF : "", errCount );
}