reactos/base/shell/cmd/path.c
Hermès Bélusca-Maïto 63316df520
[CMD] Change ERRORLEVEL behaviour for commands ASSOC, PATH, PROMPT and SET.
Commands APPEND/DPATH and FTYPE are also concerned by this; however
we do not implement them in our CMD.EXE yet.

These commands set the ERRORLEVEL differently, whether or not they are
run manually from the command-line/from a .BAT file, or from a .CMD file:

- From command-line/.BAT file, these commands set the ERRORLEVEL only if
  an error occurs. So, if two commands are run consecutively and the first
  one fails, the ERRORLEVEL will remain set even if the second command
  succeeds.

- However, when being run from a .CMD file, these command will always
  set the ERRORLEVEL. In the example case described above, the second
  command that succeeds will reset the ERRORLEVEL to 0.

This behaviour is determined from the top-level batch/script file being
run. This means that, if a .BAT file is first started, then starts a
.CMD file, the commands will still behave the .BAT way; on the opposite,
if a .CMD file is first started, then starts a .BAT file, these commands
will still behave the .CMD way.

To implement this we introduce one global BATCH_TYPE enum variable that
is initialized to the corresponding batch/script file type when the
top-level script is loaded. It is reset to "none" when that script
terminates.

See https://ss64.com/nt/errorlevel.html for more details,
section "Old style .bat Batch files vs .cmd Batch scripts",
and https://groups.google.com/forum/#!msg/microsoft.public.win2000.cmdprompt.admin/XHeUq8oe2wk/LIEViGNmkK0J
(comment by Mark Zbikowski).
2020-09-23 00:22:46 +02:00

118 lines
2.6 KiB
C

/*
* PATH.C - path internal command.
*
*
* History:
*
* 17 Jul 1998 (John P Price)
* Separated commands into individual files.
*
* 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
* added config.h include
*
* 09-Dec-1998 (Eric Kohl)
* Added help text ("/?").
*
* 18-Jan-1999 (Eric Kohl)
* Unicode ready!
*
* 18-Jan-1999 (Eric Kohl)
* Redirection safe!
*
* 24-Jan-1999 (Eric Kohl)
* Fixed Win32 environment handling.
*
* 30-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
* Remove all hardcoded strings in En.rc
*/
#include "precomp.h"
#ifdef INCLUDE_CMD_PATH
/* Size of environment variable buffer */
#define ENV_BUFFER_SIZE 1024
INT cmd_path(LPTSTR param)
{
INT retval = 0;
if (!_tcsncmp(param, _T("/?"), 2))
{
ConOutResPaging(TRUE, STRING_PATH_HELP1);
return 0;
}
/* If param is empty, display the PATH environment variable */
if (!param || !*param)
{
DWORD dwBuffer;
LPTSTR pszBuffer;
pszBuffer = (LPTSTR)cmd_alloc(ENV_BUFFER_SIZE * sizeof(TCHAR));
if (!pszBuffer)
{
WARN("Cannot allocate memory for pszBuffer!\n");
error_out_of_memory();
retval = 1;
goto Quit;
}
dwBuffer = GetEnvironmentVariable(_T("PATH"), pszBuffer, ENV_BUFFER_SIZE);
if (dwBuffer == 0)
{
cmd_free(pszBuffer);
ConErrResPrintf(STRING_SET_ENV_ERROR, _T("PATH"));
retval = 0;
goto Quit;
}
else if (dwBuffer > ENV_BUFFER_SIZE)
{
LPTSTR pszOldBuffer = pszBuffer;
pszBuffer = (LPTSTR)cmd_realloc(pszBuffer, dwBuffer * sizeof (TCHAR));
if (!pszBuffer)
{
WARN("Cannot reallocate memory for pszBuffer!\n");
error_out_of_memory();
cmd_free(pszOldBuffer);
retval = 1;
goto Quit;
}
GetEnvironmentVariable(_T("PATH"), pszBuffer, dwBuffer);
}
ConOutPrintf(_T("PATH=%s\n"), pszBuffer);
cmd_free(pszBuffer);
retval = 0;
goto Quit;
}
/* Skip leading '=' */
if (*param == _T('='))
param++;
/* Set PATH environment variable */
if (!SetEnvironmentVariable(_T("PATH"), param))
{
retval = 1;
}
Quit:
if (BatType != CMD_TYPE)
{
if (retval != 0)
nErrorLevel = retval;
}
else
{
nErrorLevel = retval;
}
return retval;
}
#endif
/* EOF */