📄 popen.c
字号:
);
}
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);
}
#endif /* _UNICODE */
/***
* static IDpair * idtab(FILE *pstream) - find an idpairs table entry
*
*Purpose:
* Find an entry in the idpairs table. This function finds the entry the
* idpairs table entry corresponding to pstream. In the case where pstream
* is NULL, the entry being searched for is any free entry. In this case,
* idtab will create the idpairs table if it doesn't exist, or expand it (by
* exactly one entry) if there are no free entries.
*
* [MTHREAD NOTE: This routine assumes that the caller has acquired the
* idpairs table lock.]
*
*Entry:
* FILE *pstream - stream corresponding to table entry to be found (if NULL
* then find any free table entry)
*
*Exit:
* if successful, returns a pointer to the idpairs table entry. otherwise,
* returns NULL.
*
*Exceptions:
*
*******************************************************************************/
static IDpair * __cdecl idtab (
FILE *pstream
)
{
IDpair * pairptr; /* ptr to entry */
IDpair * newptr; /* ptr to newly malloc'd memory */
/* search the table. if table is empty, appropriate action should
* fall out automatically.
*/
for ( pairptr = __idpairs ; pairptr < (__idpairs+__idtabsiz) ; pairptr++ )
if ( pairptr->stream == pstream )
break;
/* if we found an entry, return it.
*/
if ( pairptr < (__idpairs + __idtabsiz) )
return(pairptr);
/* did not find an entry in the table. if pstream was NULL, then try
* creating/expanding the table. otherwise, return NULL. note that
* when the table is created or expanded, exactly one new entry is
* produced. this must not be changed unless code is added to mark
* the extra entries as being free (i.e., set their stream fields to
* to NULL).
*/
if ( (pstream != NULL) ||
((__idtabsiz + 1) < __idtabsiz) ||
((__idtabsiz + 1) >= (SIZE_MAX / sizeof(IDpair))) ||
((newptr = (IDpair *)_recalloc_crt((void *)__idpairs, (__idtabsiz + 1),sizeof(IDpair))) == NULL))
/* either pstream was non-NULL or the attempt to create/expand
* the table failed. in either case, return a NULL to indicate
* failure.
*/
return( NULL );
__idpairs = newptr; /* new table ptr */
pairptr = newptr + __idtabsiz; /* first new entry */
__idtabsiz++; /* new table size */
return( pairptr );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -