mirror of
https://github.com/reactos/reactos.git
synced 2024-11-19 21:48:10 +00:00
3f892a8d6b
Adapted from a patch by Jacob S. Preciado. Bring also the code suggestions emitted during review.
138 lines
3.5 KiB
C
138 lines
3.5 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)
|
|
{
|
|
WARN("Cannot allocate memory for Saved!\n");
|
|
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;
|
|
}
|