ReactOS  0.4.15-dev-492-ga1108f6
set.c
Go to the documentation of this file.
1 /*
2  * SET.C - set internal command.
3  *
4  *
5  * History:
6  *
7  * 06/14/97 (Tim Norman)
8  * changed static var in set() to a cmd_alloc'd space to pass to putenv.
9  * need to find a better way to do this, since it seems it is wasting
10  * memory when variables are redefined.
11  *
12  * 07/08/1998 (John P. Price)
13  * removed call to show_environment in set command.
14  * moved test for syntax before allocating memory in set command.
15  * misc clean up and optimization.
16  *
17  * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
18  * added config.h include
19  *
20  * 28-Jul-1998 (John P Price <linux-guru@gcfl.net>)
21  * added set_env function to set env. variable without needing set command
22  *
23  * 09-Dec-1998 (Eric Kohl)
24  * Added help text ("/?").
25  *
26  * 24-Jan-1999 (Eric Kohl)
27  * Fixed Win32 environment handling.
28  * Unicode and redirection safe!
29  *
30  * 25-Feb-1999 (Eric Kohl)
31  * Fixed little bug.
32  *
33  * 30-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
34  * Remove all hardcoded strings in En.rc
35  */
36 
37 #include "precomp.h"
38 
39 #ifdef INCLUDE_CMD_SET
40 
41 
42 /* initial size of environment variable buffer */
43 #define ENV_BUFFER_SIZE 1024
44 
45 static BOOL
47 
48 static LPCTSTR
50 {
51  while (*p && *p <= _T(' '))
52  p++;
53  return p;
54 }
55 
56 /* Used to check for and handle:
57  * SET "var=value", SET /P "var=prompt", and SET /P var="prompt" */
58 static LPTSTR
60 {
61  TCHAR *end;
62  if (*p == _T('"'))
63  {
64  p = (LPTSTR)skip_ws(p + 1);
65  /* If a matching quote is found, truncate the string */
66  end = _tcsrchr(p, _T('"'));
67  if (end)
68  *end = _T('\0');
69  }
70  return p;
71 }
72 
74 {
75  LPTSTR p;
76  LPTSTR lpEnv;
77  LPTSTR lpOutput;
78 
79  if ( !_tcsncmp (param, _T("/?"), 2) )
80  {
82  return 0;
83  }
84 
86 
87  /* if no parameters, show the environment */
88  if (param[0] == _T('\0'))
89  {
90  lpEnv = (LPTSTR)GetEnvironmentStrings ();
91  if (lpEnv)
92  {
93  lpOutput = lpEnv;
94  while (*lpOutput)
95  {
96  if (*lpOutput != _T('='))
97  ConOutPuts(lpOutput);
98  lpOutput += _tcslen(lpOutput) + 1;
99  ConOutChar(_T('\n'));
100  }
101  FreeEnvironmentStrings (lpEnv);
102  }
103 
104  return 0;
105  }
106 
107  /* the /A does *NOT* have to be followed by a whitespace */
108  if ( !_tcsnicmp (param, _T("/A"), 2) )
109  {
110  BOOL Success;
112  Success = seta_eval ( skip_ws(param+2) );
113  if (!Success)
114  {
115  /* might seem random but this is what windows xp does */
116  nErrorLevel = 9165;
117  }
118  return !Success;
119  }
120 
121  if (!_tcsnicmp(param, _T("/P"), 2))
122  {
123  TCHAR value[1023];
125  p = _tcschr(param, _T('='));
126  if (!p)
127  {
129  nErrorLevel = 1;
130  return 1;
131  }
132 
133  *p++ = _T('\0');
134  ConOutPrintf(_T("%s"), GetQuotedString(p));
135  ConInString(value, 1023);
136 
138  {
139  nErrorLevel = 1;
140  return 1;
141  }
142  return 0;
143  }
144 
146 
147  p = _tcschr (param, _T('='));
148  if (p)
149  {
150  /* set or remove environment variable */
151  if (p == param)
152  {
153  /* handle set =val case */
155  nErrorLevel = 1;
156  return 1;
157  }
158 
159  *p++ = _T('\0');
160  if (!SetEnvironmentVariable(param, *p ? p : NULL))
161  {
162  nErrorLevel = 1;
163  return 1;
164  }
165  }
166  else
167  {
168  /* display all environment variable with the given prefix */
169  BOOL bFound = FALSE;
170 
171  while (_istspace(*param) || *param == _T(',') || *param == _T(';'))
172  param++;
173 
174  p = _tcsrchr(param, _T(' '));
175  if (!p)
176  p = param + _tcslen(param);
177  *p = _T('\0');
178 
179  lpEnv = GetEnvironmentStrings();
180  if (lpEnv)
181  {
182  lpOutput = lpEnv;
183  while (*lpOutput)
184  {
185  if (!_tcsnicmp(lpOutput, param, p - param))
186  {
187  ConOutPuts(lpOutput);
188  ConOutChar(_T('\n'));
189  bFound = TRUE;
190  }
191  lpOutput += _tcslen(lpOutput) + 1;
192  }
193  FreeEnvironmentStrings(lpEnv);
194  }
195 
196  if (!bFound)
197  {
199  nErrorLevel = 1;
200  return 1;
201  }
202  }
203 
204  return 0;
205 }
206 
207 static INT
209 {
210  LPCTSTR p2 = p;
211  if ( __iscsymf(*p) )
212  {
213  ++p2;
214  while ( __iscsym(*p2) )
215  ++p2;
216  }
217  return (INT)(p2-p);
218 }
219 
220 #define PARSE_IDENT(ident,identlen,p) \
221  identlen = ident_len(p); \
222  ident = (LPTSTR)alloca ( ( identlen + 1 ) * sizeof(TCHAR) ); \
223  memmove ( ident, p, identlen * sizeof(TCHAR) ); \
224  ident[identlen] = 0; \
225  p += identlen;
226 
227 static INT
229 {
230  LPCTSTR identVal = GetEnvVarOrSpecial ( ident );
231  if ( !identVal )
232  return 0;
233  else
234  return _tcstol ( identVal, NULL, 0 );
235 }
236 
237 static BOOL
239 {
240  switch ( op )
241  {
242  case '*':
243  *lval *= rval;
244  break;
245  case '/':
246  *lval /= rval;
247  break;
248  case '%':
249  *lval %= rval;
250  break;
251  case '+':
252  *lval += rval;
253  break;
254  case '-':
255  *lval -= rval;
256  break;
257  case '&':
258  *lval &= rval;
259  break;
260  case '^':
261  *lval ^= rval;
262  break;
263  case '|':
264  *lval |= rval;
265  break;
266  default:
268  return FALSE;
269  }
270  return TRUE;
271 }
272 
273 static BOOL
274 seta_stmt (LPCTSTR* p_, INT* result);
275 
276 static BOOL
278 {
279  LPCTSTR p = *p_;
280  if ( *p == _T('(') )
281  {
282  INT rval;
283  p = skip_ws ( p + 1 );
284  if ( !seta_stmt ( &p, &rval ) )
285  return FALSE;
286  if ( *p++ != _T(')') )
287  {
289  return FALSE;
290  }
291  *result = rval;
292  }
293  else if ( isdigit(*p) )
294  {
295  *result = _tcstol ( p, (LPTSTR *)&p, 0 );
296  }
297  else if ( __iscsymf(*p) )
298  {
299  LPTSTR ident;
300  INT identlen;
301  PARSE_IDENT(ident,identlen,p);
302  *result = seta_identval ( ident );
303  }
304  else
305  {
307  return FALSE;
308  }
309  *p_ = skip_ws ( p );
310  return TRUE;
311 }
312 
313 static BOOL
315 {
316  LPCTSTR p = *p_;
317  TCHAR op = 0;
318  INT rval;
319  if ( _tcschr(_T("!~-"),*p) )
320  {
321  op = *p;
322  p = skip_ws ( p + 1 );
323  }
324  if ( !seta_unaryTerm ( &p, &rval ) )
325  return FALSE;
326  switch ( op )
327  {
328  case '!':
329  rval = !rval;
330  break;
331  case '~':
332  rval = ~rval;
333  break;
334  case '-':
335  rval = -rval;
336  break;
337  }
338 
339  *result = rval;
340  *p_ = p;
341  return TRUE;
342 }
343 
344 static BOOL
345 seta_ltorTerm(LPCTSTR* p_, INT* result, LPCTSTR ops, BOOL (*subTerm)(LPCTSTR*,INT*))
346 {
347  LPCTSTR p = *p_;
348  INT lval;
349  if ( !subTerm ( &p, &lval ) )
350  return FALSE;
351  while ( *p && _tcschr(ops,*p) )
352  {
353  INT rval;
354  TCHAR op = *p;
355 
356  p = skip_ws ( p+1 );
357 
358  if ( !subTerm ( &p, &rval ) )
359  return FALSE;
360 
361  if ( !calc ( &lval, op, rval ) )
362  return FALSE;
363  }
364 
365  *result = lval;
366  *p_ = p;
367  return TRUE;
368 }
369 
370 static BOOL
372 {
373  return seta_ltorTerm ( p_, result, _T("*/%"), seta_mulTerm );
374 }
375 
376 static BOOL
378 {
379  return seta_ltorTerm ( p_, result, _T("+-"), seta_addTerm );
380 }
381 
382 static BOOL
384 {
385  LPCTSTR p = *p_;
386  INT lval;
387  if ( !seta_logShiftTerm ( &p, &lval ) )
388  return FALSE;
389  while ( *p && _tcschr(_T("<>"),*p) && p[0] == p[1] )
390  {
391  INT rval;
392  TCHAR op = *p;
393 
394  p = skip_ws ( p+2 );
395 
396  if ( !seta_logShiftTerm ( &p, &rval ) )
397  return FALSE;
398 
399  switch ( op )
400  {
401  case '<':
402  {
403  /* Shift left has to be a positive number, 0-31 otherwise 0 is returned,
404  * which differs from the compiler (for example gcc) so being explicit. */
405  if (rval < 0 || rval >= (8 * sizeof(lval)))
406  lval = 0;
407  else
408  lval <<= rval;
409  break;
410  }
411  case '>':
412  lval >>= rval;
413  break;
414  default:
416  return FALSE;
417  }
418  }
419 
420  *result = lval;
421  *p_ = p;
422  return TRUE;
423 }
424 
425 static BOOL
427 {
428  return seta_ltorTerm ( p_, result, _T("&"), seta_bitAndTerm );
429 }
430 
431 static BOOL
433 {
434  return seta_ltorTerm ( p_, result, _T("^"), seta_bitExclOrTerm );
435 }
436 
437 static BOOL
439 {
440  return seta_ltorTerm ( p_, result, _T("|"), seta_bitOrTerm );
441 }
442 
443 static BOOL
445 {
446  LPCTSTR p = *p_;
447  LPTSTR ident;
448  TCHAR op = 0;
449  INT identlen, exprval;
450 
451  PARSE_IDENT(ident,identlen,p);
452  if ( identlen )
453  {
454  p = skip_ws(p);
455  if ( *p == _T('=') )
456  op = *p, p = skip_ws(p+1);
457  else if ( _tcschr ( _T("*/%+-&^|"), *p ) && p[1] == _T('=') )
458  op = *p, p = skip_ws(p+2);
459  else if ( _tcschr ( _T("<>"), *p ) && *p == p[1] && p[2] == _T('=') )
460  op = *p, p = skip_ws(p+3);
461  }
462 
463  /* allow to chain multiple assignments, such as: a=b=1 */
464  if ( ident && op )
465  {
466  INT identval;
467  LPTSTR buf;
468 
469  if ( !seta_assignment ( &p, &exprval ) )
470  return FALSE;
471 
472  identval = seta_identval ( ident );
473 
474  switch ( op )
475  {
476  case '=':
477  identval = exprval;
478  break;
479  case '<':
480  {
481  /* Shift left has to be a positive number, 0-31 otherwise 0 is returned,
482  * which differs from the compiler (for example gcc) so being explicit. */
483  if (exprval < 0 || exprval >= (8 * sizeof(identval)))
484  identval = 0;
485  else
486  identval <<= exprval;
487  break;
488  }
489  case '>':
490  identval >>= exprval;
491  break;
492  default:
493  if ( !calc ( &identval, op, exprval ) )
494  return FALSE;
495  }
496  buf = (LPTSTR)alloca ( 32 * sizeof(TCHAR) );
497  _sntprintf ( buf, 32, _T("%i"), identval );
498  SetEnvironmentVariable ( ident, buf ); // TODO FIXME - check return value
499  exprval = identval;
500  }
501  else
502  {
503  /* restore p in case we found an ident but not an op */
504  p = *p_;
505  if ( !seta_expr ( &p, &exprval ) )
506  return FALSE;
507  }
508 
509  *result = exprval;
510  *p_ = p;
511  return TRUE;
512 }
513 
514 static BOOL
516 {
517  LPCTSTR p = *p_;
518  INT rval;
519 
520  if ( !seta_assignment ( &p, &rval ) )
521  return FALSE;
522  while ( *p == _T(',') )
523  {
524  p = skip_ws ( p+1 );
525 
526  if ( !seta_assignment ( &p, &rval ) )
527  return FALSE;
528  }
529 
530  *result = rval;
531  *p_ = p;
532  return TRUE;
533 }
534 
535 static BOOL
537 {
538  INT rval;
539  if ( !*p )
540  {
542  return FALSE;
543  }
544  if ( !seta_stmt ( &p, &rval ) )
545  return FALSE;
546  if ( !bc )
547  ConOutPrintf ( _T("%i"), rval );
548  return TRUE;
549 }
550 
551 #endif
INT nErrorLevel
Definition: cmd.c:157
#define TRUE
Definition: types.h:120
const CHAR * LPCTSTR
Definition: xmlstorage.h:193
#define STRING_INVALID_OPERAND
Definition: resource.h:215
#define STRING_PATH_ERROR
Definition: resource.h:55
LPBATCH_CONTEXT bc
Definition: batch.c:66
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
VOID ConOutChar(TCHAR c)
Definition: console.c:123
#define _tcstol
Definition: tchar.h:594
#define ConErrResPuts(uID)
Definition: console.h:39
static BOOL seta_eval(LPCTSTR expr)
Definition: set.c:536
static VOID ConInString(LPWSTR lpInput, DWORD dwLength)
Definition: label.c:56
static BOOL seta_mulTerm(LPCTSTR *p_, INT *result)
Definition: set.c:314
static LPCTSTR skip_ws(LPCTSTR p)
Definition: set.c:49
#define ConOutPrintf(szStr,...)
Definition: console.h:42
VOID ConOutResPaging(BOOL StartPaging, UINT resID)
Definition: console.c:182
GLuint GLuint end
Definition: gl.h:1545
static INT seta_identval(LPCTSTR ident)
Definition: set.c:228
static VOID StripQuotes(LPSTR in)
Definition: cmdcons.c:116
int32_t INT
Definition: typedefs.h:57
Definition: query.h:86
CHAR * LPTSTR
Definition: xmlstorage.h:192
#define alloca
Definition: malloc.h:361
#define STRING_SYNTAX_COMMAND_INCORRECT
Definition: resource.h:218
unsigned int BOOL
Definition: ntddk_ex.h:94
#define ConErrResPrintf(uID,...)
Definition: console.h:51
#define _tcsnicmp
Definition: xmlstorage.h:207
LPCTSTR GetEnvVarOrSpecial(LPCTSTR varName)
Definition: cmd.c:871
static BOOL seta_stmt(LPCTSTR *p_, INT *result)
Definition: set.c:515
static BOOL seta_logShiftTerm(LPCTSTR *p_, INT *result)
Definition: set.c:377
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
static LPTSTR GetQuotedString(TCHAR *p)
Definition: set.c:59
smooth NULL
Definition: ftsmooth.c:416
static BOOL seta_expr(LPCTSTR *p_, INT *result)
Definition: set.c:438
#define __iscsym(_c)
Definition: ctype.h:691
#define STRING_EXPECTED_NUMBER_OR_VARIABLE
Definition: resource.h:217
#define isdigit(c)
Definition: acclib.h:68
_TCHAR * _tcschr(const _TCHAR *s, _XINT c)
Definition: tcschr.h:4
_In_ ULONG _In_ ULONG_PTR ident
Definition: winddi.h:3993
static BOOL seta_ltorTerm(LPCTSTR *p_, INT *result, LPCTSTR ops, BOOL(*subTerm)(LPCTSTR *, INT *))
Definition: set.c:345
char TCHAR
Definition: xmlstorage.h:189
#define _T(x)
Definition: vfdio.h:22
static BOOL seta_addTerm(LPCTSTR *p_, INT *result)
Definition: set.c:371
GLfloat param
Definition: glext.h:5796
UINT op
Definition: effect.c:224
static BOOL seta_assignment(LPCTSTR *p_, INT *result)
Definition: set.c:444
static BOOL seta_unaryTerm(LPCTSTR *p_, INT *result)
Definition: set.c:277
float rval
Definition: cylfrac.c:48
#define _sntprintf
Definition: xmlstorage.h:201
#define SetEnvironmentVariable
Definition: winbase.h:3748
static INT ident_len(LPCTSTR p)
Definition: set.c:208
static BOOL calc(INT *lval, TCHAR op, INT rval)
Definition: set.c:238
#define STRING_SET_HELP
Definition: resource.h:171
#define PARSE_IDENT(ident, identlen, p)
Definition: set.c:220
LPSTR WINAPI GetEnvironmentStrings(void)
#define STRING_EXPECTED_CLOSE_PAREN
Definition: resource.h:216
_TCHAR * _tcsrchr(const _TCHAR *s, _XINT c)
Definition: tcsrchr.h:4
#define _istspace
Definition: tchar.h:1504
static BOOL seta_bitExclOrTerm(LPCTSTR *p_, INT *result)
Definition: set.c:426
static BOOL seta_bitOrTerm(LPCTSTR *p_, INT *result)
Definition: set.c:432
GLfloat GLfloat p
Definition: glext.h:8902
#define FreeEnvironmentStrings
Definition: winbase.h:3636
GLuint64EXT * result
Definition: glext.h:11304
int _tcsncmp(const _TCHAR *s1, const _TCHAR *s2, size_t n)
Definition: tcsncmp.h:9
INT cmd_set(LPTSTR param)
Definition: set.c:73
VOID ConOutPuts(LPTSTR szText)
Definition: tee.c:27
#define __iscsymf(_c)
Definition: ctype.h:690
static BOOL seta_bitAndTerm(LPCTSTR *p_, INT *result)
Definition: set.c:383