reactos/base/shell/cmd/setlocal.c

137 lines
3.4 KiB
C

/*
* SETLOCAL.C - setlocal and endlocal internal batch commands.
*
* History:
*
* 1 Feb 2008 (Christoph von Wittich)
* started.
*/
#include "precomp.h"
typedef struct _SETLOCAL
{
struct _SETLOCAL *Prev;
BOOL EnableExtensions;
BOOL DelayedExpansion;
LPTSTR Environment;
} SETLOCAL;
/* Create a copy of the current environment */
LPTSTR
DuplicateEnvironment(VOID)
{
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;
}
INT cmd_setlocal(LPTSTR param)
{
SETLOCAL *Saved;
LPTSTR *arg;
INT argc, i;
/* SETLOCAL only works inside a batch file */
if (!bc)
return 0;
Saved = cmd_alloc(sizeof(SETLOCAL));
if (!Saved)
{
error_out_of_memory();
return 1;
}
Saved->Prev = bc->setlocal;
Saved->EnableExtensions = bEnableExtensions;
Saved->DelayedExpansion = bDelayedExpansion;
Saved->Environment = DuplicateEnvironment();
if (!Saved->Environment)
{
error_out_of_memory();
cmd_free(Saved);
return 1;
}
bc->setlocal = Saved;
nErrorLevel = 0;
arg = splitspace(param, &argc);
for (i = 0; i < argc; i++)
{
if (!_tcsicmp(arg[i], _T("enableextensions")))
/* FIXME: not implemented! */
bEnableExtensions = TRUE;
else if (!_tcsicmp(arg[i], _T("disableextensions")))
/* FIXME: not implemented! */
bEnableExtensions = FALSE;
else if (!_tcsicmp(arg[i], _T("enabledelayedexpansion")))
bDelayedExpansion = TRUE;
else if (!_tcsicmp(arg[i], _T("disabledelayedexpansion")))
bDelayedExpansion = FALSE;
else
{
error_invalid_parameter_format(arg[i]);
break;
}
}
freep(arg);
return nErrorLevel;
}
/* endlocal doesn't take any params */
INT cmd_endlocal(LPTSTR param)
{
LPTSTR Environ, Name, Value;
SETLOCAL *Saved;
/* Pop a SETLOCAL struct off of this batch file's stack */
if (!bc || !(Saved = bc->setlocal))
return 0;
bc->setlocal = Saved->Prev;
bEnableExtensions = Saved->EnableExtensions;
bDelayedExpansion = Saved->DelayedExpansion;
/* First, clear out the environment. Since making any changes to the
* environment invalidates pointers obtained from GetEnvironmentStrings(),
* we must make a copy of it and get the variable names from that */
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);
}
/* Now, restore variables from the copy saved by cmd_setlocal */
for (Name = Saved->Environment; *Name; Name += _tcslen(Name) + 1)
{
if (!(Value = _tcschr(Name + 1, _T('='))))
continue;
*Value++ = _T('\0');
SetEnvironmentVariable(Name, Value);
Name = Value;
}
cmd_free(Saved->Environment);
cmd_free(Saved);
return 0;
}