- Implement console I/O

- Support temporary files, add tmpfile, rmtmp
- spawn* functions: fix args, add cwait, searchenv
This commit is contained in:
Jon Griffiths 2000-12-13 01:58:39 +00:00 committed by Alexandre Julliard
parent 5c312198f6
commit 61e48c7af1
9 changed files with 483 additions and 53 deletions

View File

@ -9,6 +9,7 @@ LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o
C_SRCS = \
console.c \
crtdll_main.c \
dir.c \
exit.c \

220
dlls/crtdll/console.c Normal file
View File

@ -0,0 +1,220 @@
/*
* CRTDLL console functions
*
* Copyright 2000 Jon Griffiths
*
* NOTES
* Only a one byte ungetch buffer is implemented, as per MS docs.
* Output is not redirectable using these functions, as per MS docs.
*
* FIXME:
* There are several problems with the console input mechanism as
* currently implemented in Wine. When these are ironed out the
* getch() function will work correctly (gets() is currently fine).
* The problem is that opening CONIN$ does not work, and
* reading from STD_INPUT_HANDLE is line buffered.
*/
#include "crtdll.h"
#include "wincon.h"
DEFAULT_DEBUG_CHANNEL(crtdll);
static HANDLE __CRTDLL_console_in = INVALID_HANDLE_VALUE;
static HANDLE __CRTDLL_console_out = INVALID_HANDLE_VALUE;
static int __CRTDLL_console_buffer = EOF;
/* INTERNAL: Initialise console handles */
VOID __CRTDLL_init_console(VOID)
{
TRACE(":Opening console handles\n");
__CRTDLL_console_in = GetStdHandle(STD_INPUT_HANDLE);
/* FIXME: Should be initialised with:
* CreateFileA("CONIN$", GENERIC_READ, FILE_SHARE_READ,
* NULL, OPEN_EXISTING, 0, (HANDLE)NULL);
*/
__CRTDLL_console_out = CreateFileA("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, (HANDLE)NULL);
if ((__CRTDLL_console_in == INVALID_HANDLE_VALUE) ||
(__CRTDLL_console_out == INVALID_HANDLE_VALUE))
WARN(":Console handle Initialisation FAILED!\n");
}
/* INTERNAL: Free console handles */
void __CRTDLL_free_console(void)
{
TRACE(":Closing console handles\n");
CloseHandle(__CRTDLL_console_in);
CloseHandle(__CRTDLL_console_out);
}
/*********************************************************************
* _cgets (CRTDLL.050)
*
* Get a string from CONIN$.
*/
LPSTR __cdecl CRTDLL__cgets(LPSTR str)
{
char *buf = str + 2;
int c;
str[1] = 0; /* Length */
/* FIXME: No editing of string supported */
do
{
if (str[1] >= str[0] || (str[1]++, c = CRTDLL__getche()) == EOF || c == '\n')
{
*buf = '\0';
return str + 2;
}
*buf++ = c & 0xff;
} while(1);
}
/*********************************************************************
* _cputs (CRTDLL.065)
*
* Write a string to CONOUT$.
*/
INT __cdecl CRTDLL__cputs(LPCSTR str)
{
DWORD count;
if (WriteConsoleA(__CRTDLL_console_out, str, strlen(str), &count, NULL)
&& count == 1)
return 0;
return EOF;
}
/*********************************************************************
* _getch (CRTDLL.118)
*
* Get a character from CONIN$.
*/
INT __cdecl CRTDLL__getch(VOID)
{
if (__CRTDLL_console_buffer != EOF)
{
INT retVal = __CRTDLL_console_buffer;
__CRTDLL_console_buffer = EOF;
return retVal;
}
else
{
INPUT_RECORD ir;
DWORD count;
DWORD mode = 0;
GetConsoleMode(__CRTDLL_console_in, &mode);
if(mode) SetConsoleMode(__CRTDLL_console_in, 0);
do {
if (ReadConsoleInputA(__CRTDLL_console_in, &ir, 1, &count))
{
/* Only interested in ASCII chars */
if (ir.EventType == KEY_EVENT &&
ir.Event.KeyEvent.bKeyDown &&
ir.Event.KeyEvent.uChar.AsciiChar)
{
if(mode) SetConsoleMode(__CRTDLL_console_in, mode);
return ir.Event.KeyEvent.uChar.AsciiChar;
}
}
else
break;
} while(1);
if (mode) SetConsoleMode(__CRTDLL_console_in, mode);
}
return EOF;
}
/*********************************************************************
* _getche (CRTDLL.119)
*
* Get a character from CONIN$ and echo it to CONOUT$.
*/
INT __cdecl CRTDLL__getche(VOID)
{
INT res = CRTDLL__getch();
if (res != EOF && CRTDLL__putch(res) != EOF)
return res;
return EOF;
}
/*********************************************************************
* _kbhit (CRTDLL.169)
*
* Check if a character is waiting in CONIN$.
*/
INT __cdecl CRTDLL__kbhit(VOID)
{
if (__CRTDLL_console_buffer != EOF)
return 1;
else
{
/* FIXME: There has to be a faster way than this in Win32.. */
INPUT_RECORD *ir;
DWORD count = 0;
int retVal = 0, i;
GetNumberOfConsoleInputEvents(__CRTDLL_console_in, &count);
if (!count)
return 0;
if (!(ir = CRTDLL_malloc(count * sizeof(INPUT_RECORD))))
return 0;
if (!PeekConsoleInputA(__CRTDLL_console_in, ir, count, &count))
return 0;
for(i = 0; i < count - 1; i++)
{
if (ir[i].EventType == KEY_EVENT &&
ir[i].Event.KeyEvent.bKeyDown &&
ir[i].Event.KeyEvent.uChar.AsciiChar)
{
retVal = 1;
break;
}
}
CRTDLL_free(ir);
return retVal;
}
}
/*********************************************************************
* _putch (CRTDLL.250)
*
* Write a character to CONOUT$.
*/
INT __cdecl CRTDLL__putch(INT c)
{
DWORD count;
if (WriteConsoleA(__CRTDLL_console_out, &c, 1, &count, NULL) &&
count == 1)
return c;
return EOF;
}
/*********************************************************************
* _ungetch (CRTDLL.311)
*
* Un-get a character from CONIN$.
*/
INT __cdecl CRTDLL__ungetch(INT c)
{
if (c == EOF || __CRTDLL_console_buffer != EOF)
return EOF;
return __CRTDLL_console_buffer = c;
}

View File

@ -55,6 +55,8 @@
#define _O_TEXT 0x4000
#define _O_BINARY 0x8000
#define _O_TEMPORARY 0x0040 /* Will be closed and deleted on exit */
/* _access() bit flags FIXME: incomplete */
#define W_OK 2
@ -246,7 +248,7 @@ typedef INT (__cdecl *comp_func)(LPCVOID, LPCVOID );
/* CRTDLL functions */
/* CRTDLL_dir.c */
/* dir.c */
INT __cdecl CRTDLL__chdir( LPCSTR newdir );
BOOL __cdecl CRTDLL__chdrive( INT newdrive );
INT __cdecl CRTDLL__findclose( DWORD hand );
@ -259,7 +261,7 @@ INT __cdecl CRTDLL__getdrive( VOID );
INT __cdecl CRTDLL__mkdir( LPCSTR newdir );
INT __cdecl CRTDLL__rmdir( LPSTR dir );
/* CRTDLL_exit.c */
/* exit.c */
INT __cdecl CRTDLL__abnormal_termination( VOID );
VOID __cdecl CRTDLL__amsg_exit( INT err );
VOID __cdecl CRTDLL__assert( LPVOID str, LPVOID file, UINT line );
@ -271,13 +273,14 @@ VOID __cdecl CRTDLL_abort( VOID );
INT __cdecl CRTDLL_atexit( atexit_function x );
atexit_function __cdecl CRTDLL__onexit( atexit_function func);
/* CRTDLL_file.c */
/* file.c */
CRTDLL_FILE* __cdecl CRTDLL__iob( VOID );
CRTDLL_FILE* __cdecl CRTDLL__fsopen( LPCSTR path, LPCSTR mode, INT share );
CRTDLL_FILE* __cdecl CRTDLL__fdopen( INT fd, LPCSTR mode );
LPSTR __cdecl CRTDLL__mktemp( LPSTR pattern );
CRTDLL_FILE* __cdecl CRTDLL_fopen( LPCSTR path, LPCSTR mode );
CRTDLL_FILE* __cdecl CRTDLL_freopen( LPCSTR path,LPCSTR mode,CRTDLL_FILE* f );
CRTDLL_FILE* __cdecl CRTDLL_tmpfile( void );
INT __cdecl CRTDLL__fgetchar( VOID );
DWORD __cdecl CRTDLL_fread( LPVOID ptr,INT size,INT nmemb,CRTDLL_FILE* file );
INT __cdecl CRTDLL_fscanf( CRTDLL_FILE* stream, LPSTR format, ... );
@ -300,6 +303,7 @@ INT __cdecl CRTDLL_vfprintf( CRTDLL_FILE* file, LPCSTR format,va_list args);
INT __cdecl CRTDLL_fprintf( CRTDLL_FILE* file, LPCSTR format, ... );
INT __cdecl CRTDLL__putw( INT val, CRTDLL_FILE* file );
INT __cdecl CRTDLL__read( INT fd, LPVOID buf, UINT count );
INT __cdecl CRTDLL__rmtmp( void );
UINT __cdecl CRTDLL__write( INT fd,LPCVOID buf,UINT count );
INT __cdecl CRTDLL__access( LPCSTR filename, INT mode );
INT __cdecl CRTDLL_fflush( CRTDLL_FILE* file );
@ -417,8 +421,9 @@ double __cdecl CRTDLL__y0( double x );
double __cdecl CRTDLL__y1( double x );
double __cdecl CRTDLL__yn( INT x, double y );
double __cdecl CRTDLL__nextafter( double x, double y );
VOID __cdecl CRTDLL__searchenv(LPCSTR file, LPCSTR env, LPSTR buff);
/* CRTDLL_mem.c */
/* memory.c */
LPVOID __cdecl CRTDLL_new( DWORD size );
VOID __cdecl CRTDLL_delete( LPVOID ptr );
new_handler_type __cdecl CRTDLL_set_new_handler( new_handler_type func );
@ -433,11 +438,15 @@ VOID __cdecl CRTDLL_free( LPVOID ptr );
LPVOID __cdecl CRTDLL_malloc( DWORD size );
LPVOID __cdecl CRTDLL_realloc( VOID *ptr, DWORD size );
/* CRTDLL_spawn.c */
HANDLE __cdecl CRTDLL__spawnve( INT flags, LPSTR name, LPSTR *argv, LPSTR *envv);
INT __cdecl CRTDLL_system( LPSTR x );
/* spawn.c */
HANDLE __cdecl CRTDLL__spawnv( INT flags, LPCSTR name, LPCSTR *argv);
HANDLE __cdecl CRTDLL__spawnve( INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv);
HANDLE __cdecl CRTDLL__spawnvp( INT flags, LPCSTR name, LPCSTR *argv);
HANDLE __cdecl CRTDLL__spawnvpe( INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv);
INT __cdecl CRTDLL_system( LPCSTR cmd );
INT __cdecl CRTDLL__cwait( PINT status, INT pid, INT action );
/* CRTDLL_str.c */
/* str.c */
LPSTR __cdecl CRTDLL__strdec( LPSTR str1, LPSTR str2 );
LPSTR __cdecl CRTDLL__strdup( LPCSTR ptr );
LPSTR __cdecl CRTDLL__strinc( LPSTR str );
@ -450,7 +459,7 @@ LONG __cdecl CRTDLL__strncnt( LPSTR str, LONG max );
LPSTR __cdecl CRTDLL__strspnp( LPSTR str1, LPSTR str2 );
VOID __cdecl CRTDLL__swab( LPSTR src, LPSTR dst, INT len );
/* CRTDLL_time.c */
/* time.c */
LPSTR __cdecl CRTDLL__strdate ( LPSTR date );
LPSTR __cdecl CRTDLL__strtime ( LPSTR date );
clock_t __cdecl CRTDLL_clock ( void );
@ -483,10 +492,22 @@ INT __cdecl CRTDLL_iswspace( WCHAR wc );
INT __cdecl CRTDLL_iswupper( WCHAR wc );
INT __cdecl CRTDLL_iswxdigit( WCHAR wc );
/* console.c */
LPSTR __cdecl CRTDLL__cgets( LPSTR str );
INT __cdecl CRTDLL__cputs( LPCSTR str );
INT __cdecl CRTDLL__getch( VOID );
INT __cdecl CRTDLL__getche( VOID );
INT __cdecl CRTDLL__kbhit( VOID );
INT __cdecl CRTDLL__putch( INT c );
INT __cdecl CRTDLL__ungetch( INT c );
/* INTERNAL: Shared internal functions */
void __CRTDLL__set_errno(ULONG err);
LPSTR __CRTDLL__strndup(LPSTR buf, INT size);
VOID __CRTDLL__init_io(VOID);
VOID __CRTDLL_init_console(VOID);
VOID __CRTDLL_free_console(VOID);
extern WORD CRTDLL_ctype [257];
extern WORD __CRTDLL_current_ctype[257];

View File

@ -57,7 +57,7 @@ debug_channels (crtdll)
@ cdecl _c_exit() CRTDLL__c_exit
@ cdecl _cabs(long) CRTDLL__cabs
@ cdecl _cexit() CRTDLL__cexit
@ stub _cgets
@ cdecl _cgets(str) CRTDLL__cgets
@ cdecl _chdir(str) CRTDLL__chdir
@ cdecl _chdrive(long) CRTDLL__chdrive
@ cdecl _chgsign(double) CRTDLL__chgsign
@ -72,11 +72,11 @@ debug_channels (crtdll)
@ cdecl _copysign(double double) CRTDLL__copysign
@ stub _cprintf
@ stub _cpumode_dll
@ stub _cputs
@ cdecl _cputs(str) CRTDLL__cputs
@ cdecl _creat(str long) CRTDLL__creat
@ stub _cscanf
@ extern _ctype CRTDLL_ctype
@ stub _cwait
@ cdecl _cwait(ptr long long) CRTDLL__cwait
@ stub _daylight_dll
@ stub _dup
@ stub _dup2
@ -125,8 +125,8 @@ debug_channels (crtdll)
@ cdecl _futime(long ptr) CRTDLL__futime
@ cdecl _gcvt(double long str) gcvt
@ cdecl _get_osfhandle(long) CRTDLL__get_osfhandle
@ stub _getch
@ stub _getche
@ cdecl _getch() CRTDLL__getch
@ cdecl _getche() CRTDLL__getche
@ cdecl _getcwd(ptr long) CRTDLL__getcwd
@ cdecl _getdcwd(long ptr long) CRTDLL__getdcwd
@ cdecl _getdiskfree(long ptr) CRTDLL__getdiskfree
@ -177,7 +177,7 @@ debug_channels (crtdll)
@ cdecl _j0(double) j0
@ cdecl _j1(double) j1
@ cdecl _jn(long double) jn
@ stub _kbhit
@ cdecl _kbhit() CRTDLL__kbhit
@ cdecl _lfind(ptr ptr ptr long ptr) CRTDLL__lfind
@ cdecl _loaddll(str) CRTDLL__loaddll
@ cdecl _local_unwind2(ptr long) CRTDLL__local_unwind2
@ -259,17 +259,17 @@ debug_channels (crtdll)
@ stub _pipe
@ stub _popen
@ cdecl _purecall() CRTDLL__purecall
@ stub _putch
@ cdecl _putch(long) CRTDLL__putch
@ stub _putenv
@ cdecl _putw(long ptr) CRTDLL__putw
@ stub _pwctype_dll
@ cdecl _read(long ptr long) CRTDLL__read
@ cdecl _rmdir(str) CRTDLL__rmdir
@ stub _rmtmp
@ cdecl _rmtmp() CRTDLL__rmtmp
@ cdecl _rotl (long long) CRTDLL__rotl
@ cdecl _rotr (long long) CRTDLL__rotr
@ cdecl _scalb (double long) CRTDLL__scalb
@ stub _searchenv
@ cdecl _searchenv(str str str) CRTDLL__searchenv
@ stub _seterrormode
@ cdecl _setjmp (ptr) CRTDLL__setjmp
@ cdecl _setmode(long long) CRTDLL__setmode
@ -282,10 +282,10 @@ debug_channels (crtdll)
@ stub _spawnle
@ stub _spawnlp
@ stub _spawnlpe
@ stub _spawnv
@ cdecl _spawnv(long str ptr) CRTDLL__spawnv
@ cdecl _spawnve(long str ptr ptr) CRTDLL__spawnve
@ stub _spawnvp
@ stub _spawnvpe
@ cdecl _spawnvp(long str ptr) CRTDLL__spawnvp
@ cdecl _spawnvpe(long str ptr ptr) CRTDLL__spawnvpe
@ cdecl _splitpath (str ptr ptr ptr ptr) CRTDLL__splitpath
@ cdecl _stat (str ptr) CRTDLL__stat
@ cdecl _statusfp() CRTDLL__statusfp
@ -321,7 +321,7 @@ debug_channels (crtdll)
@ forward _ultoa ntdll._ultoa
@ cdecl _ultow(long str long) CRTDLL__ultow
@ cdecl _umask(long) CRTDLL__umask
@ stub _ungetch
@ cdecl _ungetch(long) CRTDLL__ungetch
@ cdecl _unlink(str) CRTDLL__unlink
@ cdecl _unloaddll(long) CRTDLL__unloaddll
@ cdecl _utime(str ptr) CRTDLL__utime
@ -496,7 +496,7 @@ debug_channels (crtdll)
@ cdecl tan(double) tan
@ cdecl tanh(double) tanh
@ cdecl time(ptr) CRTDLL_time
@ stub tmpfile
@ cdecl tmpfile() CRTDLL_tmpfile
@ cdecl tmpnam(str) CRTDLL_tmpnam
@ cdecl tolower(long) tolower
@ cdecl toupper(long) toupper

View File

@ -124,9 +124,16 @@ BOOL WINAPI CRTDLL_Init(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
if (fdwReason == DLL_PROCESS_ATTACH) {
__CRTDLL__init_io();
__CRTDLL_init_console();
CRTDLL_setlocale( CRTDLL_LC_ALL, "C" );
CRTDLL_HUGE_dll = HUGE_VAL;
}
else if (fdwReason == DLL_PROCESS_DETACH)
{
CRTDLL__fcloseall();
__CRTDLL_free_console();
}
return TRUE;
}
@ -1672,3 +1679,67 @@ double __cdecl CRTDLL__nextafter(double x, double y)
return retVal;
}
/*********************************************************************
* _searchenv (CRTDLL.260)
*
* Search CWD and each directory of an environment variable for
* location of a file.
*/
VOID __cdecl CRTDLL__searchenv(LPCSTR file, LPCSTR env, LPSTR buff)
{
LPSTR envVal, penv;
char curPath[MAX_PATH];
*buff = '\0';
/* Try CWD first */
if (GetFileAttributesA( file ) != 0xFFFFFFFF)
{
GetFullPathNameA( file, MAX_PATH, buff, NULL );
/* Sigh. This error is *always* set, regardless of sucess */
__CRTDLL__set_errno(ERROR_FILE_NOT_FOUND);
return;
}
/* Search given environment variable */
envVal = CRTDLL_getenv(env);
if (!envVal)
{
__CRTDLL__set_errno(ERROR_FILE_NOT_FOUND);
return;
}
penv = envVal;
TRACE(":searching for %s in paths %s\n", file, envVal);
do
{
LPSTR end = penv;
while(*end && *end != ';') end++; /* Find end of next path */
if (penv == end || !*penv)
{
__CRTDLL__set_errno(ERROR_FILE_NOT_FOUND);
return;
}
strncpy(curPath, penv, end - penv);
if (curPath[end - penv] != '/' || curPath[end - penv] != '\\')
{
curPath[end - penv] = '\\';
curPath[end - penv + 1] = '\0';
}
else
curPath[end - penv] = '\0';
strcat(curPath, file);
TRACE("Checking for file %s\n", curPath);
if (GetFileAttributesA( curPath ) != 0xFFFFFFFF)
{
strcpy(buff, curPath);
__CRTDLL__set_errno(ERROR_FILE_NOT_FOUND);
return; /* Found */
}
penv = *end ? end + 1 : end;
} while(1);
}

View File

@ -20,7 +20,6 @@
DEFAULT_DEBUG_CHANNEL(crtdll);
/* INTERNAL: Translate find_t to PWIN32_FIND_DATAA */
static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft);
static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft)
{
DWORD dw;
@ -28,7 +27,7 @@ static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft)
/* Tested with crtdll.dll Version 2.50.4170 (NT) from win98 SE:
* attrib 0x80 (FILE_ATTRIBUTE_NORMAL)is returned as 0.
*/
if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
ft->attrib = 0;
else
ft->attrib = fd->dwFileAttributes;
@ -341,3 +340,4 @@ INT __cdecl CRTDLL__rmdir(LPSTR dir)
__CRTDLL__set_errno(GetLastError());
return -1;
}

View File

@ -105,8 +105,7 @@ VOID __cdecl CRTDLL__assert(LPVOID str, LPVOID file, UINT line)
*/
VOID __cdecl CRTDLL__c_exit(VOID)
{
FIXME("not calling CRTDLL cleanup\n");
/* dont exit, return to caller */
/* All cleanup is done on DLL detach; Return to caller */
}
@ -115,8 +114,7 @@ VOID __cdecl CRTDLL__c_exit(VOID)
*/
VOID __cdecl CRTDLL__cexit(VOID)
{
FIXME("not calling CRTDLL cleanup\n");
/* dont exit, return to caller */
/* All cleanup is done on DLL detach; Return to caller */
}

View File

@ -49,6 +49,7 @@ DEFAULT_DEBUG_CHANNEL(crtdll);
HANDLE __CRTDLL_handles[CRTDLL_MAX_FILES];
CRTDLL_FILE* __CRTDLL_files[CRTDLL_MAX_FILES];
INT __CRTDLL_flags[CRTDLL_MAX_FILES];
LPSTR __CRTDLL_tempfiles[CRTDLL_MAX_FILES];
CRTDLL_FILE __CRTDLL_iob[3];
static int __CRTDLL_fdstart = 3; /* first unallocated fd */
@ -182,6 +183,7 @@ VOID __CRTDLL__init_io(VOID)
/* FILE structs for stdin/out/err are static and never deleted */
__CRTDLL_files[i] = &__CRTDLL_iob[i];
__CRTDLL_iob[i]._file = i;
__CRTDLL_tempfiles[i] = NULL;
}
}
@ -261,6 +263,14 @@ INT __cdecl CRTDLL__close(INT fd)
__CRTDLL__set_errno(GetLastError());
return -1;
}
if (__CRTDLL_tempfiles[fd])
{
TRACE("deleting temporary file '%s'\n",__CRTDLL_tempfiles[fd]);
CRTDLL__unlink(__CRTDLL_tempfiles[fd]);
CRTDLL_free(__CRTDLL_tempfiles[fd]);
__CRTDLL_tempfiles[fd] = NULL;
}
TRACE(":ok\n");
return 0;
}
@ -361,7 +371,8 @@ INT __cdecl CRTDLL__fcloseall(VOID)
num_closed++;
}
TRACE(":closed (%d) handles\n",num_closed);
if (num_closed)
TRACE(":closed (%d) handles\n",num_closed);
return num_closed;
}
@ -792,12 +803,10 @@ INT __cdecl CRTDLL__open(LPCSTR path,INT flags)
flags &= ~_O_TEXT;
}
if (flags & ~(_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|_O_EXCL|_O_CREAT|_O_RDWR))
if (flags & ~(_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|_O_EXCL
|_O_CREAT|_O_RDWR|_O_TEMPORARY))
TRACE(":unsupported flags 0x%04x\n",flags);
/* clear those pesky flags ;-) */
flags &= (_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|_O_EXCL|_O_CREAT|_O_RDWR);
hand = CreateFileA( path, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, creation, FILE_ATTRIBUTE_NORMAL, -1);
@ -808,12 +817,17 @@ INT __cdecl CRTDLL__open(LPCSTR path,INT flags)
return -1;
}
fd = __CRTDLL__alloc_fd(hand,ioflag);
fd = __CRTDLL__alloc_fd(hand, ioflag);
TRACE(":fd (%d) handle (%d)\n",fd, hand);
if (flags & _IOAPPEND && fd > 0)
CRTDLL__lseek(fd, 0, FILE_END );
if (fd > 0)
{
if (flags & _O_TEMPORARY)
__CRTDLL_tempfiles[fd] = CRTDLL__strdup(path);
if (ioflag & _IOAPPEND)
CRTDLL__lseek(fd, 0, FILE_END );
}
return fd;
}
@ -843,6 +857,28 @@ INT __cdecl CRTDLL__putw(INT val, CRTDLL_FILE* file)
}
/*********************************************************************
* _rmtmp (CRTDLL.256)
*
* Remove all temporary files created by tmpfile().
*/
INT __cdecl CRTDLL__rmtmp(void)
{
int num_removed = 0, i = 3;
while(i < __CRTDLL_fdend)
if (__CRTDLL_tempfiles[i])
{
CRTDLL__close(i);
num_removed++;
}
if (num_removed)
TRACE(":removed (%d) temp files\n",num_removed);
return num_removed;
}
/*********************************************************************
* _read (CRTDLL.256)
*
@ -1630,6 +1666,24 @@ INT __cdecl CRTDLL_setbuf(CRTDLL_FILE* file, LPSTR buf)
}
/*********************************************************************
* tmpfile (CRTDLL.486)
*
* Create and return a temporary file.
*/
CRTDLL_FILE* __cdecl CRTDLL_tmpfile(void)
{
LPSTR filename = CRTDLL_tmpnam(NULL);
int fd = CRTDLL__open(filename, _O_CREAT | _O_BINARY |
_O_RDWR | _O_TEMPORARY);
if (fd != -1)
return __CRTDLL__alloc_fp(fd);
return NULL;
}
/*********************************************************************
* tmpnam (CRTDLL.490)
*

View File

@ -60,8 +60,7 @@ extern INT CRTDLL_doserrno;
/* INTERNAL: Spawn a child process */
static int __CRTDLL__spawn(INT flags, LPSTR exe, LPSTR args, LPSTR env);
static int __CRTDLL__spawn(INT flags, LPSTR exe, LPSTR args, LPSTR env)
static int __CRTDLL__spawn(INT flags, LPCSTR exe, LPSTR args, LPSTR env)
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
@ -109,10 +108,9 @@ static int __CRTDLL__spawn(INT flags, LPSTR exe, LPSTR args, LPSTR env)
/* INTERNAL: Convert argv list to a single 'delim'-seperated string */
static LPSTR __CRTDLL__argvtos(LPSTR *arg, CHAR delim);
static LPSTR __CRTDLL__argvtos(LPSTR *arg, CHAR delim)
static LPSTR __CRTDLL__argvtos(LPCSTR *arg, CHAR delim)
{
LPSTR *search = arg;
LPCSTR *search = arg;
LONG size = 0;
LPSTR ret;
@ -145,40 +143,107 @@ static LPSTR __CRTDLL__argvtos(LPSTR *arg, CHAR delim)
/*********************************************************************
* _spawnve (CRTDLL.274)
* _cwait (CRTDLL.069)
*
* Wait for a spawned process to finish.
*/
INT __cdecl CRTDLL__cwait(PINT status, INT pid, INT action)
{
HANDLE hPid = (HANDLE)pid;
action = action; /* Remove warning */
if (!WaitForSingleObject(hPid, -1)) /* wait forvever */
{
if (status)
{
DWORD stat;
GetExitCodeProcess(hPid, &stat);
*status = (INT)stat;
}
return pid;
}
CRTDLL_doserrno = GetLastError();
if (CRTDLL_doserrno == ERROR_INVALID_HANDLE)
CRTDLL_errno = ECHILD;
else
__CRTDLL__set_errno(CRTDLL_doserrno);
return status ? *status = -1 : -1;
}
/*********************************************************************
* _spawnv (CRTDLL.273)
*
* Spawn a process.
*
*/
HANDLE __cdecl CRTDLL__spawnve(INT flags, LPSTR name, LPSTR *argv, LPSTR *envv)
HANDLE __cdecl CRTDLL__spawnv(INT flags, LPCSTR name, LPCSTR *argv)
{
return CRTDLL__spawnve(flags, name, argv, NULL);
}
/*********************************************************************
* _spawnve (CRTDLL.274)
*
* Spawn a process.
*/
HANDLE __cdecl CRTDLL__spawnve(INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv)
{
LPSTR args = __CRTDLL__argvtos(argv,' ');
LPSTR envs = __CRTDLL__argvtos(envv,0);
LPSTR fullname = name;
LPCSTR fullname = name;
HANDLE ret = -1;
FIXME(":not translating name %s to locate program\n",fullname);
TRACE(":call (%s), params (%s), env (%s)\n",name,args,envs?"Custom":"Null");
if (args)
{
HANDLE ret = __CRTDLL__spawn(flags, fullname, args, envs);
ret = __CRTDLL__spawn(flags, fullname, args, envs);
CRTDLL_free(args);
CRTDLL_free(envs);
return ret;
}
if (envs)
CRTDLL_free(envs);
WARN(":No argv[0] passed - process will not be executed");
return -1;
return ret;
}
/*********************************************************************
* _spawnvp (CRTDLL.275)
*
* Spawn a process.
*/
HANDLE __cdecl CRTDLL__spawnvp(INT flags, LPCSTR name, LPCSTR *argv)
{
return CRTDLL__spawnvpe(flags, name, argv, NULL);
}
/*********************************************************************
* _spawnvpe (CRTDLL.276)
*
* Spawn a process.
*/
HANDLE __cdecl CRTDLL__spawnvpe(INT flags, LPCSTR name, LPCSTR *argv, LPCSTR *envv)
{
char fullname[MAX_PATH];
CRTDLL__searchenv(name, "PATH", fullname);
return CRTDLL__spawnve(flags, fullname[0] ? fullname : name, argv, envv);
}
/*********************************************************************
* system (CRTDLL.485)
*
* Spawn an O/S process.
*/
INT __cdecl CRTDLL_system(LPSTR x)
INT __cdecl CRTDLL_system(LPCSTR cmd)
{
/* FIXME: should probably launch cmd interpreter in COMSPEC */
return __CRTDLL__spawn(_P_WAIT, NULL, x, NULL);
return __CRTDLL__spawn(_P_WAIT, cmd, NULL, NULL);
}