Use special environment variables to transmit the cwd of the various

drives to child processes (based on a patch by Andreas Mohr).
This commit is contained in:
Alexandre Julliard 2000-10-03 04:19:16 +00:00
parent 8b7f04d616
commit aef9a36059
3 changed files with 59 additions and 7 deletions

View file

@ -15,6 +15,7 @@
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -146,6 +147,7 @@ int DRIVE_Init(void)
{ {
int i, len, count = 0; int i, len, count = 0;
char name[] = "Drive A"; char name[] = "Drive A";
char drive_env[] = "=A:";
char path[MAX_PATHNAME_LEN]; char path[MAX_PATHNAME_LEN];
char buffer[80]; char buffer[80];
struct stat drive_stat_buffer; struct stat drive_stat_buffer;
@ -257,6 +259,14 @@ int DRIVE_Init(void)
} }
} }
/* get current working directory info for all drives */
for (i = 0; i < MAX_DOS_DRIVES; i++, drive_env[1]++)
{
if (!GetEnvironmentVariableA(drive_env, path, sizeof(path))) continue;
/* sanity check */
if (toupper(path[0]) != drive_env[1] || path[1] != ':') continue;
DRIVE_Chdir( i, path + 2 );
}
return 1; return 1;
} }
@ -920,6 +930,34 @@ static UINT DRIVE_GetCurrentDirectory( UINT buflen, LPSTR buf )
return ret; return ret;
} }
/***********************************************************************
* DRIVE_BuildEnv
*
* Build the environment array containing the drives current directories.
* Resulting pointer must be freed with HeapFree.
*/
char *DRIVE_BuildEnv(void)
{
int i, length = 0;
const char *cwd[MAX_DOS_DRIVES];
char *env, *p;
for (i = 0; i < MAX_DOS_DRIVES; i++)
{
if ((cwd[i] = DRIVE_GetDosCwd(i)) && cwd[i][0]) length += strlen(cwd[i]) + 8;
}
if (!(env = HeapAlloc( GetProcessHeap(), 0, length+1 ))) return NULL;
for (i = 0, p = env; i < MAX_DOS_DRIVES; i++)
{
if (cwd[i] && cwd[i][0])
p += sprintf( p, "=%c:=%c:\\%s", 'A'+i, 'A'+i, cwd[i] ) + 1;
}
*p = 0;
return env;
}
/*********************************************************************** /***********************************************************************
* GetDiskFreeSpace16 (KERNEL.422) * GetDiskFreeSpace16 (KERNEL.422)
*/ */

View file

@ -50,5 +50,6 @@ extern int DRIVE_SetLogicalMapping ( int existing_drive, int new_drive );
extern int DRIVE_OpenDevice( int drive, int flags ); extern int DRIVE_OpenDevice( int drive, int flags );
extern int DRIVE_RawRead(BYTE drive, DWORD begin, DWORD length, BYTE *dataptr, BOOL fake_success ); extern int DRIVE_RawRead(BYTE drive, DWORD begin, DWORD length, BYTE *dataptr, BOOL fake_success );
extern int DRIVE_RawWrite(BYTE drive, DWORD begin, DWORD length, BYTE *dataptr, BOOL fake_success ); extern int DRIVE_RawWrite(BYTE drive, DWORD begin, DWORD length, BYTE *dataptr, BOOL fake_success );
extern char *DRIVE_BuildEnv(void);
#endif /* __WINE_DRIVE_H */ #endif /* __WINE_DRIVE_H */

View file

@ -15,6 +15,7 @@
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "wine/exception.h" #include "wine/exception.h"
#include "process.h" #include "process.h"
#include "drive.h"
#include "main.h" #include "main.h"
#include "module.h" #include "module.h"
#include "neexe.h" #include "neexe.h"
@ -577,20 +578,24 @@ static char **build_argv( char *cmdline, int reserved )
* *
* Build the environment of a new child process. * Build the environment of a new child process.
*/ */
static char **build_envp( const char *env ) static char **build_envp( const char *env, const char *extra_env )
{ {
const char *p; const char *p;
char **envp; char **envp;
int count; int count = 0;
for (p = env, count = 0; *p; count++) p += strlen(p) + 1; if (extra_env) for (p = extra_env; *p; count++) p += strlen(p) + 1;
for (p = env; *p; count++) p += strlen(p) + 1;
count += 3; count += 3;
if ((envp = malloc( count * sizeof(*envp) ))) if ((envp = malloc( count * sizeof(*envp) )))
{ {
extern char **environ; extern char **environ;
char **envptr = envp; char **envptr = envp;
char **unixptr = environ; char **unixptr = environ;
/* first put PATH, HOME and WINEPREFIX from the unix env */ /* first the extra strings */
if (extra_env) for (p = extra_env; *p; p += strlen(p) + 1) *envptr++ = (char *)p;
/* then put PATH, HOME and WINEPREFIX from the unix env */
for (unixptr = environ; unixptr && *unixptr; unixptr++) for (unixptr = environ; unixptr && *unixptr; unixptr++)
if (!memcmp( *unixptr, "PATH=", 5 ) || if (!memcmp( *unixptr, "PATH=", 5 ) ||
!memcmp( *unixptr, "HOME=", 5 ) || !memcmp( *unixptr, "HOME=", 5 ) ||
@ -665,6 +670,13 @@ static int fork_and_exec( const char *filename, char *cmdline,
{ {
int fd[2]; int fd[2];
int pid, err; int pid, err;
char *extra_env = NULL;
if (!env)
{
env = GetEnvironmentStringsA();
extra_env = DRIVE_BuildEnv();
}
if (pipe(fd) == -1) if (pipe(fd) == -1)
{ {
@ -675,10 +687,10 @@ static int fork_and_exec( const char *filename, char *cmdline,
if (!(pid = fork())) /* child */ if (!(pid = fork())) /* child */
{ {
char **argv = build_argv( cmdline, filename ? 0 : 2 ); char **argv = build_argv( cmdline, filename ? 0 : 2 );
char **envp = build_envp( env ); char **envp = build_envp( env, extra_env );
close( fd[0] ); close( fd[0] );
if (newdir) chdir(newdir); if (newdir) chdir(newdir);
if (argv && envp) if (argv && envp)
{ {
@ -701,6 +713,7 @@ static int fork_and_exec( const char *filename, char *cmdline,
} }
if (pid == -1) FILE_SetDosError(); if (pid == -1) FILE_SetDosError();
close( fd[0] ); close( fd[0] );
if (extra_env) HeapFree( GetProcessHeap(), 0, extra_env );
return pid; return pid;
} }
@ -784,7 +797,7 @@ BOOL PROCESS_Create( HFILE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env,
/* fork and execute */ /* fork and execute */
pid = fork_and_exec( unixfilename, cmd_line, env ? env : GetEnvironmentStringsA(), unixdir ); pid = fork_and_exec( unixfilename, cmd_line, env, unixdir );
SERVER_START_REQ SERVER_START_REQ
{ {