⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 expand.c

📁 DOS 源代码 系列之 command 源码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * 			returned FIND_BUF structure.	(Versions of DOS prior to 3.1 did
 * 			not support networks, so we can be fairly certain that the
 * 			reserved fields will be consistent.)
 *
 * 			If we experience an error during this function, we skip the
 * 			verification test and exit FALSE, as if the files were different.
 *
 * HISTORY: M001	Created.
 *
 */

BOOL IsSourceDest( char *pszSource, char *pszDest )
{
	int i;
	union REGS inregs, outregs;
	struct SREGS segregs;
	char szSrcAbs[MAXFILESPECLEN];		/* Absolute source pathname */
	char szDestAbs[MAXFILESPECLEN];		/* Absolute dest. pathname */
	struct find_t SrcFileInfo; 			/* Source file information buffer */
	struct find_t DestFileInfo;			/* Dest. file information buffer */
#ifdef DEBUG
	struct FIND_BUF * s;
#endif

	/* For DOS versions >= 3.1, use DOS Truename function */

	if( _osmajor > 3 || (_osmajor == 3 && _osminor >= 1) )
	{
		/* Get segment register values, and ensure they are the same (for safety:
		 * they should be the same since this is SMALL model).
		 */
		segread( &segregs );
		if( segregs.ds != segregs.es || segregs.ds != segregs.ss )
			return(FALSE);		/* Skip test */

		/* Get absolute source pathname */
		inregs.h.ah = 0x60;								/* DOS Truename function */
		inregs.x.si = (unsigned) pszSource;			/* Relative source path */
		inregs.x.di = (unsigned) szSrcAbs;			/* Buffer */
		intdosx( &inregs, &outregs, &segregs );
		if( outregs.x.cflag != 0 )
			return(FALSE); 	/* Skip test */

		/* Get absolute destination pathname */
		inregs.h.ah = 0x60;								/* DOS Truename function */
		inregs.x.si = (unsigned) pszDest;			/* Relative dest path */
		inregs.x.di = (unsigned) szDestAbs;			/* Buffer */
		intdosx( &inregs, &outregs, &segregs );
		if( outregs.x.cflag != 0 )
			return(FALSE); 	/* Skip test */

#ifdef DEBUG
		printf("Source = %s, Dest = %s\n", szSrcAbs, szDestAbs);
#endif

		if( strcmpi(szSrcAbs, szDestAbs) == 0 )
			return(TRUE);		/* Source == Destination */
	}
	else			/* DOS version >= 2.1 */
	if( (_osmajor == 3 && _osminor == 0) || (_osmajor == 2 && _osminor >= 1) )
	{
		/* Use _dos_findfirst(); compare file information structures. */

		/* Clear File Information Buffers */

		memset(&SrcFileInfo,  0, sizeof(struct find_t));
		memset(&DestFileInfo, 0, sizeof(struct find_t));

		/* Source file */
		if( _dos_findfirst(pszSource, _A_NORMAL, &SrcFileInfo) != 0 )
			return(FALSE); 	/* Skip test */

		/* Dest. file */
		if( _dos_findfirst(pszDest, _A_NORMAL, &DestFileInfo) != 0 )
			return(FALSE); 	/* Skip test */

#ifdef DEBUG
		s = (struct FIND_BUF *) &SrcFileInfo;
		printf(	"Source:  Drive=0x%hx  Name=%.11s  SAttr=0x%hx\n" \
					"LastEnt=0x%hx  DirStart=0x%hx  NetId=%.4s  Attr=0x%hx\n" \
					"Time=0x%hx  Date=0x%hx  Size=0x%lx  Name=%s\n\n",
					s->FIND_BUF_DRIVE,			/* drive of search */
					s->FIND_BUF_NAME,				/* formatted name */
					s->FIND_BUF_SATTR,			/* attribute of search */
					s->FIND_BUF_LASTENT,			/* LastEnt */
					s->FIND_BUF_DIRSTART,		/* DirStart */
					s->FIND_BUF_NETID,			/* Reserved for NET */
					SrcFileInfo.attrib,			/* attribute found */
					SrcFileInfo.wr_time,			/* time */
					SrcFileInfo.wr_date,			/* date */
					SrcFileInfo.size, 			/* size */
					SrcFileInfo.name );			/* packed name */
		s = (struct FIND_BUF *) &DestFileInfo;
		printf(	"Dest:    Drive=0x%hx  Name=%.11s  SAttr=0x%hx\n" \
					"LastEnt=0x%hx  DirStart=0x%hx  NetId=%.4s  Attr=0x%hx\n" \
					"Time=0x%hx  Date=0x%hx  Size=0x%lx  Name=%s\n\n",
					s->FIND_BUF_DRIVE,			/* drive of search */
					s->FIND_BUF_NAME,				/* formatted name */
					s->FIND_BUF_SATTR,			/* attribute of search */
					s->FIND_BUF_LASTENT,			/* LastEnt */
					s->FIND_BUF_DIRSTART,		/* DirStart */
					s->FIND_BUF_NETID,			/* Reserved for NET */
					DestFileInfo.attrib,			/* attribute found */
					DestFileInfo.wr_time,		/* time */
					DestFileInfo.wr_date,		/* date */
					DestFileInfo.size,			/* size */
					DestFileInfo.name );			/* packed name */
#endif

		/* Zero-out NET_ID members, in case they contain garbage. */
		for(i=0; i<4; i++)
		{
			((struct FIND_BUF *) &SrcFileInfo)->FIND_BUF_NETID[i] = '\0';
			((struct FIND_BUF *) &DestFileInfo)->FIND_BUF_NETID[i] = '\0';
		}

		if( memcmp(&SrcFileInfo, &DestFileInfo, sizeof(struct find_t)) == 0 )
			return(TRUE);		/* Source == Destination */
	}

	return(FALSE); 			/* Source != Destination */
}


/* BOOL PromptUser( int argc, char *$argv[] );
 *
 * Prompt the user for the source and destination files.
 *
 * ENTRY: $argv[] 	array of pointers to input parameters.
 *
 * EXIT: TRUE if user entered valid parameters; FALSE otherwise.
 * 		If TRUE, then $argv[1] -> source parameter
 * 					and  $argv[2] -> destination parameter
 *
 * HISTORY: M001	Created.
 *
 */

BOOL PromptUser( int argc, char *$argv[] )
{
	int i;

	/* Prompt for Source file, if needed. */

	if( argc == 1 )
	{
		printf(pszSRC_PROMPT1);
		while(TRUE)
		{
			printf(pszSRC_PROMPT2);

			i = GetString( $argv[1], MAX_ROW_LEN - sizeof(pszSRC_PROMPT2) );

			if( i == ABORT )
				return(FALSE);
			else
			if( i > 0 )
				break;
		}
	}

	/* Prompt for Destination file */

	printf(pszDEST_PROMPT1);
	while(TRUE)
	{
		printf(pszDEST_PROMPT2);

		i = GetString( $argv[2], MAX_ROW_LEN - sizeof(pszDEST_PROMPT2) );

		if( i == ABORT )
			return(FALSE);
		else
		if( i > 0 )
			break;
	}

	return(TRUE);
}


/* int Quit(int);
 *
 * Cleanup and exit program.
 *
 * ENTRY: Exit code.
 *
 * EXIT: None
 *
 * NOTES: NULL memory pointers are ignored by the free() and _ffree()
 * 		 functions, so we always exit through Quit(), even if the
 * 		 memory pointers haven't been initialized yet. (All the global
 * 		 memory pointers are static or external, so they are initialized
 *			 to NULL by default.)
 *
 * HISTORY: M001	Created.
 *
 */
int Quit(int rc)
{
	FreeBuffers();
	return(rc);
}


/* int GetString(char *chBuf, int iBufSiz)
 *
 * Read a line from STDIN into a buffer (chBuf).  The line is
 * terminated when the buffer is full (buffer size is specified by
 *	iBufSiz and includes a terminating NULL character) or when a newline
 * is encountered ('\n').	The line is terminated by a NULL character ('\0');
 * the newline ('\n') is not retained.	The function returns the number of
 * characters in the buffer chBuf, not including the NULL ('\0'), or ABORT
 * if the CHAR_ABORT character is encountered.
 *
 * ENTRY:	chBuf -> destination buffer
 * 			iBufSize = Maximum buffer size (including terminating NULL char.)
 *
 * EXIT: 	returns number of characters in the buffer chBuf, not including
 * 			the terminating NULL char., or ABORT if the CHAR_ABORT is
 * 			encountered.
 *
 * NOTES:	This function does not handle the case of strings which wrap.
 * 			So, in order for the BACKSPACE key to erase all the input
 * 			characters, the value of iBufSiz should limit input to 1
 * 			screen row.
 *
 * HISTORY: M001	Created.
 *
 */

int GetString(char *chBuf, int iBufSiz)
{
	int i;
	char chIn;
	int iBufEnd = iBufSiz - 1;

	/* Save characters in chBuf[] until buffer is full.	Don't
	 * exit loop until Carriage return or EOF or ABORT received.
	 */

	for( i=0;
		  ((chIn = (char) getch()) != CHAR_EOF) &&
		  (chIn != '\r') &&
		  (chIn != CHAR_ABORT); )
	{
		if( isprint(chIn) )
		{
			if( i < iBufEnd )
			{
				putch(chIn);
				chBuf[i++] = chIn;
			}
			else
				putch('\a');
		}
		else
		if( chIn == '\b' )
		{
			if( i > 0 )
			{
				putch('\b');
				putch(' ');
				putch('\b');
				chBuf[i--] = NULL;
				continue;
			}
		}
		else
			putch('\a');
	}
	chBuf[i] = EOL;		/* Zero-terminate string */

	if( chIn == CHAR_ABORT )
		i = ABORT;

	printf("\n");

#ifdef DEBUG0
	printf("i=%d, input=%s\n", i, chBuf);
#endif

	fflush(stdin);			/* Flush input buffer */

	return(i);
}


/* ProcessInput( int $argc, char *$argv[] )
 *
 * Decompress source file(s) to destination.
 *
 * ENTRY:	$argc		Number of input parameters
 * 			$argv[]	Array of ptrs to input parameters
 *
 * EXIT: 	EXIT_SUCCESS or EXIT_FAILURE.
 *
 * NOTES:
 *
 * HISTORY: M001	Created.
 *
 */

int ProcessInput( int $argc, char *$argv[] )
{
	int i;
	int rc = EXIT_SUCCESS;
	char rgchDestFileName[MAXFILESPECLEN];	/* destination file name */
	BOOL bIsDir;									/* IsDir() return value */
   long cblTotIn = 0L,
        cblTotOut = 0L;

   // initialize globals
   uchAlgorithm = uchALG_LEMPEL_ZIV;
   uchVersion = uchVER_1;

   // keep track of original drive
   wOriginalDrive = GetCurDrive();

	// Is the last parameter a directory?
	bIsDir = IsDir((LPSTR)$argv[$argc - 1]);

	if ($argc != 3 && ! bIsDir)
   {
		printf(pszNO_DEST_DIR, $argv[$argc - 1]);
		return(EXIT_FAILURE);
   }

   // Set up input, output, and ring buffers, and associated work
   // pointers.
   if (! InitBuffers())
   {
      printf(pszNOT_ENOUGH_MEM);
		return(EXIT_FAILURE);
   }

	if ($argc == 3 && ! bIsDir)
   {
		// CASE 1: expand a file to a different file

		if ( !Decompress($argv[1], $argv[2]) )
			rc = EXIT_FAILURE;
   }
	else
	{
		// CASE 2: expand a file or files to a file or files with the same name
		// in a different directory specified in $argv[$argc - 1].

		for (i = 1; i < $argc - 1; i++)
		{
			InitBufferPtrs();
			cblOutSize = 0L;
			strcpy(rgchDestFileName, $argv[$argc - 1]);
			CatPathAndFileName(rgchDestFileName, ExtractFileName($argv[i]));

			if ( !Decompress($argv[i], rgchDestFileName) )
			{
				rc = EXIT_FAILURE;
				break;
			}

			cblTotIn += cblInSize;
			cblTotOut += cblOutSize;
		}

#ifdef DEBUG0
		printf("\n       %ld bytes expanded to %ld bytes, savings: %d%%\n",
				  cblTotIn, cblTotOut, (int)(100 - 100 * cblTotOut / cblTotIn));
#endif
	}

	if( iFiles == 1 )
		printf( pszONE_FILE, iFiles);
	else
	if( iFiles > 1 )
		printf( pszTOTAL_FILES, iFiles);

	return(rc);
}


/* main(int argc, char *argv[] )
 *
 * Decompress source file(s) to destination.
 *
 * ENTRY:	argc		Number of input parameters
 * 			argv[]	Array of ptrs to input parameters
 *
 * EXIT: 	EXIT_SUCCESS or EXIT_FAILURE.
 *
 * NOTES:	This function primarily parses the command-line. The function
 * 			ProcessInput() does most of the real work.
 *
 * HISTORY: M001	main() now does command-line parsing; ProcessInput() does
 * 					most everything else.
 *
 */

int main(int argc, char *argv[])
{
	int  i;
	char *$argv[3];						/* Dummy argv[] for user prompted input. */
	char szSource[MAXFILESPECLEN];	/* Prompted source input. */
	char szDest[MAXFILESPECLEN];		/* Prompted destination input. */


	/* Parse command-line */

	if( HelpSwitchPresent(argc, argv) ) 	/* EXPAND /?: display help	*/
   {
      PrintInstructions1(); // IPG - These two lines used to be one macro
      PrintInstructions2(); // IPG - called PrintInstructions()
      		Quit(EXIT_FAILURE);
	}
	else
	if( argc == 1 || argc == 2	)	/* Missing parameters: prompt user */
	{
		/* Init. dummy argv[] so user input can be treated
		 * as command-line input parameters.
		 */

		$argv[0] = argv[0];		/* program name */

		if( argc == 2 )			/* Use cmd-line source input, if available */
			$argv[1] = argv[1];
		else
			$argv[1] = szSource; /* source input buffer */

		$argv[2] = szDest;		/* destination input buffer */

		/* Prompt user for source, $argv[1], and destination, $argv[2]. */
		if ( !PromptUser(argc, $argv) )
			Quit(EXIT_FAILURE);

		Quit( ProcessInput( 3, $argv ) );
	}
	else
	if( argc > 2 )
	{
		Quit( ProcessInput( argc, argv ) );
	}
	else
	{
		printf(pszINVALID);
		Quit(EXIT_FAILURE);
	}

	return(EXIT_SUCCESS);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -