2008-02-01 09:49:58 +00:00
|
|
|
/*
|
2009-03-06 18:05:45 +00:00
|
|
|
* SETLOCAL.C - setlocal and endlocal internal batch commands.
|
2008-02-01 09:49:58 +00:00
|
|
|
*
|
|
|
|
* History:
|
|
|
|
*
|
|
|
|
* 1 Feb 2008 (Christoph von Wittich)
|
|
|
|
* started.
|
2013-06-30 13:23:30 +00:00
|
|
|
*/
|
2008-02-01 09:49:58 +00:00
|
|
|
|
2013-01-24 23:00:42 +00:00
|
|
|
#include "precomp.h"
|
2008-02-01 09:49:58 +00:00
|
|
|
|
2020-07-18 21:35:56 +00:00
|
|
|
#include <direct.h> // For _getdrive().
|
|
|
|
|
2013-06-29 23:50:13 +00:00
|
|
|
typedef struct _SETLOCAL
|
|
|
|
{
|
|
|
|
struct _SETLOCAL *Prev;
|
2020-07-26 18:32:39 +00:00
|
|
|
LPTSTR Environment;
|
2020-07-18 21:35:56 +00:00
|
|
|
INT CurDrive;
|
2017-09-30 11:39:08 +00:00
|
|
|
BOOL EnableExtensions;
|
2013-06-29 23:50:13 +00:00
|
|
|
BOOL DelayedExpansion;
|
2020-07-26 18:32:39 +00:00
|
|
|
} SETLOCAL, *PSETLOCAL;
|
2008-02-01 09:49:58 +00:00
|
|
|
|
2009-03-06 18:05:45 +00:00
|
|
|
/* Create a copy of the current environment */
|
2009-03-23 23:52:50 +00:00
|
|
|
LPTSTR
|
|
|
|
DuplicateEnvironment(VOID)
|
2009-03-06 18:05:45 +00:00
|
|
|
{
|
2013-06-29 23:50:13 +00:00
|
|
|
LPTSTR Environ = GetEnvironmentStrings();
|
|
|
|
LPTSTR End, EnvironCopy;
|
|
|
|
|
|
|
|
if (!Environ) return NULL;
|
|
|
|
|
|
|
|
for (End = Environ; *End; End += _tcslen(End) + 1) ;
|
|
|
|
EnvironCopy = cmd_alloc((End + 1 - Environ) * sizeof(TCHAR));
|
|
|
|
|
|
|
|
if (EnvironCopy)
|
|
|
|
memcpy(EnvironCopy, Environ, (End + 1 - Environ) * sizeof(TCHAR));
|
|
|
|
|
|
|
|
FreeEnvironmentStrings(Environ);
|
|
|
|
return EnvironCopy;
|
2009-03-06 18:05:45 +00:00
|
|
|
}
|
2008-02-01 09:49:58 +00:00
|
|
|
|
2009-03-06 18:05:45 +00:00
|
|
|
INT cmd_setlocal(LPTSTR param)
|
2008-02-01 09:49:58 +00:00
|
|
|
{
|
2020-07-26 18:32:39 +00:00
|
|
|
PSETLOCAL Saved;
|
|
|
|
LPTSTR* arg;
|
2013-06-29 23:50:13 +00:00
|
|
|
INT argc, i;
|
|
|
|
|
2020-07-18 21:35:56 +00:00
|
|
|
if (!_tcscmp(param, _T("/?")))
|
|
|
|
{
|
|
|
|
// FIXME
|
|
|
|
ConOutPuts(_T("SETLOCAL help not implemented yet!\n"));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-07-26 18:32:39 +00:00
|
|
|
/* SETLOCAL only works inside a batch context */
|
2013-06-29 23:50:13 +00:00
|
|
|
if (!bc)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
Saved = cmd_alloc(sizeof(SETLOCAL));
|
|
|
|
if (!Saved)
|
|
|
|
{
|
2017-12-03 17:49:41 +00:00
|
|
|
WARN("Cannot allocate memory for Saved!\n");
|
2013-06-29 23:50:13 +00:00
|
|
|
error_out_of_memory();
|
|
|
|
return 1;
|
|
|
|
}
|
2020-07-18 21:35:56 +00:00
|
|
|
|
2013-06-29 23:50:13 +00:00
|
|
|
Saved->Environment = DuplicateEnvironment();
|
|
|
|
if (!Saved->Environment)
|
|
|
|
{
|
|
|
|
error_out_of_memory();
|
|
|
|
cmd_free(Saved);
|
|
|
|
return 1;
|
|
|
|
}
|
2020-07-18 21:35:56 +00:00
|
|
|
/*
|
|
|
|
* Save the current drive; the duplicated environment
|
|
|
|
* contains the corresponding current directory.
|
|
|
|
*/
|
|
|
|
Saved->CurDrive = _getdrive();
|
|
|
|
|
2020-07-26 18:32:39 +00:00
|
|
|
Saved->EnableExtensions = bEnableExtensions;
|
|
|
|
Saved->DelayedExpansion = bDelayedExpansion;
|
|
|
|
|
|
|
|
Saved->Prev = bc->setlocal;
|
2013-06-29 23:50:13 +00:00
|
|
|
bc->setlocal = Saved;
|
|
|
|
|
|
|
|
nErrorLevel = 0;
|
|
|
|
|
|
|
|
arg = splitspace(param, &argc);
|
|
|
|
for (i = 0; i < argc; i++)
|
|
|
|
{
|
2020-07-26 18:32:39 +00:00
|
|
|
if (!_tcsicmp(arg[i], _T("ENABLEEXTENSIONS")))
|
2017-09-30 11:39:08 +00:00
|
|
|
bEnableExtensions = TRUE;
|
2020-07-26 18:32:39 +00:00
|
|
|
else if (!_tcsicmp(arg[i], _T("DISABLEEXTENSIONS")))
|
2017-09-30 11:39:08 +00:00
|
|
|
bEnableExtensions = FALSE;
|
2020-07-26 18:32:39 +00:00
|
|
|
else if (!_tcsicmp(arg[i], _T("ENABLEDELAYEDEXPANSION")))
|
2013-06-29 23:50:13 +00:00
|
|
|
bDelayedExpansion = TRUE;
|
2020-07-26 18:32:39 +00:00
|
|
|
else if (!_tcsicmp(arg[i], _T("DISABLEDELAYEDEXPANSION")))
|
2013-06-29 23:50:13 +00:00
|
|
|
bDelayedExpansion = FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
error_invalid_parameter_format(arg[i]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
freep(arg);
|
|
|
|
|
|
|
|
return nErrorLevel;
|
2008-02-01 09:49:58 +00:00
|
|
|
}
|
|
|
|
|
2009-03-06 18:05:45 +00:00
|
|
|
INT cmd_endlocal(LPTSTR param)
|
2008-02-01 09:49:58 +00:00
|
|
|
{
|
2013-06-29 23:50:13 +00:00
|
|
|
LPTSTR Environ, Name, Value;
|
2020-07-26 18:32:39 +00:00
|
|
|
PSETLOCAL Saved;
|
2020-07-18 21:35:56 +00:00
|
|
|
TCHAR drvEnvVar[] = _T("=?:");
|
|
|
|
TCHAR szCurrent[MAX_PATH];
|
2020-07-26 18:32:39 +00:00
|
|
|
|
2020-07-18 21:35:56 +00:00
|
|
|
if (!_tcscmp(param, _T("/?")))
|
|
|
|
{
|
|
|
|
// FIXME
|
|
|
|
ConOutPuts(_T("ENDLOCAL help not implemented yet!\n"));
|
|
|
|
return 0;
|
|
|
|
}
|
2013-06-29 23:50:13 +00:00
|
|
|
|
2020-07-26 18:32:39 +00:00
|
|
|
/* Pop a SETLOCAL struct off of this batch context's stack */
|
2013-06-29 23:50:13 +00:00
|
|
|
if (!bc || !(Saved = bc->setlocal))
|
|
|
|
return 0;
|
|
|
|
bc->setlocal = Saved->Prev;
|
|
|
|
|
2017-09-30 11:39:08 +00:00
|
|
|
bEnableExtensions = Saved->EnableExtensions;
|
2013-06-29 23:50:13 +00:00
|
|
|
bDelayedExpansion = Saved->DelayedExpansion;
|
|
|
|
|
|
|
|
/* First, clear out the environment. Since making any changes to the
|
|
|
|
* environment invalidates pointers obtained from GetEnvironmentStrings(),
|
2020-07-26 18:32:39 +00:00
|
|
|
* we must make a copy of it and get the variable names from that. */
|
2013-06-29 23:50:13 +00:00
|
|
|
Environ = DuplicateEnvironment();
|
|
|
|
if (Environ)
|
|
|
|
{
|
|
|
|
for (Name = Environ; *Name; Name += _tcslen(Name) + 1)
|
|
|
|
{
|
|
|
|
if (!(Value = _tcschr(Name + 1, _T('='))))
|
|
|
|
continue;
|
|
|
|
*Value++ = _T('\0');
|
|
|
|
SetEnvironmentVariable(Name, NULL);
|
|
|
|
Name = Value;
|
|
|
|
}
|
|
|
|
cmd_free(Environ);
|
|
|
|
}
|
|
|
|
|
2020-07-26 18:32:39 +00:00
|
|
|
/* Now, restore variables from the copy saved by cmd_setlocal() */
|
2013-06-29 23:50:13 +00:00
|
|
|
for (Name = Saved->Environment; *Name; Name += _tcslen(Name) + 1)
|
|
|
|
{
|
|
|
|
if (!(Value = _tcschr(Name + 1, _T('='))))
|
|
|
|
continue;
|
|
|
|
*Value++ = _T('\0');
|
|
|
|
SetEnvironmentVariable(Name, Value);
|
|
|
|
Name = Value;
|
|
|
|
}
|
|
|
|
|
2020-07-18 21:35:56 +00:00
|
|
|
/* Restore the current drive and its current directory from the environment */
|
|
|
|
drvEnvVar[1] = _T('A') + Saved->CurDrive - 1;
|
|
|
|
if (!GetEnvironmentVariable(drvEnvVar, szCurrent, ARRAYSIZE(szCurrent)))
|
|
|
|
{
|
|
|
|
_stprintf(szCurrent, _T("%C:\\"), _T('A') + Saved->CurDrive - 1);
|
|
|
|
}
|
|
|
|
_tchdir(szCurrent); // SetRootPath(NULL, szCurrent);
|
|
|
|
|
2013-06-29 23:50:13 +00:00
|
|
|
cmd_free(Saved->Environment);
|
|
|
|
cmd_free(Saved);
|
|
|
|
return 0;
|
2008-02-01 09:49:58 +00:00
|
|
|
}
|