static Character const* __cdecl get_tmp_directory() throw()
{
    typedef __acrt_stdio_char_traits<Character> stdio_traits;

    static Character const tmp_name[] = { 'T', 'M', 'P', '\0' };

    Character* tmp_value = nullptr;
    if (_ERRCHECK_EINVAL(stdio_traits::tdupenv_s_crt(&tmp_value, nullptr, tmp_name)) != 0)
        return nullptr;

    return tmp_value;
}
Exemple #2
0
/***
*int _cenvarg(argv, envp, argblk, envblk, name) - set up cmd line/environ
*
*Purpose:
*       Set up the block forms of  the environment and the command line.
*       If "envp" is null, "_environ" is used instead.
*
*Entry:
*       _TSCHAR **argv   - argument vector
*       _TSCHAR **envp   - environment vector
*       _TSCHAR **argblk - pointer to pointer set to malloc'ed space for args
*       _TSCHAR **envblk - pointer to pointer set to malloc'ed space for env
*       _TSCHAR *name    - name of program being invoked
*
*Exit:
*       returns 0 if ok, -1 if fails
*       stores through argblk and envblk
*       (calls malloc)
*
*Exceptions:
*
*******************************************************************************/

#ifdef WPRFLAG
int __cdecl _wcenvarg (
#else  /* WPRFLAG */
int __cdecl _cenvarg (
#endif  /* WPRFLAG */
        const _TSCHAR * const *argv,
        const _TSCHAR * const *envp,
        _TSCHAR **argblk,
        _TSCHAR **envblk,
        const _TSCHAR *name
        )
{
        REG1 const _TSCHAR * const *vp;
        REG2 unsigned tmp;
        REG3 _TSCHAR *cptr;
        unsigned arg_len;
        unsigned env_len;
        int cfi_len;            /* counts the number of file handles in CFI */
        int retval = 0;

        /*
         * Null environment pointer "envp" means use global variable,
         * "_environ"
         */

        int cwd_start;
        int cwd_end;            /* length of "cwd" strings in environment */

        _TSCHAR envpfx[] = _T("SystemRoot");
        _TSCHAR *envbuf = NULL;
        int envsize = 0;
        int defined = 0;

        /*
         * Allocate space for command line string
         *  tmp counts the number of bytes in the command line string
         *      including spaces between arguments
         *  An empty string is special -- 2 bytes
         */

        for (vp = argv, tmp = 2; *vp; tmp += (unsigned int)_tcslen(*vp++) + 1) ;

        arg_len = tmp;

        /*
         * Allocate space for the command line plus 2 null bytes
         */

        if ( (*argblk = _calloc_crt(tmp, sizeof(_TSCHAR))) == NULL)
        {
                *envblk = NULL;
                errno = ENOMEM;
                _doserrno = E_nomem;
                return(-1);
        }

        if (_ERRCHECK_EINVAL(_tdupenv_s_crt(&envbuf, NULL, envpfx)) != 0)
        {
                retval = -1;
                goto error;
        }

        envsize = (int)_tcslen(envpfx) + 2;
        if (envbuf != NULL)
        {
            envsize += (int)_tcslen(envbuf);
        }

        /*
         * Allocate space for environment strings
         *  tmp counts the number of bytes in the environment strings
         *      including nulls between strings
         *  Also add "_C_FILE_INFO=" string
         */
        if (envp)
                for (vp = envp, tmp = 2; *vp; tmp += (unsigned int)_tcslen(*vp++) + 1) ;

        /*
         * The _osfile and _osfhnd arrays are passed as binary data in
         * dospawn.c
         */
        cfi_len = 0;    /* no _C_FILE_INFO */

        if (!envp)
                *envblk = NULL;
        else {
                /*
                 * Now that we've decided to pass our own environment block,
                 * compute the size of the "current directory" strings to
                 * propagate to the new environment.
                 */

#ifdef WPRFLAG
                /*
                 * Make sure wide environment exists.
                 */
                if (!_wenvptr)
                {
                        if ((_wenvptr = (wchar_t *)__crtGetEnvironmentStringsW()) == NULL)
                        {
                                retval = -1;
                                goto error;
                        }
                }
#else  /* WPRFLAG */
                if (!_aenvptr)
                {
                        if ((_aenvptr = (char *)__crtGetEnvironmentStringsA()) == NULL)
                        {
                                retval = -1;
                                goto error;
                        }
                }
#endif  /* WPRFLAG */

                /*
                 * search for the first one
                 */
                for (cwd_start = 0;
                     _tenvptr[cwd_start] != _T('\0') &&
                       _tenvptr[cwd_start] != _T('=');
                     cwd_start += (int)_tcslen(&_tenvptr[cwd_start]) + 1)
                {
                }

                /* find the total size of all contiguous ones */
                cwd_end = cwd_start;
                while (_tenvptr[cwd_end+0] == _T('=') &&
                       _tenvptr[cwd_end+1] != _T('\0') &&
                       _tenvptr[cwd_end+2] == _T(':') &&
                       _tenvptr[cwd_end+3] == _T('='))
                {
                        cwd_end += 4 + (int)_tcslen(&_tenvptr[cwd_end+4]) + 1;
                }
                tmp += cwd_end - cwd_start;

                /*
                 * Allocate space for the environment strings plus extra null byte
                 */
                env_len = tmp;

                /*
                 * Check if SystemRoot is already defined in environment provided
                 */
                for (vp = envp; *vp; vp++) {
                        if (_tcsncicmp(*vp, envpfx, _tcslen(envpfx)) == 0) {
                                defined = 1;
                                break;
                        }
                }

                if (!defined)
                        tmp += envsize;

                if( !(*envblk = _calloc_crt(tmp, sizeof(_TSCHAR))) )
                {
                        _free_crt(*argblk);
                        *argblk = NULL;
                        errno = ENOMEM;
                        _doserrno = E_nomem;
                        retval = -1;
                        goto done;
                }
        }

        /*
         * Build the command line by concatenating the argument strings
         * with spaces between, and two null bytes at the end.
         * NOTE: The argv[0] argument is followed by a null.
         */

        cptr = *argblk;
        vp = argv;

        if (!*vp)       /* Empty argument list ? */
                ++cptr; /* just two null bytes */
        else {          /* argv[0] must be followed by a null */
                _ERRCHECK(_tcscpy_s(cptr, arg_len - (cptr - *argblk), *vp));
                cptr += (int)_tcslen(*vp++) + 1;
        }

        while( *vp ) {
                _ERRCHECK(_tcscpy_s(cptr, arg_len - (cptr - *argblk), *vp));
                cptr += (int)_tcslen(*vp++);
                *cptr++ = ' ';
        }

        *cptr = cptr[ -1 ] = _T('\0'); /* remove extra blank, add double null */

        /*
         * Build the environment block by concatenating the environment
         * strings with nulls between and two null bytes at the end
         */

        cptr = *envblk;

        if (envp != NULL) {
                /*
                 * Copy the "cwd" strings to the new environment.
                 */
                memcpy(cptr, &_tenvptr[cwd_start], (cwd_end - cwd_start) * sizeof(_TSCHAR));
                cptr += cwd_end - cwd_start;

                /*
                 * Copy the environment strings from "envp".
                 */
                vp = envp;
                while( *vp ) {
                        _ERRCHECK(_tcscpy_s(cptr, env_len - (cptr - *envblk), *vp));
                        cptr += 1 + (int)_tcslen(*vp++);
                }

                if (!defined) {
                        /*
                         * Copy SystemRoot to the new environment.
                         */
                        _ERRCHECK(_tcscpy_s(cptr, envsize, envpfx));
                        _ERRCHECK(_tcscat_s(cptr, envsize, _T("=")));
                        if (envbuf != NULL)
                        {
                            _ERRCHECK(_tcscat_s(cptr, envsize, envbuf));
                        }
                        cptr += envsize;
                }
        }

        if (cptr != NULL) {
                if (cptr == *envblk) {
                        /*
                         * Empty environment block ... this requires two
                         * nulls.
                         */
                        *cptr++ = _T('\0');
                }
                /*
                 * Extra null terminates the segment
                 */
                *cptr = _T('\0');
        }

        goto done;

error:
        _free_crt(*argblk);
        *argblk = NULL;
        *envblk = NULL;

done:

#ifdef WPRFLAG
        if (_wenvptr)
                _free_crt(_wenvptr);
        _wenvptr = NULL;
#else  /* WPRFLAG */
        if (_aenvptr)
                _free_crt(_aenvptr);
        _aenvptr = NULL;
#endif  /* WPRFLAG */
        if (envbuf)
                _free_crt(envbuf);

        return retval;
}
Exemple #3
0
FILE * __cdecl _tpopen (
        const _TSCHAR *cmdstring,
        const _TSCHAR *type
        )
{

        int phdls[2];             /* I/O handles for pipe */
        int ph_open[2];           /* flags, set if correspond phdls is open */
        int i1;                   /* index into phdls[] */
        int i2;                   /* index into phdls[] */

        int tm = 0;               /* flag indicating text or binary mode */

        int stdhdl;               /* either STDIN or STDOUT */

        HANDLE newhnd;            /* ...in calls to DuplicateHandle API */

        FILE *pstream = NULL;     /* stream to be associated with pipe */

        HANDLE prochnd;           /* handle for current process */

        _TSCHAR *cmdexe;          /* pathname for the command processor */
        _TSCHAR *envbuf = NULL;   /* buffer for the env variable */
        intptr_t childhnd;        /* handle for child process (cmd.exe) */

        IDpair *locidpair;        /* pointer to IDpair table entry */
        _TSCHAR *buf = NULL, *pfin, *env;
        _TSCHAR *CommandLine;
        size_t CommandLineSize = 0;
        _TSCHAR _type[3] = {0, 0, 0};

        /* Info for spawning the child. */
        STARTUPINFO StartupInfo;  /* Info for spawning a child */
        BOOL childstatus = 0;
        PROCESS_INFORMATION ProcessInfo; /* child process information */

        errno_t save_errno;

        int fh_lock_held = 0;
        int popen_lock_held = 0;

        /* first check for errors in the arguments
         */
        _VALIDATE_RETURN((cmdstring != NULL), EINVAL,NULL);
        _VALIDATE_RETURN((type != NULL), EINVAL,NULL);

        while (*type == _T(' '))
        {
            type++;
        }
        _VALIDATE_RETURN(((*type == _T('w')) || (*type == _T('r'))), EINVAL,NULL);
        _type[0] = *type;
        ++type;
        while (*type == _T(' '))
        {
            ++type;
        }
        _VALIDATE_RETURN(((*type == 0) || (*type == _T('t')) || (*type == _T('b'))), EINVAL, NULL);
        _type[1] = *type;

        /* do the _pipe(). note that neither of the resulting handles will
         * be inheritable.
         */

        if ( _type[1] == _T('t') )
                tm = _O_TEXT;
        else if ( _type[1] == _T('b') )
                tm = _O_BINARY;

        tm |= _O_NOINHERIT;

        if ( _pipe( phdls, PSIZE, tm ) == -1 )
                goto error1;

        /* test _type[0] and set stdhdl, i1 and i2 accordingly.
         */
        if ( _type[0] == _T('w') ) {
                stdhdl = STDIN;
                i1 = 0;
                i2 = 1;
        }
        else {
                stdhdl = STDOUT;
                i1 = 1;
                i2 = 0;
        }

        /* ASSERT LOCK FOR IDPAIRS HERE!!!!
         */
        if ( !_mtinitlocknum( _POPEN_LOCK )) {
            _close( phdls[0] );
            _close( phdls[1] );
            return NULL;
        }
        _mlock( _POPEN_LOCK );
        __try
        {

        /* set flags to indicate pipe handles are open. note, these are only
         * used for error recovery.
         */
        ph_open[ 0 ] = ph_open[ 1 ] = 1;


        /* get the process handle, it will be needed in some API calls
         */
        prochnd = GetCurrentProcess();



        if ( !DuplicateHandle( prochnd,
                               (HANDLE)_osfhnd( phdls[i1] ),
                               prochnd,
                               &newhnd,
                               0L,
                               TRUE,                    /* inheritable */
                               DUPLICATE_SAME_ACCESS )
        ) {
                goto error2;
        }
        (void)_close( phdls[i1] );
        ph_open[ i1 ] = 0;

        /* associate a stream with phdls[i2]. note that if there are no
         * errors, pstream is the return value to the caller.
         */
        if ( (pstream = _tfdopen( phdls[i2], _type )) == NULL )
                goto error2;

        /* next, set locidpair to a free entry in the idpairs table.
         */
        if ( (locidpair = idtab( NULL )) == NULL )
                goto error3;


        /* Find what to use. command.com or cmd.exe */
        if ( (_ERRCHECK_EINVAL(_tdupenv_s_crt(&envbuf, NULL, _T("COMSPEC"))) != 0) || (envbuf == NULL) )
        {
            unsigned int osver = 0;
            _get_osver(&osver);
            cmdexe = ( osver & 0x8000 ) ? _T("command.com") : _T("cmd.exe");
        }
        else
        {
            cmdexe = envbuf;
        }

        /*
         * Initialise the variable for passing to CreateProcess
         */

        memset(&StartupInfo, 0, sizeof(StartupInfo));
        StartupInfo.cb = sizeof(StartupInfo);

        /* Used by os for duplicating the Handles. */

        StartupInfo.dwFlags = STARTF_USESTDHANDLES;
        StartupInfo.hStdInput = stdhdl == STDIN ? (HANDLE) newhnd
                                                : (HANDLE) _osfhnd(0);
        StartupInfo.hStdOutput = stdhdl == STDOUT ? (HANDLE) newhnd
                                                  : (HANDLE) _osfhnd(1);
        StartupInfo.hStdError = (HANDLE) _osfhnd(2);


        CommandLineSize = _tcslen(cmdexe) + _tcslen(_T(" /c ")) + (_tcslen(cmdstring)) +1;
        if ((CommandLine = _calloc_crt( CommandLineSize, sizeof(_TSCHAR))) == NULL)
            goto error3;
        _ERRCHECK(_tcscpy_s(CommandLine, CommandLineSize, cmdexe));
        _ERRCHECK(_tcscat_s(CommandLine, CommandLineSize, _T(" /c ")));
        _ERRCHECK(_tcscat_s(CommandLine, CommandLineSize, cmdstring));

        /* Check if cmdexe can be accessed. If yes CreateProcess else try
         * searching path.
         */
        save_errno = errno;
        if (_taccess_s(cmdexe, 0) == 0) {
            childstatus = CreateProcess( (LPTSTR) cmdexe,
                                         (LPTSTR) CommandLine,
                                         NULL,
                                         NULL,
                                         TRUE,
                                         0,
                                         NULL,
                                         NULL,
                                         &StartupInfo,
                                         &ProcessInfo
                                         );
        }
        else {
            TCHAR* envPath = NULL;
            size_t envPathSize = 0;
            if ((buf = _calloc_crt(_MAX_PATH, sizeof(_TSCHAR))) == NULL)
            {
                _free_crt(buf);
                _free_crt(CommandLine);
                _free_crt(envbuf);
                cmdexe = NULL;
                errno = save_errno;
                goto error3;
            }
            if (_ERRCHECK_EINVAL(_tdupenv_s_crt(&envPath, NULL, _T("PATH"))) != 0)
            {
                _free_crt(envPath);
                _free_crt(buf);
                _free_crt(CommandLine);
                _free_crt(envbuf);
                cmdexe = NULL;
                errno = save_errno;
                goto error3;
            }
            env = envPath;

#ifdef WPRFLAG
            while ( (env = _wgetpath(env, buf, _MAX_PATH -1)) && (*buf) ) {
#else  /* WPRFLAG */
            while ( (env = _getpath(env, buf, _MAX_PATH -1)) && (*buf) ) {
#endif  /* WPRFLAG */
                pfin = buf + _tcslen(buf) -1;

#ifdef _MBCS
                if (*pfin == SLASHCHAR) {
                    if (pfin != _mbsrchr(buf, SLASHCHAR))
                        _ERRCHECK(strcat_s(buf, _MAX_PATH, SLASH));
                }
                else if (*pfin != XSLASHCHAR)
                    _ERRCHECK(strcat_s(buf, _MAX_PATH, SLASH));

#else  /* _MBCS */
                if (*pfin != SLASHCHAR && *pfin != XSLASHCHAR)
                    _ERRCHECK(_tcscat_s(buf, _MAX_PATH, SLASH));
#endif  /* _MBCS */
                /* check that the final path will be of legal size. if so,
                 * build it. otherwise, return to the caller (return value
                 * and errno rename set from initial call to _spawnve()).
                 */
                if ( (_tcslen(buf) + _tcslen(cmdexe)) < _MAX_PATH )
                    _ERRCHECK(_tcscat_s(buf, _MAX_PATH, cmdexe));
                else
                    break;

                /* Check if buf can be accessed. If yes CreateProcess else try
                 * again.
                 */
                if (_taccess_s(buf, 0) == 0) {
                    childstatus = CreateProcess( (LPTSTR) buf,
                                                 CommandLine,
                                                 NULL,
                                                 NULL,
                                                 TRUE,
                                                 0,
                                                 NULL,
                                                 NULL,
                                                 &StartupInfo,
                                                 &ProcessInfo
                                                 );
                    break;
                }
            }
            _free_crt(envPath);
            _free_crt(buf);
        }
        _free_crt(CommandLine);
        _free_crt(envbuf);
        cmdexe = NULL;
        CloseHandle((HANDLE)newhnd);
        CloseHandle((HANDLE)ProcessInfo.hThread);
                errno = save_errno;

        /* check if the CreateProcess was sucessful.
         */
        if ( childstatus)
            childhnd = (intptr_t)ProcessInfo.hProcess;
        else
            goto error4;
        locidpair->prochnd = childhnd;
        locidpair->stream = pstream;

        /* success, return the stream to the caller
         */
        goto done;

        /**
         * error handling code. all detected errors end up here, entering
         * via a goto one of the labels. note that the logic is currently
         * a straight fall-thru scheme (e.g., if entered at error4, the
         * code for error4, error3,...,error1 is all executed).
         **********************************************************************/

error4:         /* make sure locidpair is reusable
                 */
                locidpair->stream = NULL;

error3:         /* close pstream (also, clear ph_open[i2] since the stream
                 * close will also close the pipe handle)
                 */
                (void)fclose( pstream );
                ph_open[ i2 ] = 0;
                pstream = NULL;

error2:         /* close handles on pipe (if they are still open)
                 */

                if ( ph_open[i1] )
                        _close( phdls[i1] );
                if ( ph_open[i2] )
                        _close( phdls[i2] );
done:

        ;}
        __finally {
            _munlock(_POPEN_LOCK);
        }


error1:
        return pstream;
}

#ifndef _UNICODE

/***
*int _pclose(pstream) - wait on a child command and close the stream on the
*   associated pipe
*
*Purpose:
*       Closes pstream then waits on the associated child command. The
*       argument, pstream, must be the return value from a previous call to
*       _popen. _pclose first looks up the process handle of child command
*       started by that _popen and does a cwait on it. Then, it closes pstream
*       and returns the exit status of the child command to the caller.
*
*Entry:
*       FILE *pstream - file stream returned by a previous call to _popen
*
*Exit:
*       If successful, _pclose returns the exit status of the child command.
*       The format of the return value is that same as for cwait, except that
*       the low order and high order bytes are swapped.
*
*       If an error occurs, -1 is returned.
*
*Exceptions:
*
*******************************************************************************/

int __cdecl _pclose (
        FILE *pstream
        )
{
        IDpair *locidpair;        /* pointer to entry in idpairs table */
        int termstat;             /* termination status word */
        int retval = -1;          /* return value (to caller) */
        errno_t save_errno;

        _VALIDATE_RETURN((pstream != NULL), EINVAL, -1);

        if (!_mtinitlocknum(_POPEN_LOCK))
            return -1;
        _mlock(_POPEN_LOCK);
        __try {

        if ((locidpair = idtab(pstream)) == NULL)
        {
                /* invalid pstream, exit with retval == -1
                 */
                errno = EBADF;
                goto done;
        }

        /* close pstream
         */
        (void)fclose(pstream);

        /* wait on the child (copy of the command processor) and all of its
         * children.
         */
        save_errno = errno;
        errno = 0;
        if ( (_cwait(&termstat, locidpair->prochnd, _WAIT_GRANDCHILD) != -1) ||
             (errno == EINTR) )
                retval = termstat;
        errno = save_errno;

        /* Mark the IDpairtable entry as free (note: prochnd was closed by the
         * preceding call to _cwait).
         */
        locidpair->stream = NULL;
        locidpair->prochnd = 0;

        /* only return path!
         */
        done:

        ; }
        __finally {
            _munlock(_POPEN_LOCK);
        }
        return(retval);
}