Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenset.c
Go to the documentation of this file.
00001 /* 00002 * SET.C - set internal command. 00003 * 00004 * 00005 * History: 00006 * 00007 * 06/14/97 (Tim Norman) 00008 * changed static var in set() to a cmd_alloc'd space to pass to putenv. 00009 * need to find a better way to do this, since it seems it is wasting 00010 * memory when variables are redefined. 00011 * 00012 * 07/08/1998 (John P. Price) 00013 * removed call to show_environment in set command. 00014 * moved test for syntax before allocating memory in set command. 00015 * misc clean up and optimization. 00016 * 00017 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>) 00018 * added config.h include 00019 * 00020 * 28-Jul-1998 (John P Price <linux-guru@gcfl.net>) 00021 * added set_env function to set env. variable without needing set command 00022 * 00023 * 09-Dec-1998 (Eric Kohl) 00024 * Added help text ("/?"). 00025 * 00026 * 24-Jan-1999 (Eric Kohl) 00027 * Fixed Win32 environment handling. 00028 * Unicode and redirection safe! 00029 * 00030 * 25-Feb-1999 (Eric Kohl) 00031 * Fixed little bug. 00032 * 00033 * 30-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>) 00034 * Remove all hardcode string to En.rc 00035 */ 00036 00037 #include <precomp.h> 00038 00039 #ifdef INCLUDE_CMD_SET 00040 00041 00042 /* initial size of environment variable buffer */ 00043 #define ENV_BUFFER_SIZE 1024 00044 00045 static BOOL 00046 seta_eval ( LPCTSTR expr ); 00047 00048 static LPCTSTR 00049 skip_ws ( LPCTSTR p ) 00050 { 00051 while (*p && *p <= _T(' ')) 00052 p++; 00053 return p; 00054 } 00055 00056 /* Used to check for and handle: 00057 * SET "var=value", SET /P "var=prompt", and SET /P var="prompt" */ 00058 static LPTSTR 00059 GetQuotedString(TCHAR *p) 00060 { 00061 TCHAR *end; 00062 if (*p == _T('"')) 00063 { 00064 p = (LPTSTR)skip_ws(p + 1); 00065 /* If a matching quote is found, truncate the string */ 00066 end = _tcsrchr(p, _T('"')); 00067 if (end) 00068 *end = _T('\0'); 00069 } 00070 return p; 00071 } 00072 00073 INT cmd_set (LPTSTR param) 00074 { 00075 LPTSTR p; 00076 LPTSTR lpEnv; 00077 LPTSTR lpOutput; 00078 00079 if ( !_tcsncmp (param, _T("/?"), 2) ) 00080 { 00081 ConOutResPaging(TRUE,STRING_SET_HELP); 00082 return 0; 00083 } 00084 00085 param = (LPTSTR)skip_ws(param); 00086 00087 /* if no parameters, show the environment */ 00088 if (param[0] == _T('\0')) 00089 { 00090 lpEnv = (LPTSTR)GetEnvironmentStrings (); 00091 if (lpEnv) 00092 { 00093 lpOutput = lpEnv; 00094 while (*lpOutput) 00095 { 00096 if (*lpOutput != _T('=')) 00097 ConOutPuts(lpOutput); 00098 lpOutput += _tcslen(lpOutput) + 1; 00099 } 00100 FreeEnvironmentStrings (lpEnv); 00101 } 00102 00103 return 0; 00104 } 00105 00106 /* the /A does *NOT* have to be followed by a whitespace */ 00107 if ( !_tcsnicmp (param, _T("/A"), 2) ) 00108 { 00109 BOOL Success; 00110 StripQuotes(param); 00111 Success = seta_eval ( skip_ws(param+2) ); 00112 if(!Success) 00113 { 00114 /*might seem random but this is what windows xp does */ 00115 nErrorLevel = 9165; 00116 } 00117 return !Success; 00118 } 00119 00120 if (!_tcsnicmp(param, _T("/P"), 2)) 00121 { 00122 TCHAR value[1023]; 00123 param = GetQuotedString((LPTSTR)skip_ws(param + 2)); 00124 p = _tcschr(param, _T('=')); 00125 if (!p) 00126 { 00127 ConErrResPuts(STRING_SYNTAX_COMMAND_INCORRECT); 00128 nErrorLevel = 1; 00129 return 1; 00130 } 00131 00132 *p++ = _T('\0'); 00133 ConOutPrintf(_T("%s"), GetQuotedString(p)); 00134 ConInString(value, 1023); 00135 00136 if (!*value || !SetEnvironmentVariable(param, value)) 00137 { 00138 nErrorLevel = 1; 00139 return 1; 00140 } 00141 return 0; 00142 } 00143 00144 param = GetQuotedString(param); 00145 00146 p = _tcschr (param, _T('=')); 00147 if (p) 00148 { 00149 /* set or remove environment variable */ 00150 if (p == param) 00151 { 00152 /* handle set =val case */ 00153 ConErrResPuts(STRING_SYNTAX_COMMAND_INCORRECT); 00154 nErrorLevel = 1; 00155 return 1; 00156 } 00157 00158 *p++ = _T('\0'); 00159 if (!SetEnvironmentVariable(param, *p ? p : NULL)) 00160 { 00161 nErrorLevel = 1; 00162 return 1; 00163 } 00164 } 00165 else 00166 { 00167 /* display all environment variable with the given prefix */ 00168 BOOL bFound = FALSE; 00169 00170 while (_istspace(*param) || *param == _T(',') || *param == _T(';')) 00171 param++; 00172 00173 p = _tcsrchr(param, _T(' ')); 00174 if (!p) 00175 p = param + _tcslen(param); 00176 *p = _T('\0'); 00177 00178 lpEnv = GetEnvironmentStrings(); 00179 if (lpEnv) 00180 { 00181 lpOutput = lpEnv; 00182 while (*lpOutput) 00183 { 00184 if (!_tcsnicmp(lpOutput, param, p - param)) 00185 { 00186 ConOutPuts(lpOutput); 00187 bFound = TRUE; 00188 } 00189 lpOutput += _tcslen(lpOutput) + 1; 00190 } 00191 FreeEnvironmentStrings(lpEnv); 00192 } 00193 00194 if (!bFound) 00195 { 00196 ConErrResPrintf (STRING_PATH_ERROR, param); 00197 nErrorLevel = 1; 00198 return 1; 00199 } 00200 } 00201 00202 return 0; 00203 } 00204 00205 static INT 00206 ident_len ( LPCTSTR p ) 00207 { 00208 LPCTSTR p2 = p; 00209 if ( __iscsymf(*p) ) 00210 { 00211 ++p2; 00212 while ( __iscsym(*p2) ) 00213 ++p2; 00214 } 00215 return (INT)(p2-p); 00216 } 00217 00218 #define PARSE_IDENT(ident,identlen,p) \ 00219 identlen = ident_len(p); \ 00220 ident = (LPTSTR)alloca ( ( identlen + 1 ) * sizeof(TCHAR) ); \ 00221 memmove ( ident, p, identlen * sizeof(TCHAR) ); \ 00222 ident[identlen] = 0; \ 00223 p += identlen; 00224 00225 static BOOL 00226 seta_identval ( LPCTSTR ident, INT* result ) 00227 { 00228 LPCTSTR identVal = GetEnvVarOrSpecial ( ident ); 00229 if ( !identVal ) 00230 { 00231 /* TODO FIXME - what to do upon failure? */ 00232 *result = 0; 00233 return FALSE; 00234 } 00235 *result = _tcstol ( identVal, NULL, 0 ); 00236 return TRUE; 00237 } 00238 00239 static BOOL 00240 calc ( INT* lval, TCHAR op, INT rval ) 00241 { 00242 switch ( op ) 00243 { 00244 case '*': 00245 *lval *= rval; 00246 break; 00247 case '/': 00248 *lval /= rval; 00249 break; 00250 case '%': 00251 *lval %= rval; 00252 break; 00253 case '+': 00254 *lval += rval; 00255 break; 00256 case '-': 00257 *lval -= rval; 00258 break; 00259 case '&': 00260 *lval &= rval; 00261 break; 00262 case '^': 00263 *lval ^= rval; 00264 break; 00265 case '|': 00266 *lval |= rval; 00267 break; 00268 default: 00269 ConErrResPuts ( STRING_INVALID_OPERAND ); 00270 return FALSE; 00271 } 00272 return TRUE; 00273 } 00274 00275 static BOOL 00276 seta_stmt ( LPCTSTR* p_, INT* result ); 00277 00278 static BOOL 00279 seta_unaryTerm ( LPCTSTR* p_, INT* result ) 00280 { 00281 LPCTSTR p = *p_; 00282 if ( *p == _T('(') ) 00283 { 00284 INT rval; 00285 p = skip_ws ( p + 1 ); 00286 if ( !seta_stmt ( &p, &rval ) ) 00287 return FALSE; 00288 if ( *p++ != _T(')') ) 00289 { 00290 ConErrResPuts ( STRING_EXPECTED_CLOSE_PAREN ); 00291 return FALSE; 00292 } 00293 *result = rval; 00294 } 00295 else if ( isdigit(*p) ) 00296 { 00297 *result = _tcstol ( p, (LPTSTR *)&p, 0 ); 00298 } 00299 else if ( __iscsymf(*p) ) 00300 { 00301 LPTSTR ident; 00302 INT identlen; 00303 PARSE_IDENT(ident,identlen,p); 00304 if ( !seta_identval ( ident, result ) ) 00305 return FALSE; 00306 } 00307 else 00308 { 00309 ConErrResPuts ( STRING_EXPECTED_NUMBER_OR_VARIABLE ); 00310 return FALSE; 00311 } 00312 *p_ = skip_ws ( p ); 00313 return TRUE; 00314 } 00315 00316 static BOOL 00317 seta_mulTerm ( LPCTSTR* p_, INT* result ) 00318 { 00319 LPCTSTR p = *p_; 00320 TCHAR op = 0; 00321 INT rval; 00322 if ( _tcschr(_T("!~-"),*p) ) 00323 { 00324 op = *p; 00325 p = skip_ws ( p + 1 ); 00326 } 00327 if ( !seta_unaryTerm ( &p, &rval ) ) 00328 return FALSE; 00329 switch ( op ) 00330 { 00331 case '!': 00332 rval = !rval; 00333 break; 00334 case '~': 00335 rval = ~rval; 00336 break; 00337 case '-': 00338 rval = -rval; 00339 break; 00340 } 00341 00342 *result = rval; 00343 *p_ = p; 00344 return TRUE; 00345 } 00346 00347 static BOOL 00348 seta_ltorTerm ( LPCTSTR* p_, INT* result, LPCTSTR ops, BOOL (*subTerm)(LPCTSTR*,INT*) ) 00349 { 00350 LPCTSTR p = *p_; 00351 INT lval; 00352 if ( !subTerm ( &p, &lval ) ) 00353 return FALSE; 00354 while ( *p && _tcschr(ops,*p) ) 00355 { 00356 INT rval; 00357 TCHAR op = *p; 00358 00359 p = skip_ws ( p+1 ); 00360 00361 if ( !subTerm ( &p, &rval ) ) 00362 return FALSE; 00363 00364 if ( !calc ( &lval, op, rval ) ) 00365 return FALSE; 00366 } 00367 00368 *result = lval; 00369 *p_ = p; 00370 return TRUE; 00371 } 00372 00373 static BOOL 00374 seta_addTerm ( LPCTSTR* p_, INT* result ) 00375 { 00376 return seta_ltorTerm ( p_, result, _T("*/%"), seta_mulTerm ); 00377 } 00378 00379 static BOOL 00380 seta_logShiftTerm ( LPCTSTR* p_, INT* result ) 00381 { 00382 return seta_ltorTerm ( p_, result, _T("+-"), seta_addTerm ); 00383 } 00384 00385 static BOOL 00386 seta_bitAndTerm ( LPCTSTR* p_, INT* result ) 00387 { 00388 LPCTSTR p = *p_; 00389 INT lval; 00390 if ( !seta_logShiftTerm ( &p, &lval ) ) 00391 return FALSE; 00392 while ( *p && _tcschr(_T("<>"),*p) && p[0] == p[1] ) 00393 { 00394 INT rval; 00395 TCHAR op = *p; 00396 00397 p = skip_ws ( p+2 ); 00398 00399 if ( !seta_logShiftTerm ( &p, &rval ) ) 00400 return FALSE; 00401 00402 switch ( op ) 00403 { 00404 case '<': 00405 lval <<= rval; 00406 break; 00407 case '>': 00408 lval >>= rval; 00409 break; 00410 default: 00411 ConErrResPuts ( STRING_INVALID_OPERAND ); 00412 return FALSE; 00413 } 00414 } 00415 00416 *result = lval; 00417 *p_ = p; 00418 return TRUE; 00419 } 00420 00421 static BOOL 00422 seta_bitExclOrTerm ( LPCTSTR* p_, INT* result ) 00423 { 00424 return seta_ltorTerm ( p_, result, _T("&"), seta_bitAndTerm ); 00425 } 00426 00427 static BOOL 00428 seta_bitOrTerm ( LPCTSTR* p_, INT* result ) 00429 { 00430 return seta_ltorTerm ( p_, result, _T("^"), seta_bitExclOrTerm ); 00431 } 00432 00433 static BOOL 00434 seta_expr ( LPCTSTR* p_, INT* result ) 00435 { 00436 return seta_ltorTerm ( p_, result, _T("|"), seta_bitOrTerm ); 00437 } 00438 00439 static BOOL 00440 seta_assignment ( LPCTSTR* p_, INT* result ) 00441 { 00442 LPCTSTR p = *p_; 00443 LPTSTR ident; 00444 TCHAR op = 0; 00445 INT identlen, exprval; 00446 00447 PARSE_IDENT(ident,identlen,p); 00448 if ( identlen ) 00449 { 00450 p = skip_ws(p); 00451 if ( *p == _T('=') ) 00452 op = *p, p = skip_ws(p+1); 00453 else if ( _tcschr ( _T("*/%+-&^|"), *p ) && p[1] == _T('=') ) 00454 op = *p, p = skip_ws(p+2); 00455 else if ( _tcschr ( _T("<>"), *p ) && *p == p[1] && p[2] == _T('=') ) 00456 op = *p, p = skip_ws(p+3); 00457 } 00458 00459 /* allow to chain multiple assignments, such as: a=b=1 */ 00460 if ( ident && op ) 00461 { 00462 INT identval; 00463 LPTSTR buf; 00464 00465 if ( !seta_assignment ( &p, &exprval ) ) 00466 return FALSE; 00467 00468 if ( !seta_identval ( ident, &identval ) ) 00469 identval = 0; 00470 switch ( op ) 00471 { 00472 case '=': 00473 identval = exprval; 00474 break; 00475 case '<': 00476 identval <<= exprval; 00477 break; 00478 case '>': 00479 identval >>= exprval; 00480 break; 00481 default: 00482 if ( !calc ( &identval, op, exprval ) ) 00483 return FALSE; 00484 } 00485 buf = (LPTSTR)alloca ( 32 * sizeof(TCHAR) ); 00486 _sntprintf ( buf, 32, _T("%i"), identval ); 00487 SetEnvironmentVariable ( ident, buf ); // TODO FIXME - check return value 00488 exprval = identval; 00489 } 00490 else 00491 { 00492 /* restore p in case we found an ident but not an op */ 00493 p = *p_; 00494 if ( !seta_expr ( &p, &exprval ) ) 00495 return FALSE; 00496 } 00497 00498 *result = exprval; 00499 *p_ = p; 00500 return TRUE; 00501 } 00502 00503 static BOOL 00504 seta_stmt ( LPCTSTR* p_, INT* result ) 00505 { 00506 LPCTSTR p = *p_; 00507 INT rval; 00508 00509 if ( !seta_assignment ( &p, &rval ) ) 00510 return FALSE; 00511 while ( *p == _T(',') ) 00512 { 00513 p = skip_ws ( p+1 ); 00514 00515 if ( !seta_assignment ( &p, &rval ) ) 00516 return FALSE; 00517 } 00518 00519 *result = rval; 00520 *p_ = p; 00521 return TRUE; 00522 } 00523 00524 static BOOL 00525 seta_eval ( LPCTSTR p ) 00526 { 00527 INT rval; 00528 if ( !*p ) 00529 { 00530 ConErrResPuts ( STRING_SYNTAX_COMMAND_INCORRECT ); 00531 return FALSE; 00532 } 00533 if ( !seta_stmt ( &p, &rval ) ) 00534 return FALSE; 00535 if ( !bc ) 00536 ConOutPrintf ( _T("%i"), rval ); 00537 return TRUE; 00538 } 00539 00540 #endif Generated on Sat May 26 2012 04:17:07 for ReactOS by
1.7.6.1
|