Source code of Windows XP (NT5)
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.

177 lines
6.3 KiB

  1. /***
  2. *execvpe.c - execute a file with given environ; search along PATH
  3. *
  4. * Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * defines _execvpe() - execute a file with given environ
  8. *
  9. *Revision History:
  10. * 10-17-83 RN written
  11. * 10-29-85 TC added execvpe capability
  12. * 11-19-86 SKS handle both kinds of slashes
  13. * 12-01-86 JMB added Kanji file name support under conditional KANJI
  14. * switches, corrected header info
  15. * removed bogus check for env = b after call to strncpy().
  16. * 12-11-87 JCR Added "_LOAD_DS" to declaration
  17. * 09-05-88 SKS Treat EACCES the same as ENOENT -- keep trying
  18. * 10-18-88 GJF Removed copy of PATH string to local array, changed
  19. * bbuf to be a malloc-ed buffer. Removed bogus limits
  20. * on the size of that PATH string.
  21. * 10-26-88 GJF Don't search PATH when relative pathname is given (per
  22. * Stevesa). Also, if the name built from PATH component
  23. * and filename is a UNC name, allow any error.
  24. * 11-20-89 GJF Fixed copyright. Added const attribute to types of
  25. * filename, argvector and envptr. Also, added "#include
  26. * <jstring.h>" under KANJI switch (same as 5-17-89 change
  27. * to CRT version).
  28. * 03-08-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include
  29. * <cruntime.h> and removed #include <register.h>. Also,
  30. * cleaned up the formatting a bit.
  31. * 07-24-90 SBM Removed redundant includes, replaced <assertm.h> by
  32. * <assert.h>
  33. * 09-27-90 GJF New-style function declarator.
  34. * 01-17-91 GJF ANSI naming.
  35. * 11-30-92 KRS Port _MBCS code from 16-bit tree.
  36. * 04-06-93 SKS Replace _CRTAPI* with __cdecl
  37. * 12-07-93 CFW Wide char enable.
  38. * 01-10-95 CFW Debug CRT allocs.
  39. * 02-06-95 CFW assert -> _ASSERTE.
  40. * 02-06-98 GJF Changes for Win64: changed return type to intptr_t.
  41. *
  42. *******************************************************************************/
  43. #include <cruntime.h>
  44. #include <errno.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <process.h>
  48. #include <mbstring.h>
  49. #include <tchar.h>
  50. #include <dbgint.h>
  51. #define SLASHCHAR _T('\\')
  52. #define XSLASHCHAR _T('/')
  53. #define SLASH _T("\\")
  54. #define DELIMITER _T(";")
  55. #ifdef _MBCS
  56. /* note, the macro below assumes p is to pointer to a single-byte character
  57. * or the 1st byte of a double-byte character, in a string.
  58. */
  59. #define ISPSLASH(p) ( ((p) == _mbschr((p), SLASHCHAR)) || ((p) == \
  60. _mbschr((p), XSLASHCHAR)) )
  61. #else
  62. #define ISSLASH(c) ( ((c) == SLASHCHAR) || ((c) == XSLASHCHAR) )
  63. #endif
  64. /***
  65. *int _execvpe(filename, argvector, envvector) - execute a file
  66. *
  67. *Purpose:
  68. * Executes a file with given arguments and environment.
  69. * try to execute the file. start with the name itself (directory '.'),
  70. * and if that doesn't work start prepending pathnames from the
  71. * environment until one works or we run out. if the file is a pathname,
  72. * don't go to the environment to get alternate paths. If a needed text
  73. * file is busy, wait a little while and try again before despairing
  74. * completely
  75. *
  76. *Entry:
  77. * _TSCHAR *filename - file to execute
  78. * _TSCHAR **argvector - vector of arguments
  79. * _TSCHAR **envvector - vector of environment variables
  80. *
  81. *Exit:
  82. * destroys the calling process (hopefully)
  83. * if fails, returns -1
  84. *
  85. *Exceptions:
  86. *
  87. *******************************************************************************/
  88. intptr_t __cdecl _texecvpe (
  89. REG3 const _TSCHAR *filename,
  90. const _TSCHAR * const *argvector,
  91. const _TSCHAR * const *envptr
  92. )
  93. {
  94. REG1 _TSCHAR *env;
  95. _TSCHAR *bbuf = NULL;
  96. REG2 _TSCHAR *buf;
  97. _TSCHAR *pfin;
  98. _ASSERTE(filename != NULL);
  99. _ASSERTE(*filename != _T('\0'));
  100. _ASSERTE(argvector != NULL);
  101. _ASSERTE(*argvector != NULL);
  102. _ASSERTE(**argvector != _T('\0'));
  103. _texecve(filename,argvector,envptr);
  104. if ( (errno != ENOENT)
  105. || (_tcschr(filename, SLASHCHAR) != NULL)
  106. || (_tcschr(filename, XSLASHCHAR) != NULL)
  107. || *filename && *(filename+1) == _T(':')
  108. || !(env=_tgetenv(_T("PATH"))) )
  109. goto reterror;
  110. /* allocate a buffer to hold alternate pathnames for the executable
  111. */
  112. if ( (buf = bbuf = _malloc_crt(_MAX_PATH * sizeof(_TSCHAR))) == NULL )
  113. goto reterror;
  114. do {
  115. /* copy a component into bbuf[], taking care not to overflow it
  116. */
  117. /* UNDONE: make sure ';' isn't 2nd byte of DBCS char */
  118. while ( (*env) && (*env != _T(';')) && (buf < bbuf+(_MAX_PATH-2)*sizeof(_TSCHAR)) )
  119. *buf++ = *env++;
  120. *buf = _T('\0');
  121. pfin = --buf;
  122. buf = bbuf;
  123. #ifdef _MBCS
  124. if (*pfin == SLASHCHAR) {
  125. if (pfin != _mbsrchr(buf,SLASHCHAR))
  126. /* *pfin is the second byte of a double-byte
  127. * character
  128. */
  129. strcat( buf, SLASH );
  130. }
  131. else if (*pfin != XSLASHCHAR)
  132. strcat(buf, SLASH);
  133. #else
  134. if (*pfin != SLASHCHAR && *pfin != XSLASHCHAR)
  135. _tcscat(buf, SLASH);
  136. #endif
  137. /* check that the final path will be of legal size. if so,
  138. * build it. otherwise, return to the caller (return value
  139. * and errno rename set from initial call to _execve()).
  140. */
  141. if ( (_tcslen(buf) + _tcslen(filename)) < _MAX_PATH )
  142. _tcscat(buf, filename);
  143. else
  144. break;
  145. _texecve(buf, argvector, envptr);
  146. if ( (errno != ENOENT)
  147. #ifdef _MBCS
  148. && (!ISPSLASH(buf) || !ISPSLASH(buf+1)) )
  149. #else
  150. && (!ISSLASH(*buf) || !ISSLASH(*(buf+1))) )
  151. #endif
  152. break;
  153. } while ( *env && env++ );
  154. reterror:
  155. if (bbuf != NULL)
  156. _free_crt(bbuf);
  157. return(-1);
  158. }