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

📄 dir.c

📁 DOS操用系统源代码,C语言编写,对操作系统的认识有很大的帮助.
💻 C
字号:
/****************************************************************/
/*								*/
/*			      dir.c				*/
/*								*/
/*		        DOS "dir" Command 			*/
/*								*/
/*			 November 6, 1991			*/
/*								*/
/*			Copyright (c) 1995			*/
/*			Pasquale J. Villani			*/
/*			All Rights Reserved			*/
/*								*/
/* This file is part of DOS-C.					*/
/*								*/
/* DOS-C is free software; you can redistribute it and/or	*/
/* modify it under the terms of the GNU General Public License	*/
/* as published by the Free Software Foundation; either version	*/
/* 2, or (at your option) any later version.			*/
/*								*/
/* DOS-C is distributed in the hope that it will be useful, but	*/
/* WITHOUT ANY WARRANTY; without even the implied warranty of	*/
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See	*/
/* the GNU General Public License for more details.		*/
/*								*/
/* You should have received a copy of the GNU General Public	*/
/* License along with DOS-C; see the file COPYING.  If not,	*/
/* write to the Free Software Foundation, 675 Mass Ave,		*/
/* Cambridge, MA 02139, USA.					*/
/****************************************************************/


/* $Logfile:   C:/dos-c/src/command/dir.c_v  $ */

/* $Log:   C:/dos-c/src/command/dir.c_v  $ 
 * 
 *    Rev 1.4   31 Jan 1998  8:12:26   patv
 * Put preprocessor switch for version strings and changed log strings
 * 
 *    Rev 1.3   22 Jan 1998  4:51:42   patv
 * Fixed bug in bytes free calculation.
 * 
 *    Rev 1.2   29 Aug 1996 13:07:00   patv
 * Bug fixes for v0.91b
 * 
 *    Rev 1.1   01 Sep 1995 18:04:32   patv
 * First GPL release.
 * 
 *    Rev 1.0   02 Jul 1995 10:01:40   patv
 * Initial revision.
 */
/* $EndLog$ */

#include "../../hdr/portab.h"
#include "globals.h"
#include "proto.h"

#ifdef VERSION_STRINGS
static BYTE *RcsId = "$Header:   C:/dos-c/src/command/dir.c_v   1.4   31 Jan 1998  8:12:26   patv  $";
#endif

#ifdef PROTO
COUNT chk_line(COUNT);
#else
COUNT chk_line();
#endif


#define D_ALL	D_NORMAL | D_RDONLY | D_HIDDEN | D_SYSTEM | D_DIR | D_ARCHIVE


BOOL dir(argc, argv)
COUNT argc;
BYTE *argv[];
{
	WORD count = 0, disp_line, columns = 0;
	ULONG total = 0l;
	BYTE vid[67], *ext;
	BYTE cudir[67];
	BYTE sdrive[2];
	dmatch dmp;
	COUNT at_mask, at_pat;
	UCOUNT free_clst, sec_size, clst_size, n_clst;
	BOOL wflag, pflag, lflag, bflag;
	COUNT driveno = -1, cudrvno;
	BYTE pattern[MAX_CMDLINE] = "", formatted[MAX_CMDLINE];
	BYTE path[MAX_CMDLINE] = "", sopt[MAX_CMDLINE] = "";

	/* parse for options						*/
	wflag = pflag = lflag = bflag = count = FALSE;
	dosopt("$d$p*[a:wplb]+", (BYTE FAR *)tail,
		&driveno, path, pattern, sopt, &wflag, &pflag, &lflag, &bflag);

	/* Set defaults for file name and path if not supplied.		*/
	if(strcmp(path, "") == 0)
		strcpy(path, ".");
	if(strcmp(pattern,"") == 0)
		strcpy(pattern,"*.*");

	/* Intialize the dta to put the dir info into			*/
	DosSetDta((BYTE FAR *)&dmp);

	/* Get the current drive, so we can switch back.		*/
	cudrvno = DosGetDrive();

	/* Switch to the requested directory to list			*/
	DosSetDrive(driveno < 0 ? cudrvno : driveno);

	/* Get the current directory. Note that the DOS system call	*/
	/* does not return drive or leading '\', so we need to add	*/
	/* them.							*/
	cudir[0] = '\\';
	DosPwd(DosGetDrive() + 1, (BYTE FAR *)&cudir[1]);

	/* Change to the path and then test the file name. If it is a	*/
	/* directory, switch to it, because the user wants a listing of	*/
	/* its content.							*/
	if(DosCd((BYTE FAR *)path) != SUCCESS)
	{
		error_message(INV_DIR);
		DosSetDrive(cudrvno);
		return FALSE;
	}
	if(!iswild(pattern))
	{
		if(DosFindFirst(D_DIR, (BYTE FAR *)pattern) != SUCCESS)
		{
			error_message(FILE_NOT_FOUND);
			return TRUE;
		}
		else
		{
			if(dmp.dm_attr_fnd & D_DIR)
			{
				if(DosCd((BYTE FAR *)pattern) != SUCCESS)
				{
					error_message(INV_DIR);
					DosSetDrive(cudrvno);
					return FALSE;
				}
				else
					strcpy(pattern, "*.*");
			}
		}
	}


	/* Get the new directory.					*/
	path[0] = '\\';
	DosPwd(DosGetDrive() + 1, (BYTE FAR *)&path[1]);

	/* Intialize the dta to put the dir info into			*/
	DosSetDta((BYTE FAR *)&dmp);

	/* Get the volume label				*/
	if(DosFindFirst(D_VOLID, (BYTE FAR *)"*.*") != SUCCESS)
		sprintf(vid, "has no label");
	else
	{
		for(ext = dmp.dm_name; *ext != NULL; ext++)
			if(*ext == '.')
			{
				*ext++ = NULL;
				break;
			}
		sprintf(vid, "is %s%s", dmp.dm_name, ext);
	}

	/* Display the header, if not turned off			*/
	sdrive[0] = 'A' + DosGetDrive();
	sdrive[1] = NULL;
	if(bflag)
		disp_line = 0;
	else
		disp_line = 4;
	if(!bflag)
	{
		printf("\n Volume in drive %s %s\n", sdrive, vid);
		printf(" Directory of %s:%s\n\n", sdrive, path);
	}

	/* Build the attribute mask and pattern				*/
	at_mask = *sopt == '\0' ? D_RDONLY | D_HIDDEN | D_SYSTEM : 0;
	at_pat = 0;
	for(ext = sopt; *ext != '\0'; ++ext)
	{
		if(*ext == '-')
		{
			++ext;
			switch(tolower(*ext))
			{
			case 'a':
				at_mask |= D_ARCHIVE;
				at_pat &= ~D_ARCHIVE;
				break;

			case 'd':
				at_mask |= D_DIR;
				at_pat &= ~D_DIR;
				break;

			case 'r':
				at_mask |= D_RDONLY;
				at_pat &= ~D_RDONLY;
				break;

			case 'h':
				at_mask |= D_HIDDEN;
				at_pat &= ~D_HIDDEN;
				break;

			case 's':
				at_mask |= D_SYSTEM;
				at_pat &= ~D_SYSTEM;
				break;
			}
		}
		else
		{
			switch(tolower(*ext))
			{
			case 'a':
				at_mask |= D_ARCHIVE;
				at_pat |= D_ARCHIVE;
				break;

			case 'd':
				at_mask |= D_DIR;
				at_pat |= D_DIR;
				break;

			case 'r':
				at_mask |= D_RDONLY;
				at_pat |= D_RDONLY;
				break;

			case 'h':
				at_mask |= D_HIDDEN;
				at_pat |= D_HIDDEN;
				break;

			case 's':
				at_mask |= D_SYSTEM;
				at_pat |= D_SYSTEM;
				break;
			}
		}
	}

	if(DosFindFirst(D_ALL, (BYTE FAR *)pattern) != SUCCESS)
	{
		error_message(FILE_NOT_FOUND);
		return TRUE;
	}

	if(wflag)
	{
		do
		{
			char *p;

			if((*sopt != 0) && !((dmp.dm_attr_fnd & at_mask) == at_pat))
				continue;
			if(dmp.dm_attr_fnd & D_DIR)
			{
				if(bflag && *dmp.dm_name == '.')
					continue;
				sprintf(formatted, "[%s]", dmp.dm_name);
				if(lflag)
					strlwr(formatted);
				printf("%-14s ", formatted);
				++columns;
				if(columns == 5)
				{
					if(pflag)
						disp_line = chk_line(disp_line);
					printf("\n");
					columns = 0;
				}
			}
			else
			{
				ext = "   ";
				sprintf(formatted, "%s", dmp.dm_name);
				if(lflag)
					strlwr(formatted);
				printf("%-15s",formatted);
				++columns;
				if(columns == 5)
				{
					if(pflag)
						disp_line = chk_line(disp_line);
					printf("\n");
					columns = 0;
				}
			}
		++count;
		total += dmp.dm_size;
		}
		while(DosFindNext() == SUCCESS);
	}
	else
	{
		do
		{
			WORD hour = TM_HOUR(dmp.dm_time);

			if((*sopt != 0) && !((dmp.dm_attr_fnd & at_mask) == at_pat))
				continue;
			if(dmp.dm_name[0] == '.')
				ext = "";
			else
				for(ext = dmp.dm_name; *ext != NULL; ext++)
				{
					if(*ext == '.')
					{
						*ext++ = NULL;
						break;
					}
				}
			if(lflag)
			{
				strlwr(dmp.dm_name);
				strlwr(ext);
			}
			if(dmp.dm_attr_fnd & D_DIR)
			{
				if(bflag && *dmp.dm_name == '.')
					continue;
				if(pflag)
					disp_line = chk_line(disp_line);
				printf(bflag ? "\n%s.%s" : "\n   %8s %3s  <DIR>      %-2d-%-02d-%-02d  %-2d:%-02d%s",
					dmp.dm_name, ext,
					DT_MONTH(dmp.dm_date),
					DT_DAY(dmp.dm_date),
					(DT_YEAR(dmp.dm_date) + 1980) % 100,
					hour > 12 ? hour - 12 : (hour == 0) ? 12 : hour,
					TM_MIN(dmp.dm_time),
					hour >= 12 ? "p" : "a");
			}
			else
			{
				if(pflag)
					disp_line = chk_line(disp_line);
				printf(bflag ? "\n%s.%s" : "\n   %8s %3s %-10ld  %-2d-%-02d-%-02d  %-2d:%-02d%s",
					dmp.dm_name, ext, dmp.dm_size,
					DT_MONTH(dmp.dm_date),
					DT_DAY(dmp.dm_date),
					(DT_YEAR(dmp.dm_date) + 1980) % 100,
					hour > 12 ? hour - 12 : (hour == 0) ? 12 : hour,
					TM_MIN(dmp.dm_time),
					hour >= 12 ? "p" : "a");
			}
			++count;
			total += dmp.dm_size;
		}
		while(DosFindNext() == SUCCESS);
	}

	/* /b does not print any statistics				*/
	if(bflag)
	{
		printf("\n\n");
	}
	else
	/* Now print the available free bytes (It's really clusters	*/
	/* translated to bytes.						*/
	{
		DosFree(0, (COUNT FAR *)&clst_size,(COUNT FAR *) &free_clst, (COUNT FAR *)&sec_size, (COUNT FAR *)&n_clst);
		printf("\n  %-10d file(s)   %-10ld bytes\n", count, total);
		printf(  "                       %-10lu bytes free\n\n",
			(ULONG)free_clst
			* (ULONG)sec_size
			* (ULONG)clst_size);
	}

	/* Change back to the current drive and directory, so that we	*/
	/* look like we just did a listing without all the gymnastics.	*/
	if((DosCd((BYTE FAR *)cudir)) != SUCCESS)
	{
		DosSetDrive(cudrvno);
		error_message(INV_DIR);
		return FALSE;
	}
	else
	{
		DosSetDrive(cudrvno);
		return TRUE;
	}
}

static COUNT chk_line(disp_line)
COUNT disp_line;
{
	BYTE line[MAX_CMDLINE];

	if(disp_line == 23)
	{
		printf("\nStrike a key when ready . . .");
		DosRead(STDIN, line, MAX_CMDLINE);
		return 0;
	}
	return ++disp_line;
}




⌨️ 快捷键说明

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