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

📄 cmd.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
				*cp++ = _totlower (*rest++);
			if (*rest == _T('"'))
				rest++;
		}
		else
		{
			while (!IsDelimiter (*rest))
				*cp++ = _totlower (*rest++);
		}


		/* Terminate first word */
		*cp = _T('\0');

		/* Do not limit commands to MAX_PATH */
		/*
		if(_tcslen(com) > MAX_PATH)
		{
			error_bad_command();
			cmd_free(com);
			return;
		}
		*/

		/* Skip over whitespace to rest of line, exclude 'echo' command */
		if (_tcsicmp (com, _T("echo"))) 
		{
			while (_istspace (*rest))
			rest++;
		}

		/* Scan internal command table */
		for (cmdptr = cmds;; cmdptr++)
		{
			/* If end of table execute ext cmd */
			if (cmdptr->name == NULL)
			{
				Execute (line, com, rest);
				break;
			}

			if (!_tcscmp (com, cmdptr->name))
			{
				cmdptr->func (com, rest);
				break;
			}

			/* The following code handles the case of commands like CD which
			 * are recognised even when the command name and parameter are
			 * not space separated.
			 *
			 * e.g dir..
			 * cd\freda
			 */

			/* Get length of command name */
			cl = _tcslen (cmdptr->name);

			if ((cmdptr->flags & CMD_SPECIAL) &&
			    (!_tcsncmp (cmdptr->name, com, cl)) &&
			    (_tcschr (_T("\\.-"), *(com + cl))))
			{
				/* OK its one of the specials...*/

				/* Terminate first word properly */
				com[cl] = _T('\0');

				/* Call with new rest */
				cmdptr->func (com, cstart + cl);
				break;
			}
		}
	}
	cmd_free(com);
}


/*
 * process the command line and execute the appropriate functions
 * full input/output redirection and piping are supported
 */

VOID ParseCommandLine (LPTSTR cmd)
{
	TCHAR szMsg[RC_STRING_MAX_SIZE];
	TCHAR cmdline[CMDLINE_LENGTH];
	LPTSTR s;
#ifdef FEATURE_REDIRECTION
	TCHAR in[CMDLINE_LENGTH] = _T("");
	TCHAR out[CMDLINE_LENGTH] = _T("");
	TCHAR err[CMDLINE_LENGTH] = _T("");
	TCHAR szTempPath[MAX_PATH] = _T(".\\");
	TCHAR szFileName[2][MAX_PATH] = {_T(""), _T("")};
	HANDLE hFile[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
	LPTSTR t = NULL;
	INT  num = 0;
	INT  nRedirFlags = 0;
	INT  Length;
	UINT Attributes;
	BOOL bNewBatch = TRUE;
	HANDLE hOldConIn;
	HANDLE hOldConOut;
	HANDLE hOldConErr;
#endif /* FEATURE_REDIRECTION */

	_tcscpy (cmdline, cmd);
	s = &cmdline[0];

#ifdef _DEBUG
	DebugPrintf (_T("ParseCommandLine: (\'%s\')\n"), s);
#endif /* DEBUG */

#ifdef FEATURE_ALIASES
	/* expand all aliases */
	ExpandAlias (s, CMDLINE_LENGTH);
#endif /* FEATURE_ALIAS */

#ifdef FEATURE_REDIRECTION
	/* find the temp path to store temporary files */
	Length = GetTempPath (MAX_PATH, szTempPath);
	if (Length > 0 && Length < MAX_PATH)
	{
		Attributes = GetFileAttributes(szTempPath);
		if (Attributes == 0xffffffff ||
		    !(Attributes & FILE_ATTRIBUTE_DIRECTORY))
		{
			Length = 0;
		}
	}
	if (Length == 0 || Length >= MAX_PATH)
	{
		_tcscpy(szTempPath, _T(".\\"));
	}
	if (szTempPath[_tcslen (szTempPath) - 1] != _T('\\'))
		_tcscat (szTempPath, _T("\\"));

	/* get the redirections from the command line */
	num = GetRedirection (s, in, out, err, &nRedirFlags);

	/* more efficient, but do we really need to do this? */
	for (t = in; _istspace (*t); t++)
		;
	_tcscpy (in, t);

	for (t = out; _istspace (*t); t++)
		;
	_tcscpy (out, t);

	for (t = err; _istspace (*t); t++)
		;
	_tcscpy (err, t);

	if(bc && !_tcslen (in) && _tcslen (bc->In))
		_tcscpy(in, bc->In);
	if(bc && !out[0] && _tcslen(bc->Out))
	{
		nRedirFlags |= OUTPUT_APPEND;
		_tcscpy(out, bc->Out);
	}
	if(bc && !_tcslen (err) && _tcslen (bc->Err))
	{
		nRedirFlags |= ERROR_APPEND;
		_tcscpy(err, bc->Err);
	}


	/* Set up the initial conditions ... */
	/* preserve STDIN, STDOUT and STDERR handles */
	hOldConIn  = GetStdHandle (STD_INPUT_HANDLE);
	hOldConOut = GetStdHandle (STD_OUTPUT_HANDLE);
	hOldConErr = GetStdHandle (STD_ERROR_HANDLE);

	/* redirect STDIN */
	if (in[0])
	{
		HANDLE hFile;
		SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};

	/* we need make sure the LastError msg is zero before calling CreateFile */
		SetLastError(0);

	/* Set up pipe for the standard input handler */
		hFile = CreateFile (in, GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING,
		                    FILE_ATTRIBUTE_NORMAL, NULL);
		if (hFile == INVALID_HANDLE_VALUE)
		{
			LoadString(CMD_ModuleHandle, STRING_CMD_ERROR1, szMsg, RC_STRING_MAX_SIZE);
			ConErrPrintf(szMsg, in);
			return;
		}

		if (!SetStdHandle (STD_INPUT_HANDLE, hFile))
		{
			LoadString(CMD_ModuleHandle, STRING_CMD_ERROR1, szMsg, RC_STRING_MAX_SIZE);
			ConErrPrintf(szMsg, in);
			return;
		}
#ifdef _DEBUG
		DebugPrintf (_T("Input redirected from: %s\n"), in);
#endif
	}

	/* Now do all but the last pipe command */
	*szFileName[0] = _T('\0');
	hFile[0] = INVALID_HANDLE_VALUE;

	while (num-- > 1)
	{
		SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};

		/* Create unique temporary file name */
		GetTempFileName (szTempPath, _T("CMD"), 0, szFileName[1]);

		/* we need make sure the LastError msg is zero before calling CreateFile */
		SetLastError(0);

		/* Set current stdout to temporary file */
		hFile[1] = CreateFile (szFileName[1], GENERIC_WRITE, 0, &sa,
				       TRUNCATE_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);

		if (hFile[1] == INVALID_HANDLE_VALUE)
		{
			LoadString(CMD_ModuleHandle, STRING_CMD_ERROR2, szMsg, RC_STRING_MAX_SIZE);
			ConErrPrintf(szMsg);
			return;
		}

		SetStdHandle (STD_OUTPUT_HANDLE, hFile[1]);

		DoCommand (s);

		/* close stdout file */
		SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
		if ((hFile[1] != INVALID_HANDLE_VALUE) && (hFile[1] != hOldConOut))
		{
			CloseHandle (hFile[1]);
			hFile[1] = INVALID_HANDLE_VALUE;
		}

		/* close old stdin file */
		SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
		if ((hFile[0] != INVALID_HANDLE_VALUE) && (hFile[0] != hOldConIn))
		{
			/* delete old stdin file, if it is a real file */
			CloseHandle (hFile[0]);
			hFile[0] = INVALID_HANDLE_VALUE;
			DeleteFile (szFileName[0]);
			*szFileName[0] = _T('\0');
		}

		/* copy stdout file name to stdin file name */
		_tcscpy (szFileName[0], szFileName[1]);
		*szFileName[1] = _T('\0');

		/* we need make sure the LastError msg is zero before calling CreateFile */
		SetLastError(0);

		/* open new stdin file */
		hFile[0] = CreateFile (szFileName[0], GENERIC_READ, 0, &sa,
		                       OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
		SetStdHandle (STD_INPUT_HANDLE, hFile[0]);

		s = s + _tcslen (s) + 1;
	}

	/* Now set up the end conditions... */
	/* redirect STDOUT */
	if (out[0])
	{
		/* Final output to here */
		HANDLE hFile;
		SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};

		/* we need make sure the LastError msg is zero before calling CreateFile */
		SetLastError(0);

		hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, &sa,
		                    (nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
		                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);

		if (hFile == INVALID_HANDLE_VALUE)
		{
			INT size = _tcslen(out)-1;

			if (out[size] != _T(':'))
			{
				LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
				ConErrPrintf(szMsg, out);
				return;
			}

			out[size]=_T('\0');
			hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, &sa,
			                    (nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
			                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);

			if (hFile == INVALID_HANDLE_VALUE)
			{
				LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
				ConErrPrintf(szMsg, out);
				return;
			}

		}

		if (!SetStdHandle (STD_OUTPUT_HANDLE, hFile))
		{
			LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
			ConErrPrintf(szMsg, out);
			return;
		}

		if (nRedirFlags & OUTPUT_APPEND)
		{
			LONG lHighPos = 0;

			if (GetFileType (hFile) == FILE_TYPE_DISK)
				SetFilePointer (hFile, 0, &lHighPos, FILE_END);
		}
#ifdef _DEBUG
		DebugPrintf (_T("Output redirected to: %s\n"), out);
#endif
	}
	else if (hOldConOut != INVALID_HANDLE_VALUE)
	{
		/* Restore original stdout */
		HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
		SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
		if (hOldConOut != hOut)
			CloseHandle (hOut);
		hOldConOut = INVALID_HANDLE_VALUE;
	}

	/* redirect STDERR */
	if (err[0])
	{
		/* Final output to here */
		HANDLE hFile;
		SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};

		if (!_tcscmp (err, out))
		{
#ifdef _DEBUG
			DebugPrintf (_T("Stdout and stderr will use the same file!!\n"));
#endif
			DuplicateHandle (GetCurrentProcess (),
			                 GetStdHandle (STD_OUTPUT_HANDLE),
			                 GetCurrentProcess (),
			                 &hFile, 0, TRUE, DUPLICATE_SAME_ACCESS);
		}
		else
		{
			hFile = CreateFile (err,
			                    GENERIC_WRITE,
			                    FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
			                    &sa,
			                    (nRedirFlags & ERROR_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
			                    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
			                    NULL);
			if (hFile == INVALID_HANDLE_VALUE)
			{
				LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
				ConErrPrintf(szMsg, err);
				return;
			}
		}

		if (!SetStdHandle (STD_ERROR_HANDLE, hFile))
		{
			LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
			ConErrPrintf(szMsg, err);
			return;
		}

		if (nRedirFlags & ERROR_APPEND)
		{
			LONG lHighPos = 0;

			if (GetFileType (hFile) == FILE_TYPE_DISK)
				SetFilePointer (hFile, 0, &lHighPos, FILE_END);
		}
#ifdef _DEBUG
		DebugPrintf (_T("Error redirected to: %s\n"), err);
#endif
	}
	else if (hOldConErr != INVALID_HANDLE_VALUE)
	{
		/* Restore original stderr */
		HANDLE hErr = GetStdHandle (STD_ERROR_HANDLE);
		SetStdHandle (STD_ERROR_HANDLE, hOldConErr);
		if (hOldConErr != hErr)
			CloseHandle (hErr);
		hOldConErr = INVALID_HANDLE_VALUE;
	}

	if(bc)
		bNewBatch = FALSE;
#endif

	/* process final command */
	DoCommand (s);

#ifdef FEATURE_REDIRECTION
	if(bNewBatch && bc)
		AddBatchRedirection(in, out, err);
	/* close old stdin file */
#if 0  /* buggy implementation */
	SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
	if ((hFile[0] != INVALID_HANDLE_VALUE) &&
		(hFile[0] != hOldConIn))
	{
		/* delete old stdin file, if it is a real file */
		CloseHandle (hFile[0]);
		hFile[0] = INVALID_HANDLE_VALUE;
		DeleteFile (szFileName[0]);
		*szFileName[0] = _T('\0');
	}

	/* Restore original STDIN */
	if (hOldConIn != INVALID_HANDLE_VALUE)
	{
		HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
		SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
		if (hOldConIn != hIn)
			CloseHandle (hIn);
		hOldConIn = INVALID_HANDLE_VALUE;
	}
	else
	{
#ifdef _DEBUG
		DebugPrintf (_T("Can't restore STDIN! Is invalid!!\n"), out);
#endif
	}
#endif  /* buggy implementation */


	if (hOldConIn != INVALID_HANDLE_VALUE)
	{
		HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
		SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
		if (hIn == INVALID_HANDLE_VALUE)
		{
#ifdef _DEBUG
			DebugPrintf (_T("Previous STDIN is invalid!!\n"));
#endif
		}
		else
		{
			if (GetFileType (hIn) == FILE_TYPE_DISK)
			{
				if (hFile[0] == hIn)
				{
					CloseHandle (hFile[0]);
					hFile[0] = INVALID_HANDLE_VALUE;
					DeleteFile (szFileName[0]);
					*szFileName[0] = _T('\0');
				}
				else
				{
#ifdef _DEBUG
					DebugPrintf (_T("hFile[0] and hIn dont match!!!\n"));
#endif
				}
			}
		}
	}


	/* Restore original STDOUT */
	if (hOldConOut != INVALID_HANDLE_VALUE)
	{
		HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
		SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
		if (hOldConOut != hOut)
			CloseHandle (hOut);
		hOldConOut = INVALID_HANDLE_VALUE;
	}

	/* Restore original STDERR */
	if (hOldConErr != INVALID_HANDLE_VALUE)
	{
		HANDLE hErr = GetStdHandle (STD_ERROR_HANDLE);
		SetStdHandle (STD_ERROR_HANDLE, hOldConErr);
		if (hOldConErr != hErr)
			CloseHandle (hErr);
		hOldConErr = INVALID_HANDLE_VALUE;
	}
#endif /* FEATURE_REDIRECTION */
}

BOOL
GrowIfNecessary ( UINT needed, LPTSTR* ret, UINT* retlen )
{
	if ( *ret && needed < *retlen )
		return TRUE;
	*retlen = needed;
	if ( *ret )
		cmd_free ( *ret );
	*ret = (LPTSTR)cmd_alloc ( *retlen * sizeof(TCHAR) );
	if ( !*ret )
		SetLastError ( ERROR_OUTOFMEMORY );
	return *ret != NULL;
}

LPCTSTR
GetEnvVarOrSpecial ( LPCTSTR varName )
{
	static LPTSTR ret = NULL;
	static UINT retlen = 0;
	UINT size;

	size = GetEnvironmentVariable ( varName, ret, retlen );
	if ( size > retlen )
	{
		if ( !GrowIfNecessary ( size, &ret, &retlen ) )
			return NULL;
		size = GetEnvironmentVariable ( varName, ret, retlen );
	}
	if ( size )
		return ret;

	/* env var doesn't exist, look for a "special" one */
	/* %CD% */
	if (_tcsicmp(varName,_T("cd")) ==0)
	{
		size = GetCurrentDirectory ( retlen, ret );
		if ( size > retlen )
		{
			if ( !GrowIfNecessary ( size, &ret, &retlen ) )
				return NULL;
			size = GetCurrentDirectory ( retlen, ret );
		}
		if ( !size )
			return NULL;
		return ret;
	}
	/* %TIME% */
	else if (_tcsicmp(varName,_T("time")) ==0)
	{
		SYSTEMTIME t;
		if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
			return NULL;
		GetSystemTime(&t);
		_sntprintf ( ret, retlen, _T("%02d%c%02d%c%02d%c%02d"),
			t.wHour, cTimeSeparator, t.wMinute, cTimeSeparator,
			t.wSecond, cDecimalSeparator, t.wMilliseconds / 10);
		return ret;
	}
	/* %DATE% */
	else if (_tcsicmp(varName,_T("date")) ==0)
	{

		if ( !GrowIfNecessary ( GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0), &ret, &retlen ) )
			return NULL;

		size = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, ret, retlen);

		if ( !size )
			return NULL;
		return ret;
	}

	/* %RANDOM% */
	else if (_tcsicmp(varName,_T("random")) ==0)
	{
		if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
			return NULL;
		/* Get random number */
		_itot(rand(),ret,10);
		return ret;
	}

	/* %CMDCMDLINE% */
	else if (_tcsicmp(varName,_T("cmdcmdline")) ==0)
	{
		return GetCommandLine();
	}

	/* %CMDEXTVERSION% */
	else if (_tcsicmp(varName,_T("cmdextversion")) ==0)
	{
		if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
			return NULL;
		/* Set version number to 2 */
		_itot(2,ret,10);
		return ret;
	}

	/* %ERRORLEVEL% */
	else if (_tcsicmp(varName,_T("errorlevel")) ==0)
	{
		if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
			return NULL;
		_itot(nErrorLevel,ret,10);
		return ret;
	}

	GrowIfNecessary(_tcslen(varName) + 2, &ret, &retlen);
	_stprintf(ret,_T("%%%s%%"),varName);
	return ret; /* not found - return orginal string */
}

LPCTSTR
GetParsedEnvVar ( LPCTSTR varName, UINT* varNameLen, BOOL ModeSetA )
{
	static LPTSTR ret = NULL;
	static UINT retlen = 0;
	LPTSTR p, tmp;
	UINT size;

	if ( varNameLen )
		*varNameLen = 0;
	SetLastError(0);
	if ( *varName++ != '%' )
		return NULL;
	switch ( *varName )
	{
	case _T('0'):
	case _T('1'):
	case _T('2'):
	case _T('3'):
	case _T('4'):
	case _T('5'):
	case _T('6'):
	case _T('7'):
	case _T('8'):
	case _T('9'):

⌨️ 快捷键说明

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