2 * Copyright (c) 1980, 1991 The Regents of the University of California.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * stdio.c Implement a whole load of i/o functions.
31 * This makes it much easier to keep track of inherited handles and
32 * also makes us reasonably vendor crt-independent.
37 #define WIN32_LEAN_AND_MEAN
41 #include <sys/types.h>
49 #define __MAX_OPEN_FILES 64
54 typedef struct _myfile {
59 typedef unsigned long u_long;
61 #define INVHL (INVALID_HANDLE_VALUE)
63 MY_FILE __gOpenFiles[__MAX_OPEN_FILES]={0};
64 MY_FILE __gOpenFilesCopy[__MAX_OPEN_FILES]={0};
66 MY_FILE *my_stdin=0, *my_stdout=0, *my_stderr=0;
72 void init_stdio(void) {
75 __gOpenFiles[0].handle = GetStdHandle(STD_INPUT_HANDLE);
76 __gOpenFiles[1].handle = GetStdHandle(STD_OUTPUT_HANDLE);
77 __gOpenFiles[2].handle = GetStdHandle(STD_ERROR_HANDLE);
79 __gOpenFiles[0].flags = (GetFileType(ULongToPtr(STD_INPUT_HANDLE))==
80 FILE_TYPE_CHAR)? FCONSOLE:0;
81 __gOpenFiles[1].flags = (GetFileType(ULongToPtr(STD_OUTPUT_HANDLE))==
82 FILE_TYPE_CHAR)? FCONSOLE:0;
83 __gOpenFiles[2].flags = (GetFileType(ULongToPtr(STD_ERROR_HANDLE))==
84 FILE_TYPE_CHAR)? FCONSOLE:0;
86 for(i=3;i<__MAX_OPEN_FILES;i++) {
87 __gOpenFiles[i].handle = INVHL;
88 __gOpenFilesCopy[i].handle = INVHL;
89 __gOpenFiles[i].flags = 0;
92 my_stdin = &__gOpenFiles[0];
93 my_stdout = &__gOpenFiles[1];
94 my_stderr = &__gOpenFiles[2];
97 void nt_close_on_exec(int fd, int on) {
99 __gOpenFiles[fd].flags |= FIOCLEX;
101 __gOpenFiles[fd].flags &= ~FIOCLEX;
103 void restore_fds(void ) {
107 if (__forked && (didfds|| __dup_stdin))
110 // ok for tcsh. see fork.c for why
112 __gOpenFiles[0].handle = INVHL;
113 __gOpenFiles[1].handle = INVHL;
114 __gOpenFiles[2].handle = INVHL;
115 my_stdin = &__gOpenFiles[0];
116 my_stdout = &__gOpenFiles[1];
117 my_stderr = &__gOpenFiles[2];
118 for(i=min;i<__MAX_OPEN_FILES;i++) {
119 if (__gOpenFilesCopy[i].handle == INVHL)
121 __gOpenFiles[i].handle = __gOpenFilesCopy[i].handle ;
122 __gOpenFiles[i].flags = __gOpenFilesCopy[i].flags ;
125 void close_copied_fds(void ) {
128 if (didfds|| __dup_stdin)
130 for(i=min;i<__MAX_OPEN_FILES;i++) {
131 if (__gOpenFilesCopy[i].handle == INVHL)
133 CloseHandle((HANDLE)__gOpenFilesCopy[i].handle);
134 __gOpenFilesCopy[i].handle = INVHL;
138 void copy_fds(void ) {
141 if (didfds || __dup_stdin)
143 for(i=min;i<__MAX_OPEN_FILES;i++) {
144 if (__gOpenFiles[i].handle == INVHL) {
145 __gOpenFilesCopy[i].handle = INVHL;
149 if(!DuplicateHandle(GetCurrentProcess(),
150 (HANDLE)__gOpenFiles[i].handle ,
152 (HANDLE*)&__gOpenFilesCopy[i].handle,
153 0, TRUE, DUPLICATE_SAME_ACCESS) )
154 __gOpenFilesCopy[i].handle = INVHL;
155 __gOpenFilesCopy[i].flags = __gOpenFiles[i].flags;
158 intptr_t __nt_get_osfhandle(int fd) {
159 return (intptr_t)(__gOpenFiles[fd].handle);
161 int __nt_open_osfhandle(intptr_t h1, int mode) {
164 UNREFERENCED_PARAMETER(mode);
166 for(i=0;i<__MAX_OPEN_FILES;i++) {
167 if (__gOpenFiles[i].handle == INVHL) {
168 __gOpenFiles[i].handle = (HANDLE)h1;
169 __gOpenFiles[i].flags = 0;
176 int nt_close(int fd) {
178 if( (fd == -1) ||(__gOpenFiles[fd].handle == INVHL))
180 CloseHandle((HANDLE)(__gOpenFiles[fd].handle));
181 __gOpenFiles[fd].handle = INVHL;
182 __gOpenFiles[fd].flags = 0;
184 // dprintf("closing 0x%08x\n",(__gOpenFiles[fd].handle));
187 int nt_access(char *filename, int mode) {
189 DWORD attribs=(DWORD)-1, bintype;
191 char buf[512];/*FIXBUF*/
197 (void)StringCbPrintf(buf,sizeof(buf),"%s",filename);
199 attribs = GetFileAttributes(buf);
202 if (attribs == (DWORD) -1) {
203 if( (GetLastError() == ERROR_FILE_NOT_FOUND) && (mode & X_OK) ) {
206 (void)StringCbPrintf(buf,sizeof(buf),"%s.exe",filename);
209 (void)StringCbPrintf(buf,sizeof(buf),"%s.cmd",filename);
212 (void)StringCbPrintf(buf,sizeof(buf),"%s.bat",filename);
215 (void)StringCbPrintf(buf,sizeof(buf),"%s.com",filename);
225 if (attribs == (DWORD)-1 ) {
229 if ( (mode & W_OK) && (attribs & FILE_ATTRIBUTE_READONLY) ) {
234 if ((mode & XD_OK) && (attribs & FILE_ATTRIBUTE_DIRECTORY) ){
238 if ((!(attribs & FILE_ATTRIBUTE_DIRECTORY)) &&
239 !GetBinaryType(buf,&bintype) &&(tries >4) ) {
246 int nt_seek(HANDLE h1, long offset, int how) {
251 dwmove = FILE_CURRENT;
264 if (SetFilePointer(h1,offset,NULL,dwmove) == -1){
270 int nt_lseek(int fd,long offset, int how) {
272 h1 =__gOpenFiles[fd].handle;
273 return nt_seek(h1,offset,how);
275 int nt_isatty(int fd) {
276 return (__gOpenFiles[fd].flags & FCONSOLE);
278 int nt_dup(int fdin) {
281 HANDLE horig = __gOpenFiles[fdin].handle;
285 if (!DuplicateHandle(GetCurrentProcess(),
291 DUPLICATE_SAME_ACCESS)) {
292 errno = GetLastError();
296 ret = __nt_open_osfhandle((intptr_t)hdup,_O_BINARY | _O_NOINHERIT);
298 __gOpenFiles[ret].flags = __gOpenFiles[fdin].flags;
302 int nt_dup2(int fdorig,int fdcopy) {
305 HANDLE horig = __gOpenFiles[fdorig].handle;
308 if (__gOpenFiles[fdcopy].handle != INVHL) {
309 CloseHandle((HANDLE)__gOpenFiles[fdcopy].handle );
310 __gOpenFiles[fdcopy].handle = INVHL;
311 __gOpenFiles[fdcopy].flags = 0;
313 if (!DuplicateHandle(GetCurrentProcess(),
318 fdcopy<3?TRUE:FALSE, DUPLICATE_SAME_ACCESS)) {
319 errno = GetLastError();
323 __gOpenFiles[fdcopy].handle = hdup;
324 __gOpenFiles[fdcopy].flags = __gOpenFiles[fdorig].flags;
327 SetStdHandle(STD_INPUT_HANDLE,hdup);
330 SetStdHandle(STD_OUTPUT_HANDLE,hdup);
333 SetStdHandle(STD_ERROR_HANDLE,hdup);
341 int nt_pipe2(HANDLE hpipe[2]) {
343 SECURITY_ATTRIBUTES secd;
345 secd.nLength=sizeof(secd);
346 secd.lpSecurityDescriptor=NULL;
347 secd.bInheritHandle=FALSE;
349 return (!CreatePipe(&hpipe[0],&hpipe[1],&secd,0));
351 int nt_pipe(int hpipe[2]) {
355 hpipe[0] = __nt_open_osfhandle((intptr_t)hpipe2[0],O_NOINHERIT);
356 hpipe[1] = __nt_open_osfhandle((intptr_t)hpipe2[1],O_NOINHERIT);
359 /* check if name is //server. if checkifShare is set,
360 * also check if //server/share
362 int is_server(const char *name,int checkifShare) {
365 if (!*name || !*(name+1))
369 if (((p1[0] != '/') && (p1[0] != '\\') ) ||
370 ((p1[1] != '/') && (p1[1] != '\\') ))
374 while (*p2 && *p2 != '/' && *p2 != '\\')
376 if (Ismbyte1(*p2) && *(p2 + 1))
379 #endif /* DSPMBYTE */
382 /* just check for server */
384 /* null terminated unc server name */
385 /* terminating '/' (//server/) is also ok */
386 if (!*p2 || !*(p2+1))
391 if (!*p2 || !*(p2+1))
394 while(*p2 && *p2 != '/' && *p2 != '\\')
396 if (!*p2 || !*(p2+1))
402 __inline int is_unc(char *filename) {
403 if (*filename && (*filename == '/' || *filename == '\\')
405 && (*(filename+1) == '/' || *(filename+1) == '\\')) {
410 int nt_stat(const char *filename, struct stat *stbuf) {
412 // stat hangs on server name
413 // Use any directory, since the info in stat means %$!* on
416 /* is server or share */
417 if (is_server(filename,0) || is_server(filename,1) ||
418 (*(filename+1) && *(filename+1) == ':' && !*(filename+2)) ) {
419 return _stat("C:/",(struct _stat *)stbuf);
422 size_t len = strlen(filename);
423 char *last = (char*)filename + len - 1;
425 /* Possible X: and X:/ strings */
426 BOOL root = (len <= 3 && *(filename + 1) == ':');
427 /* exclude X:/ strings */
428 BOOL lastslash = ((*last == '/') && !root);
431 rc = _stat(filename,(struct _stat *)stbuf);
438 // replacement for creat that makes handle non-inheritable.
441 int nt_creat(const char *filename, int mode) {
442 // ignore the bloody mode
444 int fd = 0,is_cons =0;
446 SECURITY_ATTRIBUTES security;
448 UNREFERENCED_PARAMETER(mode);
451 security.nLength = sizeof(security);
452 security.lpSecurityDescriptor = NULL;
453 security.bInheritHandle = FALSE;
455 if (!_stricmp(filename,"/dev/tty") ){
456 filename = "CONOUT$";
459 else if (!_stricmp(filename,"/dev/null") ){
462 retval = CreateFile(filename,
463 GENERIC_READ | GENERIC_WRITE,
464 FILE_SHARE_READ | FILE_SHARE_WRITE,
465 is_cons?NULL:&security,
470 if (retval == INVALID_HANDLE_VALUE) {
474 fd = __nt_open_osfhandle((intptr_t)retval,_O_BINARY);
476 //should never happen
481 __gOpenFiles[fd].flags = FCONSOLE;
487 int nt_open(const char *filename, int perms,...) {
489 // ignore the bloody mode
491 int fd,mode, is_cons=0;
493 SECURITY_ATTRIBUTES security;
494 DWORD dwAccess, dwFlags, dwCreateDist;
498 mode = va_arg(ap,int);
501 if (!lstrcmp(filename,"/dev/tty") ){
502 if (perms == O_RDONLY) //o_rdonly is 0
504 else if (perms & O_WRONLY)
505 filename = "CONOUT$";
508 else if (!lstrcmp(filename,"/dev/null") ){
511 security.nLength = sizeof(security);
512 security.lpSecurityDescriptor = NULL;
513 security.bInheritHandle = FALSE;
515 switch (perms & (_O_RDONLY | _O_WRONLY | _O_RDWR) ) {
517 dwAccess = GENERIC_READ;
520 dwAccess = GENERIC_WRITE;
523 dwAccess = GENERIC_READ | GENERIC_WRITE ;
529 switch (perms & (_O_CREAT | _O_TRUNC) ){
531 dwCreateDist = OPEN_EXISTING;
534 dwCreateDist = CREATE_ALWAYS;
536 case _O_CREAT | _O_TRUNC:
537 dwCreateDist = CREATE_ALWAYS;
540 dwCreateDist = TRUNCATE_EXISTING;
547 if (perms & O_TEMPORARY)
548 dwFlags = FILE_FLAG_DELETE_ON_CLOSE;
549 retval = CreateFile(filename,
550 dwAccess,//GENERIC_READ | GENERIC_WRITE,
551 FILE_SHARE_READ | FILE_SHARE_WRITE,
553 dwCreateDist,//CREATE_ALWAYS,
557 if (retval == INVALID_HANDLE_VALUE) {
558 int err = GetLastError();
559 if (err == ERROR_FILE_NOT_FOUND)
565 if (perms & O_APPEND) {
566 SetFilePointer(retval,0,NULL,FILE_END);
568 fd = __nt_open_osfhandle((intptr_t)retval,_O_BINARY);
570 //should never happen
575 __gOpenFiles[fd].flags = FCONSOLE;
582 * This should be the LAST FUNCTION IN THIS FILE
586 #undef _open_osfhandle
588 int nt_fstat(int fd, struct stat *stbuf) {
594 if(!DuplicateHandle(GetCurrentProcess(),
595 (HANDLE)__gOpenFiles[fd].handle,
600 DUPLICATE_SAME_ACCESS) )
602 realfd = _open_osfhandle((intptr_t)h1,0);
606 if( fstat(realfd,stbuf) <0 ) {