home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / execvpe.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  5KB  |  145 lines

  1. /***
  2. *execvpe.c - execute a file with given environ; search along PATH
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines _execvpe() - execute a file with given environ
  8. *
  9. *******************************************************************************/
  10.  
  11. #include <cruntime.h>
  12. #include <errno.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <process.h>
  16. #include <mbstring.h>
  17. #include <tchar.h>
  18. #include <dbgint.h>
  19.  
  20. #define SLASHCHAR _T('\\')
  21. #define XSLASHCHAR _T('/')
  22.  
  23. #define SLASH _T("\\")
  24. #define DELIMITER _T(";")
  25.  
  26. #ifdef _MBCS
  27. /* note, the macro below assumes p is to pointer to a single-byte character
  28.  * or the 1st byte of a double-byte character, in a string.
  29.  */
  30. #define ISPSLASH(p)     ( ((p) == _mbschr((p), SLASHCHAR)) || ((p) == \
  31. _mbschr((p), XSLASHCHAR)) )
  32. #else  /* _MBCS */
  33. #define ISSLASH(c)      ( ((c) == SLASHCHAR) || ((c) == XSLASHCHAR) )
  34. #endif  /* _MBCS */
  35.  
  36.  
  37. /***
  38. *int _execvpe(filename, argvector, envvector) - execute a file
  39. *
  40. *Purpose:
  41. *       Executes a file with given arguments and environment.
  42. *       try to execute the file. start with the name itself (directory '.'),
  43. *       and if that doesn't work start prepending pathnames from the
  44. *       environment until one works or we run out. if the file is a pathname,
  45. *       don't go to the environment to get alternate paths. If a needed text
  46. *       file is busy, wait a little while and try again before despairing
  47. *       completely
  48. *
  49. *Entry:
  50. *       _TSCHAR *filename        - file to execute
  51. *       _TSCHAR **argvector - vector of arguments
  52. *       _TSCHAR **envvector - vector of environment variables
  53. *
  54. *Exit:
  55. *       destroys the calling process (hopefully)
  56. *       if fails, returns -1
  57. *
  58. *Exceptions:
  59. *
  60. *******************************************************************************/
  61.  
  62. int __cdecl _texecvpe (
  63.         REG3 const _TSCHAR *filename,
  64.         const _TSCHAR * const *argvector,
  65.         const _TSCHAR * const *envptr
  66.         )
  67. {
  68.         REG1 _TSCHAR *env;
  69.         _TSCHAR *bbuf = NULL;
  70.         REG2 _TSCHAR *buf;
  71.         _TSCHAR *pfin;
  72.  
  73.         _ASSERTE(filename != NULL);
  74.         _ASSERTE(*filename != _T('\0'));
  75.         _ASSERTE(argvector != NULL);
  76.         _ASSERTE(*argvector != NULL);
  77.         _ASSERTE(**argvector != _T('\0'));
  78.  
  79.         _texecve(filename,argvector,envptr);
  80.  
  81.         if ( (errno != ENOENT)
  82.         || (_tcschr(filename, SLASHCHAR) != NULL)
  83.         || (_tcschr(filename, XSLASHCHAR) != NULL)
  84.         || *filename && *(filename+1) == _T(':')
  85.         || !(env=_tgetenv(_T("PATH"))) )
  86.                 goto reterror;
  87.  
  88.         /* allocate a buffer to hold alternate pathnames for the executable
  89.          */
  90.         if ( (buf = bbuf = _malloc_crt(_MAX_PATH * sizeof(_TSCHAR))) == NULL )
  91.             goto reterror;
  92.  
  93.         do {
  94.                 /* copy a component into bbuf[], taking care not to overflow it
  95.                  */
  96.                 /* UNDONE: make sure ';' isn't 2nd byte of DBCS char */
  97.                 while ( (*env) && (*env != _T(';')) && (buf < bbuf+(_MAX_PATH-2)*sizeof(_TSCHAR)) )
  98.                         *buf++ = *env++;
  99.  
  100.                 *buf = _T('\0');
  101.                 pfin = --buf;
  102.                 buf = bbuf;
  103.  
  104. #ifdef _MBCS
  105.                 if (*pfin == SLASHCHAR) {
  106.                         if (pfin != _mbsrchr(buf,SLASHCHAR))
  107.                                 /* *pfin is the second byte of a double-byte
  108.                                  * character
  109.                                  */
  110.                                 strcat( buf, SLASH );
  111.                 }
  112.                 else if (*pfin != XSLASHCHAR)
  113.                         strcat(buf, SLASH);
  114. #else  /* _MBCS */
  115.                 if (*pfin != SLASHCHAR && *pfin != XSLASHCHAR)
  116.                         _tcscat(buf, SLASH);
  117. #endif  /* _MBCS */
  118.  
  119.                 /* check that the final path will be of legal size. if so,
  120.                  * build it. otherwise, return to the caller (return value
  121.                  * and errno rename set from initial call to _execve()).
  122.                  */
  123.                 if ( (_tcslen(buf) + _tcslen(filename)) < _MAX_PATH )
  124.                         _tcscat(buf, filename);
  125.                 else
  126.                         break;
  127.  
  128.                 _texecve(buf, argvector, envptr);
  129.  
  130.                 if ( (errno != ENOENT)
  131. #ifdef _MBCS
  132.                 && (!ISPSLASH(buf) || !ISPSLASH(buf+1)) )
  133. #else  /* _MBCS */
  134.                 && (!ISSLASH(*buf) || !ISSLASH(*(buf+1))) )
  135. #endif  /* _MBCS */
  136.                         break;
  137.         } while ( *env && env++ );
  138.  
  139. reterror:
  140.         if (bbuf != NULL)
  141.                 _free_crt(bbuf);
  142.  
  143.         return(-1);
  144. }
  145.