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

  1. /***
  2. *spawnvpe.c - spawn a child process with given environ (search PATH)
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines _spawnvpe() - spawn a child process with given environ (search
  8. *       PATH)
  9. *
  10. *******************************************************************************/
  11.  
  12. #include <cruntime.h>
  13. #include <errno.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <malloc.h>
  17. #include <internal.h>
  18. #include <process.h>
  19. #include <mbstring.h>
  20. #include <tchar.h>
  21. #include <dbgint.h>
  22.  
  23. #define SLASH _T("\\")
  24. #define SLASHCHAR _T('\\')
  25. #define XSLASHCHAR _T('/')
  26. #define DELIMITER _T(";")
  27.  
  28. #ifdef _MBCS
  29. /* note, the macro below assumes p is to pointer to a single-byte character
  30.  * or the 1st byte of a double-byte character, in a string.
  31.  */
  32. #define ISPSLASH(p)     ( ((p) == _mbschr((p), SLASHCHAR)) || ((p) == \
  33. _mbschr((p), XSLASHCHAR)) )
  34. #else  /* _MBCS */
  35. #define ISSLASH(c)      ( ((c) == SLASHCHAR) || ((c) == XSLASHCHAR) )
  36. #endif  /* _MBCS */
  37.  
  38. /***
  39. *_spawnvpe(modeflag, filename, argv, envptr) - spawn a child process
  40. *
  41. *Purpose:
  42. *       Spawns a child process with the given arguments and environ,
  43. *       searches along PATH for given file until found.
  44. *       Formats the parameters and calls _spawnve to do the actual work. The
  45. *       NULL environment pointer indicates that the new process will inherit
  46. *       the parents process's environment.  NOTE - at least one argument must
  47. *       be present.  This argument is always, by convention, the name of the
  48. *       file being spawned.
  49. *
  50. *Entry:
  51. *       int modeflag - defines mode of spawn (WAIT, NOWAIT, or OVERLAY)
  52. *                       only WAIT and OVERLAY supported
  53. *       _TSCHAR *filename - name of file to execute
  54. *       _TSCHAR **argv - vector of parameters
  55. *       _TSCHAR **envptr - vector of environment variables
  56. *
  57. *Exit:
  58. *       returns exit code of spawned process
  59. *       if fails, returns -1
  60. *
  61. *Exceptions:
  62. *
  63. *******************************************************************************/
  64.  
  65. int __cdecl _tspawnvpe (
  66.         int modeflag,
  67.         REG3 const _TSCHAR *filename,
  68.         const _TSCHAR * const *argv,
  69.         const _TSCHAR * const *envptr
  70.         )
  71. {
  72.         int i;
  73.         REG1 _TSCHAR *env;
  74.         REG2 _TSCHAR *buf = NULL;
  75.         _TSCHAR *pfin;
  76.         _ASSERTE(filename != NULL);
  77.         _ASSERTE(*filename != _T('\0'));
  78.         _ASSERTE(argv != NULL);
  79.         _ASSERTE(*argv != NULL);
  80.         _ASSERTE(**argv != _T('\0'));
  81.  
  82.  
  83.         if (
  84.         (i = _tspawnve(modeflag, filename, argv, envptr)) != -1
  85.                 /* everything worked just fine; return i */
  86.  
  87.         || (errno != ENOENT)
  88.                 /* couldn't spawn the process, return failure */
  89.  
  90.         || (_tcschr(filename, XSLASHCHAR) != NULL)
  91.                 /* filename contains a '/', return failure */
  92.  
  93.  
  94.         || !(env = _tgetenv(_T("PATH")))
  95.                 /* no PATH environment string name, return failure */
  96.  
  97.         || ( (buf = _malloc_crt(_MAX_PATH * sizeof(_TSCHAR))) == NULL )
  98.                 /* cannot allocate buffer to build alternate pathnames, return
  99.                  * failure */
  100.         ) {
  101.                 goto done;
  102.         }
  103.  
  104.  
  105.  
  106.         /* could not find the file as specified, search PATH. try each
  107.          * component of the PATH until we get either no error return, or the
  108.          * error is not ENOENT and the component is not a UNC name, or we run
  109.          * out of components to try.
  110.          */
  111.  
  112. #ifdef WPRFLAG
  113.         while ( (env = _wgetpath(env, buf, _MAX_PATH - 1)) && (*buf) ) {
  114. #else  /* WPRFLAG */
  115.         while ( (env = _getpath(env, buf, _MAX_PATH - 1)) && (*buf) ) {
  116. #endif  /* WPRFLAG */
  117.  
  118.                 pfin = buf + _tcslen(buf) - 1;
  119.  
  120.                 /* if necessary, append a '/'
  121.                  */
  122. #ifdef _MBCS
  123.                 if (*pfin == SLASHCHAR) {
  124.                         if (pfin != _mbsrchr(buf,SLASHCHAR))
  125.                         /* fin is the second byte of a double-byte char */
  126.                                 strcat(buf, SLASH );
  127.                 }
  128.                 else if (*pfin !=XSLASHCHAR)
  129.                         strcat(buf, SLASH);
  130. #else  /* _MBCS */
  131.                 if (*pfin != SLASHCHAR && *pfin != XSLASHCHAR)
  132.                         _tcscat(buf, SLASH);
  133. #endif  /* _MBCS */
  134.                 /* check that the final path will be of legal size. if so,
  135.                  * build it. otherwise, return to the caller (return value
  136.                  * and errno rename set from initial call to _spawnve()).
  137.                  */
  138.                 if ( (_tcslen(buf) + _tcslen(filename)) < _MAX_PATH )
  139.                         _tcscat(buf, filename);
  140.                 else
  141.                         break;
  142.  
  143.                 /* try spawning it. if successful, or if errno comes back with a
  144.                  * value other than ENOENT and the pathname is not a UNC name,
  145.                  * return to the caller.
  146.                  */
  147.                 if ( (i = _tspawnve(modeflag, buf, argv, envptr)) != -1
  148.                         || ((errno != ENOENT)
  149. #ifdef _MBCS
  150.                                 && (!ISPSLASH(buf) || !ISPSLASH(buf+1))) )
  151. #else  /* _MBCS */
  152.                                 && (!ISSLASH(*buf) || !ISSLASH(*(buf+1)))) )
  153. #endif  /* _MBCS */
  154.                         break;
  155.  
  156.         }
  157.  
  158. done:
  159.         if (buf != NULL)
  160.             _free_crt(buf);
  161.         return(i);
  162. }
  163.