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.

367 lines
9.0 KiB

  1. /*******************************************************************************
  2. *
  3. * SETARGVA.C (ANSI argc, argv routines)
  4. *
  5. * argc / argv routines
  6. *
  7. * Copyright Citrix Systems Inc. 1995
  8. * Copyright (C) 1997-1999 Microsoft Corp.
  9. *
  10. * $Author: butchd $
  11. ******************************************************************************/
  12. /*
  13. * Include files
  14. */
  15. #include <windows.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. /*
  20. * ANSI ARGS structure and other stuff (private).
  21. */
  22. #include "setargva.h"
  23. /*
  24. * Local function prototypes.
  25. */
  26. void args_init(ARGS *);
  27. int add_arg_to_list(char *, ARGS *);
  28. int args_trunc(ARGS *);
  29. /*
  30. * setargvA()
  31. *
  32. * Forms a standard C-runtime argc, argv parsed command line.
  33. *
  34. * ENTRY:
  35. * szModuleName (input)
  36. * Optional Windows module name. If not NULL, will be added as first
  37. * parsed argument (argv[0], argc=1).
  38. * szCmdLine (input)
  39. * Points to command line to parse into argc, argv
  40. * argc (output)
  41. * Points to int to save argument count into on exit.
  42. * argv (output)
  43. * Points to (char **) to save argv array into on exit.
  44. *
  45. * RETURNS:
  46. * ERROR_SUCCESS if ok; ERROR_xxx code if not ok.
  47. *
  48. * A typical use of this routine is by a Windows UI application to
  49. * convert a command line into the C argc & argv variables prior to calling
  50. * the utilsub.lib ParseCommandLine() function. Therefore, a companion
  51. * routine, freeargv(), allows for alloc'd memory to be freed by the caller
  52. * after use, if desired.
  53. *
  54. */
  55. int WINAPI
  56. setargvA( LPSTR szModuleName,
  57. LPSTR szCmdLine,
  58. int *argc,
  59. char ***argv )
  60. {
  61. int rc;
  62. char *cp;
  63. char FAR *cfp = szCmdLine;
  64. char ch, fname[_MAX_PATH];
  65. ARGS arg_data;
  66. /*
  67. * Initialize arg_data
  68. */
  69. args_init( &arg_data );
  70. /*
  71. * If present, add module name as argv[0].
  72. */
  73. if ( szModuleName ) {
  74. if ( (rc = add_arg_to_list( szModuleName, &arg_data )) != ERROR_SUCCESS )
  75. goto setargv_error;
  76. }
  77. /*
  78. * Skip leading blanks/tabs of remaining args
  79. */
  80. cp = fname;
  81. /* skip consecutive blanks and/or tabs */
  82. while ( (ch = *cfp) == ' ' || ch == '\t' )
  83. cfp++;
  84. /*
  85. * Process remainder of command line
  86. */
  87. while ( ch = *cfp++ ) {
  88. /*
  89. * Process quoted strings.
  90. */
  91. if ( ch == '"' ) {
  92. while ( (ch = *cfp++) && ch != '"' )
  93. *cp++ = ch;
  94. if ( ch == '\0' )
  95. cfp--;
  96. /*
  97. * If we find a delimeter, process the pathname we just scanned.
  98. */
  99. } else if ( ch == ' ' || ch == '\t') {
  100. *cp = '\0';
  101. if ( (rc = add_arg_to_list( fname, &arg_data )) != ERROR_SUCCESS )
  102. goto setargv_error;
  103. cp = fname;
  104. /* skip consecutive blanks and/or tabs */
  105. while ( (ch = *cfp) == ' ' || ch == '\t')
  106. cfp++;
  107. /*
  108. * All other chars, just copy to internal buffer.
  109. */
  110. } else {
  111. *cp++ = ch;
  112. }
  113. }
  114. if ( cp != fname ) {
  115. *cp = '\0';
  116. if ( (rc = add_arg_to_list( fname, &arg_data )) != ERROR_SUCCESS )
  117. goto setargv_error;
  118. }
  119. if ( (rc = args_trunc( &arg_data )) != ERROR_SUCCESS )
  120. goto setargv_error;
  121. /*
  122. * Initialize global variables __argc and __argv
  123. */
  124. *argc = arg_data.argc;
  125. *argv = arg_data.argv;
  126. return(ERROR_SUCCESS);
  127. //--------------
  128. // Error return
  129. //--------------
  130. setargv_error:
  131. return(rc);
  132. }
  133. /*
  134. * freeargvA()
  135. *
  136. * Frees up the memory alloc'd for argv strings and argv
  137. * array itself.
  138. *
  139. * ENTER:
  140. * argv = argv array as created by this setargv() routine.
  141. *
  142. */
  143. void WINAPI
  144. freeargvA( char **argv )
  145. {
  146. free(*argv);
  147. free(argv);
  148. }
  149. /*
  150. * args_init()
  151. *
  152. * Initialize the ARGS struct passed as an argument.
  153. *
  154. * ENTER:
  155. * argp = pointer to ARGS struct
  156. *
  157. */
  158. static void
  159. args_init( ARGS *argp )
  160. {
  161. argp->argc = 0;
  162. argp->argv = NULL;
  163. argp->argvlen = 0;
  164. argp->argvp = NULL;
  165. argp->buflen = 0;
  166. argp->buf = argp->bufptr = argp->bufend = NULL;
  167. }
  168. /*
  169. * add_arg_to_list()
  170. *
  171. * This routine adds the specified argument string to the argv array,
  172. * and increments the argv pointer and argc counter.
  173. * If necessary, memory for the argument string is allocated.
  174. *
  175. * RETURNS:
  176. * ERROR_SUCCESS if ok; ERROR_NOT_ENOUGH_MEMORY if not.
  177. *
  178. */
  179. static int
  180. add_arg_to_list( char *arg_string,
  181. ARGS *argp )
  182. {
  183. int len;
  184. #ifdef notdef
  185. printf( "add_arg_to_list: arg_string=%s:, argc=%d, argvp=%x",
  186. arg_string,argp->argc,argp->argvp );
  187. #endif
  188. /*
  189. * Verify we have an argv array buffer.
  190. * If we have one but it is full, expand the array.
  191. * If we can't alloc/realloc the array, return an error.
  192. */
  193. if ( !argp->argv ) {
  194. argp->argvlen = MIN_ARG_ALLOC;
  195. argp->argc = 0;
  196. argp->argv = malloc( argp->argvlen * sizeof( char *) );
  197. argp->argvp = argp->argv;
  198. } else if ( argp->argc + 1 >= argp->argvlen ) {
  199. argp->argvlen += MIN_ARG_ALLOC;
  200. argp->argv = realloc( argp->argv, argp->argvlen * sizeof(char *) );
  201. argp->argvp = argp->argv + argp->argc;
  202. }
  203. if ( !argp->argv ) {
  204. #ifdef notdef
  205. printf("add_arg_to_list: failed to (re)alloc argv buf\n");
  206. #endif
  207. goto add_arg_to_list_error;
  208. }
  209. /*
  210. * Verify we have a string buffer to store the argument string.
  211. * If we have one but there is not room for the new arg, expand the
  212. * buffer. If we can't alloc/realloc the buffer, return an error.
  213. */
  214. len = strlen( arg_string ) + 1;
  215. if ( !argp->buf ) {
  216. argp->buflen = MIN_BUF_ALLOC;
  217. while ( argp->buflen < len )
  218. argp->buflen += MIN_BUF_ALLOC;
  219. argp->buf = malloc( argp->buflen );
  220. argp->bufptr = argp->buf;
  221. argp->bufend = argp->buf + argp->buflen - 1;
  222. } else if ( argp->bufptr + len > argp->bufend ) {
  223. char *old_buf;
  224. int buf_offset = (int)(argp->bufptr - argp->buf);
  225. while ( argp->buflen < buf_offset + len )
  226. argp->buflen += MIN_BUF_ALLOC;
  227. old_buf = argp->buf;
  228. argp->buf = realloc( argp->buf, argp->buflen );
  229. argp->bufend = argp->buf + argp->buflen - 1;
  230. argp->bufptr = argp->buf + buf_offset;
  231. /*
  232. * If the argument string buffer moved, then we need to relocate the
  233. * argv pointers in the argv array to point to the new string locations.
  234. */
  235. if ( argp->buf != old_buf ) {
  236. char *buf_ptr, **argv_ptr;
  237. argv_ptr = argp->argv;
  238. buf_ptr = argp->buf;
  239. while ( buf_ptr != argp->bufptr ) {
  240. *argv_ptr++ = buf_ptr;
  241. buf_ptr += strlen( buf_ptr ) + 1;
  242. }
  243. }
  244. }
  245. if ( !argp->buf ) {
  246. #ifdef notdef
  247. printf("add_arg_to_list: failed to (re)alloc string buf\n");
  248. #endif
  249. goto add_arg_to_list_error;
  250. }
  251. /*
  252. * Add the new argument to the buffer and the argv array.
  253. * Increment the arg count, the argv pointer, and the buffer pointer.
  254. */
  255. strcpy( argp->bufptr, arg_string );
  256. *(argp->argvp) = argp->bufptr;
  257. argp->bufptr += len;
  258. ++argp->argc;
  259. ++argp->argvp;
  260. *(argp->argvp) = NULL;
  261. return(ERROR_SUCCESS);
  262. //--------------
  263. // Error return
  264. //--------------
  265. add_arg_to_list_error:
  266. return(ERROR_NOT_ENOUGH_MEMORY);
  267. }
  268. /*
  269. * args_trunc()
  270. *
  271. * Truncate the memory used by the ARGS struct
  272. * so that unused memory is freed.
  273. *
  274. * ENTER:
  275. * argp = pointer to ARGS struct
  276. *
  277. * RETURNS:
  278. * ERROR_SUCCESS if ok; ERROR_NOT_ENOUGH_MEMORY code if not ok.
  279. *
  280. */
  281. static int
  282. args_trunc( ARGS *argp )
  283. {
  284. char *old_buf;
  285. /*
  286. * call realloc to shrink size of argv array, set argvlen = argc
  287. * to indicate no more room in argv array.
  288. */
  289. argp->argvlen = argp->argc + 1;
  290. argp->argv = realloc( argp->argv, argp->argvlen * sizeof(char *) );
  291. if ( !argp->argv )
  292. goto args_trunc_error;
  293. argp->argvp = argp->argv + argp->argc;
  294. /*
  295. * call realloc to shrink size of argument string buffer, set bufend
  296. * pointer to end of buffer to indicate buf is full.
  297. */
  298. old_buf = argp->buf;
  299. argp->buflen = (int)(argp->bufptr - argp->buf);
  300. argp->buf = realloc( argp->buf, argp->buflen );
  301. if ( !argp->buf )
  302. goto args_trunc_error;
  303. argp->bufptr = argp->buf + argp->buflen;
  304. argp->bufend = argp->buf + argp->buflen - 1;
  305. /*
  306. * If the argument string buffer moved, then we need to relocate the
  307. * argv pointers in the argv array to point to the new string locations.
  308. */
  309. if ( old_buf != argp->buf ) {
  310. char *buf_ptr, **argv_ptr;
  311. argv_ptr = argp->argv;
  312. buf_ptr = argp->buf;
  313. while ( buf_ptr != argp->bufptr ) {
  314. *argv_ptr++ = buf_ptr;
  315. buf_ptr += strlen( buf_ptr ) + 1;
  316. }
  317. }
  318. return(ERROR_SUCCESS);
  319. //--------------
  320. // Error return
  321. //--------------
  322. args_trunc_error:
  323. return(ERROR_NOT_ENOUGH_MEMORY);
  324. }