Accessing Open File Handles in a Child ProcessID: Q104652
|
To access the open file handles of a parent process under MS-DOS/Windows, it is not necessary to pass the handles of files opened in a parent process via the command line to a spawned child process. Those file handles are automatically inherited by the child process.
The following information describes how the handles of files opened
within a parent process are inherited by the child process, and how
they can be reused in the child process.
The child process will automatically inherit the file handles (type
int) of all files opened in the parent process with no regard to the
_fileinfo variable. This happens during the program startup, where a
new PSP is set up for the child process.
A common misconception is that _fileinfo causes file handles to be
passed to the child process. However, the variable _fileinfo only
causes the mode flags to be passed to the child and does not affect the
passing of the file handles themselves.
Setting the variable _fileinfo to a nonzero value causes the parent
program to copy the mode flags for all open files into the environment
variable "_C_FILE_INFO" (versions 5.1 and earlier of the Microsoft C
compiler use ";C_FILE_INFO"). Each mode flag is stored in a coded form
in this environment variable.
If the child process was written with Microsoft C, the startup code
will check for a set _C_FILE_INFO environment string and decode it.
The result is stored in the public array _osfile[]. After _C_FILE_INFO
has been read, decoded, and transferred into _osfile[], it is deleted
from the environment, thus making it invisible to the "main" code of
the child. The values stored in _osfile[] can subsequently be used to
reopen the inherited files for buffered I/O using _fdopen().
If the spawned process is a non-Microsoft C application, there is no
startup code; thus, the environment string is never read, and remains
visible in the MS-DOS environment. The environment string may appear
to be incorrect because the mode flags encoded in _C_FILE_INFO will
cause the contents of that string to look "damaged." However, this is
OK because the contents are encoded.
To access files inside the child process you can do one of the
following:
/* Compile Options Needed: None
*/
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
void main( void )
{
unsigned int iFileHandle1,
iFileHandle2;
FILE* FPtr1,
* FPtr2;
static char String [ 80 ];
static char CmdName[ ] = "CHILD.EXE";
static char * ArgV [ 2 ] = { "CHILD",
NULL
};
// Open temporary files - handles will be stored in PSP.
system("cls");
printf("Parent: opening files \"TEST1.DAT\" and
\"TEST2.DAT\"\n");
FPtr1 = fopen( "test1.dat", "w+"); //, _SH_DENYNO );
FPtr2 = fopen( "test2.dat", "wb+"); //, _SH_DENYNO );
// Set the _fileinfo variable that is declared in STDLIB.H to
// force the MS-DOS environment variable _C_FILE_INFO to be
// passed to the spawned process.
// _C_FILE_INFO contains a char string with encoded
// information about the modes of the open files passed to the
// child process. The C startup code of the child will read
// and decode _C_FILE_INFO, store the appropriate info into a
// global array named _osfile[], and then delete the
// _C_FILE_INFO entry from the child's environment.
_fileinfo = 1;
// Spawn a child process that will write a string to the file.
printf("Parent: transferring control to child process..\n\n");
spawnv( P_WAIT, CmdName, ArgV );
// Rewind the files to read from the start.
rewind( FPtr1 );
rewind( FPtr2 );
// Output the strings written to the files by the child.
printf("Parent: scanning the strings from the files...\n");
fscanf(FPtr1, "%[^\n]", String );
printf("Parent: contents of \"TEST1.DAT\" are: %s\n", String);
fscanf(FPtr2, "%[^\n]", String );
printf("Parent: contents of \"TEST2.DAT\" are: %s\n", String);
// Close the files,
fclose( FPtr1 );
fclose( FPtr2 );
// and delete them.
remove( "test1.dat" );
remove( "test2.dat" );
}
/* Compile Options Needed: none
*/
#include <stdio.h>
#include <string.h>
#define FOPEN 0x01 /* File handle open */
#define FRDONLY 0x10 /* File handle associated with read-only file*/
#define FAPPEND 0x20 /* File handle opened O_APPEND */
#define FTEXT 0x80 /* File handle is in text mode */
extern char near _osfile[];
void main( void )
{
unsigned int iFileHandle,
iCount,
iScanRetVal;
static char szFileString[] = "This is file #";
static char szMode[5];
static char* pszMode = szMode;
FILE* ChildFPtr[ 255 ];
// Use the low-level I/O file handles of the inherited files
// and check their mode flag as stored in _osfile[]
// to ensure reopening with the correct mode flag set.
// Start with file #5, because the first 5 files (0-4)
// are used for the standard I/O (stdin, stdout, stderr,
// stdaux, and stdprn).
for( iCount = 5 ; _osfile[ iCount ] != 0;
iCount++, pszMode = &szMode[0] ) {
// Set current file handle to iCount.
// All files opened in the parent process will be open
// in the child too, regardless of passing _C_FILE_INFO
// or not.
iFileHandle = iCount;
// _C_FILE_INFO will cause _osfile[] to contain the
// correct open modes for the inherited files, thus
// allowing the user to reopen them for buffered I/O
// by calling _fdopen() with the correct mode flag set.
// To do so we must construct a mode parameter according
// to _osfile[]:
if(_osfile[ iCount ] & FRDONLY )
pszMode = ( char * ) strcpy( szMode, "r");
else
pszMode = ( char * ) strcpy( szMode, "w+");
if( _osfile[ iCount ] & FAPPEND )
pszMode = ( char * ) strcat( szMode, "a");
if( !(_osfile[ iCount ] & FTEXT) )
pszMode = ( char * ) strcat( szMode, "b");
// Now open the files for buffered I/O and
// don't forget to reset pszMode for next loop.
printf("Child: _osfile[ %i ] = %s %s %s\n",
iCount,
(_osfile[ iCount ] & FRDONLY) ? "_O_RDONLY" : "_O_RDWR",
(_osfile[ iCount ] & FAPPEND) ? "| _O_APPEND" : "",
(_osfile[ iCount ] & FTEXT) ? "| _O_TEXT" : "| _O_BINARY"
);
printf("Child: Now opening file using _fdopen( %d, %s )\n",
iCount, szMode );
ChildFPtr[ iCount ] = _fdopen( iFileHandle, szMode );
strcpy( szMode, "\0");
// Write some strings to the file.
printf("Child: Now writing the string \"%s%d\" to file #%d\n",
szFileString, iCount, iCount);
if( fprintf( ChildFPtr[ iCount ], "%s%d\n",
szFileString, iCount) < 0 ) {
printf("Child: Error writing to file %d - exiting!\n",
iCount );
return;
}
// Make sure nothing remains in the buffers,
_flushall();
// and check the file length.
printf("Child: Length of file is %ld bytes\n\n", _filelength(
iFileHandle ));
}
}
Additional query words: kbinf 1.00 1.50 6.00 6.00a 6.00ax 7.00 modeflag
Keywords : kb16bitonly
Version :
Platform :
Issue type :
Last Reviewed: August 2, 1999