Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

311 lines
7.3 KiB

  1. /********************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1987-1990 **/
  4. /********************************************************************/
  5. /*
  6. * Switches.c - switch handling routines
  7. *
  8. * ??/??/??, ??????, initial code
  9. * 10/31/88, erichn, uses OS2.H instead of DOSCALLS
  10. * 12/04/88, erichn, DOS LM integration
  11. * 06/08/89, erichn, canonicalization sweep, stronger typing
  12. * 02/20/91, danhi, change to use lm 16/32 mapping layer
  13. */
  14. #define INCL_NOCOMMON
  15. #include <os2.h>
  16. #include <apperr.h>
  17. #include <lmerr.h>
  18. #include <stdio.h>
  19. #include <process.h>
  20. #include <ctype.h>
  21. #include <malloc.h>
  22. #include "netcmds.h"
  23. #include "nettext.h"
  24. /* External variables */
  25. int DOSNEAR FASTCALL firstswitch(TCHAR *known)
  26. {
  27. if (SwitchList[0] == NULL)
  28. return 0;
  29. if (sw_compare(known, SwitchList[0]) >= 0)
  30. return 1;
  31. else
  32. return 0;
  33. }
  34. /*
  35. * Is the cmd line a valid form of NET ADMIN /C
  36. */
  37. int DOSNEAR FASTCALL IsAdminCommand(VOID)
  38. {
  39. if (!SwitchList[0] || !ArgList[1])
  40. return 0;
  41. _tcsupr(SwitchList[0]);
  42. return (IsComputerName(ArgList[1]) &&
  43. (sw_compare(swtxt_SW_ADMIN_COMMAND, SwitchList[0]) >= 0));
  44. }
  45. /*** noswitch, oneswitch, twoswitch
  46. *
  47. * noswitch() Returns TRUE is no switches on the command line
  48. * oneswitch() Returns TRUE is there is exactly one switch
  49. * twoswitch() Returns TRUE is there are exactly two switches
  50. *
  51. */
  52. int DOSNEAR FASTCALL noswitch(VOID)
  53. {
  54. return (SwitchList[0] == NULL);
  55. }
  56. int DOSNEAR FASTCALL oneswitch(VOID)
  57. {
  58. return ((SwitchList[0] != NULL) && (SwitchList[1] == NULL));
  59. }
  60. int DOSNEAR FASTCALL twoswitch(VOID)
  61. {
  62. return ((SwitchList[0] != NULL) && (SwitchList[1] != NULL)
  63. && (SwitchList[2] == NULL));
  64. }
  65. /*** noswitch_optional, oneswitch_optional
  66. *
  67. * as above, except that the switch provided as argument is considered
  68. * an optional switch that will be allowed. So if you say
  69. * oneswitch_optional("/FOO"), then one switch (any switch) is OK,
  70. * and so is two switches if one of them is "/FOO".
  71. */
  72. int DOSNEAR FASTCALL noswitch_optional(TCHAR *optional_switch )
  73. {
  74. return ( noswitch() ||
  75. ( oneswitch() &&
  76. (sw_compare(optional_switch, SwitchList[0]) >= 0) )
  77. ) ;
  78. }
  79. int DOSNEAR FASTCALL oneswitch_optional(TCHAR *optional_switch )
  80. {
  81. return ( oneswitch() ||
  82. ( twoswitch() &&
  83. ( (sw_compare(optional_switch, SwitchList[0]) >= 0) ||
  84. (sw_compare(optional_switch, SwitchList[1]) >= 0) ) )
  85. ) ;
  86. }
  87. /***
  88. * o n l y s w i t c h
  89. *
  90. * Returns TRUE if the first switch matches the named switch, and it
  91. * is the only switch.
  92. */
  93. int DOSNEAR FASTCALL onlyswitch(TCHAR *known)
  94. {
  95. return (oneswitch() && firstswitch(known));
  96. }
  97. /*** ValidateSwitches
  98. *
  99. * Given a list of valid switches, check each entry in the switch
  100. * list.
  101. *
  102. * This function not only checks for invalid switches, but also
  103. * attempts to discern ambiguous usages. A usage is ambiguous if
  104. * it does not match any valid swithc exactly, and it a partial
  105. * match of more than one switch. See sw_compare(). This
  106. * algorithm can be fooled by nasty lists of valid switches, such
  107. * as one which lists the same switch twice.
  108. *
  109. * The function has been modified to canonicalize the SwitchList.
  110. * It replaces an '=' in /x=value with a ':'; it translates
  111. * switches if needed, (see switches.h); and it expands unambiguous
  112. * partial matches to the full switch name.
  113. *
  114. * Returns:
  115. * 1: All switches OK
  116. * *: If any error, prints a message and exits.
  117. *
  118. */
  119. int DOSNEAR FASTCALL ValidateSwitches(USHORT cmd, SWITCHTAB valid_list[])
  120. {
  121. USHORT match;
  122. int comp_result;
  123. USHORT candidate; /* most recent NEAR match */
  124. USHORT i,j;
  125. TCHAR * good_one; /* which element (cmd_line or trans) of the valid_list */
  126. int needed;
  127. TCHAR FAR * sepptr;
  128. for (i = 0; SwitchList[i]; i++)
  129. {
  130. sepptr = _tcschr(SwitchList[i], ':');
  131. if (sepptr)
  132. *sepptr = NULLC;
  133. _tcsupr(SwitchList[i]);
  134. if (sepptr)
  135. *sepptr = ':';
  136. candidate = 0;
  137. match = 0;
  138. for (j = 0; valid_list[j].cmd_line; j++)
  139. {
  140. comp_result = sw_compare(valid_list[j].cmd_line, SwitchList[i]);
  141. if (comp_result == 0)
  142. {
  143. candidate = j;
  144. match = 1;
  145. break;
  146. }
  147. else if (comp_result == 1)
  148. {
  149. match++;
  150. candidate = j;
  151. }
  152. }
  153. if (match == 0)
  154. {
  155. if (! _tcscmp(swtxt_SW_HELP, SwitchList[i]))
  156. help_help(cmd, ALL);
  157. if (! _tcscmp(swtxt_SW_SYNTAX, SwitchList[i]))
  158. help_help(cmd, USAGE_ONLY);
  159. IStrings[0] = SwitchList[i];
  160. ErrorPrint(APE_SwUnkSw, 1);
  161. help_help(cmd, USAGE_ONLY);
  162. }
  163. else if (match > 1)
  164. {
  165. IStrings[0] = SwitchList[i];
  166. ErrorPrint(APE_SwAmbSw, 1);
  167. help_help(cmd, USAGE_ONLY);
  168. }
  169. switch(valid_list[candidate].arg_ok)
  170. {
  171. case NO_ARG:
  172. if (sepptr)
  173. {
  174. ErrorPrint(APE_InvalidSwitchArg, 0);
  175. help_help(cmd, USAGE_ONLY);
  176. }
  177. break;
  178. case ARG_OPT:
  179. break;
  180. case ARG_REQ:
  181. if (!sepptr)
  182. {
  183. ErrorPrint(APE_InvalidSwitchArg, 0);
  184. help_help(cmd, USAGE_ONLY);
  185. }
  186. break;
  187. }
  188. /* (expansion || translation) required ? */
  189. if (comp_result || valid_list[candidate].translation)
  190. {
  191. if (valid_list[candidate].translation)
  192. good_one = valid_list[candidate].translation;
  193. else
  194. good_one = valid_list[candidate].cmd_line;
  195. needed = _tcslen(good_one);
  196. if (sepptr)
  197. needed += _tcslen(sepptr);
  198. if ((SwitchList[i] = calloc(needed+1, sizeof(TCHAR))) == NULL)
  199. ErrorExit(NERR_InternalError);
  200. _tcscpy(SwitchList[i], good_one);
  201. if (sepptr)
  202. _tcscat(SwitchList[i], sepptr);
  203. }
  204. }
  205. return 1;
  206. }
  207. /*** sw_compare
  208. *
  209. * Compare a known switch name to a switch string passed from
  210. * the command line.
  211. *
  212. * The command-line switch may still retain the "excess baggage"
  213. * of a value (as in /B:1024). The comparison is not sensitive
  214. * to case, and should be DBCS compatible as it uses the runtime
  215. * library to do all searches and compares.
  216. *
  217. * Returns:
  218. * -1: No match
  219. * 0: Exact match to full length of known switch
  220. * 1: Partial match; matches initial substring of
  221. * known switch
  222. *
  223. * The difference between return 0/1 is used by ValidateSwitches()
  224. * to detect the presence of a possibly ambiguous usage. Once
  225. * that function has checked all switches, further compares can
  226. * treat results 0 & 1 from this function as "match".
  227. */
  228. int DOSNEAR FASTCALL sw_compare(TCHAR *known, TCHAR *cand)
  229. {
  230. register unsigned int complen;
  231. /* Try to find end of switch name by looking */
  232. /* the for separator between name and value, */
  233. /* otherwise use total length. */
  234. complen = _tcscspn(cand, TEXT(":"));
  235. if (complen < 2) /* Special check for empty switch SLASH */
  236. return -1;
  237. if (complen > _tcslen(known))
  238. return -1;
  239. if (_tcsncmp(known,cand,complen) != 0)
  240. return -1;
  241. if (complen == _tcslen(known))
  242. return 0;
  243. return 1;
  244. }
  245. /*
  246. * Used only by interpre.c
  247. */
  248. int DOSNEAR FASTCALL CheckSwitch(TCHAR *x)
  249. {
  250. register TCHAR **p;
  251. for (p=SwitchList; *p; p++)
  252. if (sw_compare(x,*p) >= 0)
  253. {
  254. return 1;
  255. }
  256. return 0;
  257. }