5ad2e4176829fbfdf63cb7557fe375660e8dc3a8
[reactos.git] / reactos / base / shell / cmd / setlocal.c
1 /*
2 * SETLOCAL.C - setlocal and endlocal internal batch commands.
3 *
4 * History:
5 *
6 * 1 Feb 2008 (Christoph von Wittich)
7 * started.
8 */
9
10 #include "precomp.h"
11
12 typedef struct _SETLOCAL
13 {
14 struct _SETLOCAL *Prev;
15 BOOL DelayedExpansion;
16 LPTSTR Environment;
17 } SETLOCAL;
18
19 /* Create a copy of the current environment */
20 LPTSTR
21 DuplicateEnvironment(VOID)
22 {
23 LPTSTR Environ = GetEnvironmentStrings();
24 LPTSTR End, EnvironCopy;
25
26 if (!Environ) return NULL;
27
28 for (End = Environ; *End; End += _tcslen(End) + 1) ;
29 EnvironCopy = cmd_alloc((End + 1 - Environ) * sizeof(TCHAR));
30
31 if (EnvironCopy)
32 memcpy(EnvironCopy, Environ, (End + 1 - Environ) * sizeof(TCHAR));
33
34 FreeEnvironmentStrings(Environ);
35 return EnvironCopy;
36 }
37
38 INT cmd_setlocal(LPTSTR param)
39 {
40 SETLOCAL *Saved;
41 LPTSTR *arg;
42 INT argc, i;
43
44 /* SETLOCAL only works inside a batch file */
45 if (!bc)
46 return 0;
47
48 Saved = cmd_alloc(sizeof(SETLOCAL));
49 if (!Saved)
50 {
51 error_out_of_memory();
52 return 1;
53 }
54 Saved->Prev = bc->setlocal;
55 Saved->DelayedExpansion = bDelayedExpansion;
56 Saved->Environment = DuplicateEnvironment();
57 if (!Saved->Environment)
58 {
59 error_out_of_memory();
60 cmd_free(Saved);
61 return 1;
62 }
63 bc->setlocal = Saved;
64
65 nErrorLevel = 0;
66
67 arg = splitspace(param, &argc);
68 for (i = 0; i < argc; i++)
69 {
70 if (!_tcsicmp(arg[i], _T("enableextensions")))
71 /* not implemented, ignore */;
72 else if (!_tcsicmp(arg[i], _T("disableextensions")))
73 /* not implemented, ignore */;
74 else if (!_tcsicmp(arg[i], _T("enabledelayedexpansion")))
75 bDelayedExpansion = TRUE;
76 else if (!_tcsicmp(arg[i], _T("disabledelayedexpansion")))
77 bDelayedExpansion = FALSE;
78 else
79 {
80 error_invalid_parameter_format(arg[i]);
81 break;
82 }
83 }
84 freep(arg);
85
86 return nErrorLevel;
87 }
88
89 /* endlocal doesn't take any params */
90 INT cmd_endlocal(LPTSTR param)
91 {
92 LPTSTR Environ, Name, Value;
93 SETLOCAL *Saved;
94
95 /* Pop a SETLOCAL struct off of this batch file's stack */
96 if (!bc || !(Saved = bc->setlocal))
97 return 0;
98 bc->setlocal = Saved->Prev;
99
100 bDelayedExpansion = Saved->DelayedExpansion;
101
102 /* First, clear out the environment. Since making any changes to the
103 * environment invalidates pointers obtained from GetEnvironmentStrings(),
104 * we must make a copy of it and get the variable names from that */
105 Environ = DuplicateEnvironment();
106 if (Environ)
107 {
108 for (Name = Environ; *Name; Name += _tcslen(Name) + 1)
109 {
110 if (!(Value = _tcschr(Name + 1, _T('='))))
111 continue;
112 *Value++ = _T('\0');
113 SetEnvironmentVariable(Name, NULL);
114 Name = Value;
115 }
116 cmd_free(Environ);
117 }
118
119 /* Now, restore variables from the copy saved by cmd_setlocal */
120 for (Name = Saved->Environment; *Name; Name += _tcslen(Name) + 1)
121 {
122 if (!(Value = _tcschr(Name + 1, _T('='))))
123 continue;
124 *Value++ = _T('\0');
125 SetEnvironmentVariable(Name, Value);
126 Name = Value;
127 }
128
129 cmd_free(Saved->Environment);
130 cmd_free(Saved);
131 return 0;
132 }