TclFile TclpOpenFile( const char *fname, /* The name of the file to open. */ int mode) /* In what mode to open the file? */ { int fd; const char *native; Tcl_DString ds; native = Tcl_UtfToExternalDString(NULL, fname, -1, &ds); fd = TclOSopen(native, mode, 0666); /* INTL: Native. */ Tcl_DStringFree(&ds); if (fd != -1) { fcntl(fd, F_SETFD, FD_CLOEXEC); /* * If the file is being opened for writing, seek to the end so we can * append to any data already in the file. */ if ((mode & O_WRONLY) && !(mode & O_APPEND)) { TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_END); } /* * Increment the fd so it can't be 0, which would conflict with the * NULL return for errors. */ return MakeFile(fd); } return NULL; }
TclFile TclpCreateTempFile( const char *contents) /* String to write into temp file, or NULL. */ { int fd = TclUnixOpenTemporaryFile(NULL, NULL, NULL, NULL); if (fd == -1) { return NULL; } fcntl(fd, F_SETFD, FD_CLOEXEC); if (contents != NULL) { Tcl_DString dstring; char *native; native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring); if (write(fd, native, Tcl_DStringLength(&dstring)) == -1) { close(fd); Tcl_DStringFree(&dstring); return NULL; } Tcl_DStringFree(&dstring); TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_SET); } return MakeFile(fd); }
static int FileSeekProc( ClientData instanceData, /* File state. */ long offset, /* Offset to seek to. */ int mode, /* Relative to where should we seek? Can be * one of SEEK_START, SEEK_SET or SEEK_END. */ int *errorCodePtr) /* To store error code. */ { FileState *fsPtr = instanceData; Tcl_WideInt oldLoc, newLoc; /* * Save our current place in case we need to roll-back the seek. */ oldLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) 0, SEEK_CUR); if (oldLoc == Tcl_LongAsWide(-1)) { /* * Bad things are happening. Error out... */ *errorCodePtr = errno; return -1; } newLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) offset, mode); /* * Check for expressability in our return type, and roll-back otherwise. */ if (newLoc > Tcl_LongAsWide(INT_MAX)) { *errorCodePtr = EOVERFLOW; TclOSseek(fsPtr->fd, (Tcl_SeekOffset) oldLoc, SEEK_SET); return -1; } else { *errorCodePtr = (newLoc == Tcl_LongAsWide(-1)) ? errno : 0; } return (int) Tcl_WideAsLong(newLoc); }
static Tcl_WideInt FileWideSeekProc( ClientData instanceData, /* File state. */ Tcl_WideInt offset, /* Offset to seek to. */ int mode, /* Relative to where should we seek? Can be * one of SEEK_START, SEEK_CUR or SEEK_END. */ int *errorCodePtr) /* To store error code. */ { FileState *fsPtr = instanceData; Tcl_WideInt newLoc; newLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) offset, mode); *errorCodePtr = (newLoc == -1) ? errno : 0; return newLoc; }
TclFile TclpCreateTempFile( const char *contents) /* String to write into temp file, or NULL. */ { char fileName[L_tmpnam + 9]; const char *native; Tcl_DString dstring; int fd; /* * We should also check against making more then TMP_MAX of these. */ strcpy(fileName, P_tmpdir); /* INTL: Native. */ if (fileName[strlen(fileName) - 1] != '/') { strcat(fileName, "/"); /* INTL: Native. */ } strcat(fileName, "tclXXXXXX"); fd = mkstemp(fileName); /* INTL: Native. */ if (fd == -1) { return NULL; } fcntl(fd, F_SETFD, FD_CLOEXEC); unlink(fileName); /* INTL: Native. */ if (contents != NULL) { native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring); if (write(fd, native, strlen(native)) == -1) { close(fd); Tcl_DStringFree(&dstring); return NULL; } Tcl_DStringFree(&dstring); TclOSseek(fd, (Tcl_SeekOffset) 0, SEEK_SET); } return MakeFile(fd); }
void TclpInitPlatform(void) { #ifdef DJGPP tclPlatform = TCL_PLATFORM_WINDOWS; #else tclPlatform = TCL_PLATFORM_UNIX; #endif /* * Make sure, that the standard FDs exist. [Bug 772288] */ if (TclOSseek(0, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) { open("/dev/null", O_RDONLY); } if (TclOSseek(1, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) { open("/dev/null", O_WRONLY); } if (TclOSseek(2, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) { open("/dev/null", O_WRONLY); } /* * The code below causes SIGPIPE (broken pipe) errors to be ignored. This * is needed so that Tcl processes don't die if they create child * processes (e.g. using "exec" or "open") that terminate prematurely. * The signal handler is only set up when the first interpreter is * created; after this the application can override the handler with a * different one of its own, if it wants. */ #ifdef SIGPIPE (void) signal(SIGPIPE, SIG_IGN); #endif /* SIGPIPE */ #if defined(__FreeBSD__) && defined(__GNUC__) /* * Adjust the rounding mode to be more conventional. Note that FreeBSD * only provides the __fpsetreg() used by the following two for the GNU * Compiler. When using, say, Intel's icc they break. (Partially based on * patch in BSD ports system from [email protected]) */ fpsetround(FP_RN); (void) fpsetmask(0L); #endif #if defined(__bsdi__) && (_BSDI_VERSION > 199501) /* * Find local symbols. Don't report an error if we fail. */ (void) dlopen(NULL, RTLD_NOW); /* INTL: Native. */ #endif /* * Initialize the C library's locale subsystem. This is required for input * methods to work properly on X11. We only do this for LC_CTYPE because * that's the necessary one, and we don't want to affect LC_TIME here. * The side effect of setting the default locale should be to load any * locale specific modules that are needed by X. [BUG: 5422 3345 4236 2522 * 2521]. */ setlocale(LC_CTYPE, ""); /* * In case the initial locale is not "C", ensure that the numeric * processing is done in "C" locale regardless. This is needed because Tcl * relies on routines like strtod, but should not have locale dependent * behavior. */ setlocale(LC_NUMERIC, "C"); #ifdef GET_DARWIN_RELEASE { struct utsname name; if (!uname(&name)) { tclMacOSXDarwinRelease = strtol(name.release, NULL, 10); } } #endif }
Tcl_Channel TclpGetDefaultStdChannel( int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */ { Tcl_Channel channel = NULL; int fd = 0; /* Initializations needed to prevent */ int mode = 0; /* compiler warning (used before set). */ const char *bufMode = NULL; /* * Some #def's to make the code a little clearer! */ #define ZERO_OFFSET ((Tcl_SeekOffset) 0) #define ERROR_OFFSET ((Tcl_SeekOffset) -1) switch (type) { case TCL_STDIN: if ((TclOSseek(0, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET) && (errno == EBADF)) { return NULL; } fd = 0; mode = TCL_READABLE; bufMode = "line"; break; case TCL_STDOUT: if ((TclOSseek(1, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET) && (errno == EBADF)) { return NULL; } fd = 1; mode = TCL_WRITABLE; bufMode = "line"; break; case TCL_STDERR: if ((TclOSseek(2, ZERO_OFFSET, SEEK_CUR) == ERROR_OFFSET) && (errno == EBADF)) { return NULL; } fd = 2; mode = TCL_WRITABLE; bufMode = "none"; break; default: Tcl_Panic("TclGetDefaultStdChannel: Unexpected channel type"); break; } #undef ZERO_OFFSET #undef ERROR_OFFSET channel = Tcl_MakeFileChannel(INT2PTR(fd), mode); if (channel == NULL) { return NULL; } /* * Set up the normal channel options for stdio handles. */ if (Tcl_GetChannelType(channel) == &fileChannelType) { Tcl_SetChannelOption(NULL, channel, "-translation", "auto"); } else { Tcl_SetChannelOption(NULL, channel, "-translation", "auto crlf"); } Tcl_SetChannelOption(NULL, channel, "-buffering", bufMode); return channel; }