Make a temporary file using BuildTemporary() in "/tmp" folder on Linux or using "TEMP" environment variable on Windows.
Use the new OSD_File::Capture() method for standard output redirection.
#include <OSD_Process.hxx>
#include <OSD_Path.hxx>
#include <OSD.hxx>
+#include <OSD_File.hxx>
#include <string.h>
#include <tcl.h>
cout << flush;
}
- FILE* capture_start (int std_fd, int *save_fd, char*& tmp_name)
+ int capture_start (OSD_File& theTmpFile, int std_fd)
{
- *save_fd = 0;
-
- // open temporary files
- #if defined(_WIN32)
- // use _tempnam() to decrease chances of failure (tmpfile() creates
- // file in root folder and will fail if it is write protected), see #24132
- static const char* tmpdir = getenv("TEMP");
- static char prefix[256] = ""; // prefix for temporary files, initialize once per process using pid
- if (prefix[0] == '\0')
- sprintf (prefix, "drawtmp%d_", (int)OSD_Process().ProcessId());
- tmp_name = _tempnam (tmpdir, prefix);
- FILE* aTmpFile = (tmp_name != NULL ? fopen (tmp_name, "w+b") : tmpfile());
- #else
- tmp_name = NULL;
- FILE* aTmpFile = tmpfile();
- #endif
- int fd_tmp = (aTmpFile != NULL ? fileno (aTmpFile) : -1);
- if (fd_tmp < 0)
+ theTmpFile.BuildTemporary();
+ if (theTmpFile.Failed())
{
cerr << "Error: cannot create temporary file for capturing console output" << endl;
- fclose (aTmpFile);
- return NULL;
+ return -1;
}
// remember current file descriptors of standard stream, and replace it by temporary
- (*save_fd) = dup(std_fd);
- dup2(fd_tmp, std_fd);
- return aTmpFile;
+ return theTmpFile.Capture(std_fd);
}
- void capture_end (FILE* tmp_file, int std_fd, int save_fd, char* tmp_name, Standard_OStream &log, Standard_Boolean doEcho)
+ void capture_end (OSD_File* tmp_file, int std_fd, int save_fd, Standard_OStream &log, Standard_Boolean doEcho)
{
- if (! tmp_file)
+ if (!tmp_file)
return;
// restore normal descriptors of console stream
- dup2 (save_fd, std_fd);
+ dup2(save_fd, std_fd);
close(save_fd);
// extract all output and copy it to log and optionally to cout
const int BUFSIZE = 2048;
- char buf[BUFSIZE];
- rewind(tmp_file);
- while (fgets (buf, BUFSIZE, tmp_file) != NULL)
+ TCollection_AsciiString buf;
+ tmp_file->Rewind();
+ while (tmp_file->ReadLine (buf, BUFSIZE) > 0)
{
log << buf;
if (doEcho)
}
// close temporary file
- fclose (tmp_file);
+ tmp_file->Close();
// remove temporary file if this is not done by the system
- if (tmp_name)
- remove (tmp_name);
+ if (tmp_file->Exists())
+ tmp_file->Remove();
}
+
};
// MKV 29.03.05
flush_standard_streams();
// capture cout and cerr to log
- char *err_name = NULL, *out_name = NULL;
- FILE * aFile_err = NULL;
- FILE * aFile_out = NULL;
- int fd_err_save = 0;
- int fd_out_save = 0;
+ OSD_File aFile_out, aFile_err;
+ int fd_err_save = -1;
+ int fd_out_save = -1;
if (doLog)
{
- aFile_out = capture_start (STDOUT_FILENO, &fd_out_save, out_name);
- aFile_err = capture_start (STDERR_FILENO, &fd_err_save, err_name);
+ fd_out_save = capture_start (aFile_out, STDOUT_FILENO);
+ fd_err_save = capture_start (aFile_err, STDERR_FILENO);
}
// run command
// end capturing cout and cerr
if (doLog)
{
- capture_end (aFile_err, STDERR_FILENO, fd_err_save, err_name, di.Log(), doEcho);
- capture_end (aFile_out, STDOUT_FILENO, fd_out_save, out_name, di.Log(), doEcho);
+ capture_end (&aFile_err, STDERR_FILENO, fd_err_save, di.Log(), doEcho);
+ capture_end (&aFile_out, STDOUT_FILENO, fd_out_save, di.Log(), doEcho);
}
// log command result
#ifndef _WIN32
-
#include <OSD_Directory.hxx>
#include <OSD_Path.hxx>
#include <OSD_Protection.hxx>
}
OSD_Directory OSD_Directory::BuildTemporary(){
-OSD_Protection Protect;
OSD_Directory aDirectoryToReturn;
-Standard_Integer internal_prot;
-Standard_CString name = tmpnam(NULL);
-TCollection_AsciiString aString (name);
-
- internal_prot = Protect.Internal();
+char name[] = "/tmp/CSFXXXXXX";
- umask ( 0 );
- mkdir (name, (mode_t)internal_prot);
- unlink(name);//Destroys link but directory still exists while
+ // Create a temporary directory with 0700 permissions.
+ if (NULL == mkdtemp( name ))
+ return aDirectoryToReturn; // Can't create a directory
+
+ unlink(name);//Destroys link but directory still exists while
//current process lives.
+ TCollection_AsciiString aString (name);
aDirectoryToReturn.SetPath ( aString );
return aDirectoryToReturn;
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
-OSD_File OSD_File::BuildTemporary(){
+void OSD_File::BuildTemporary(){
+
+ if ( IsOpen() )
+ Close();
#if defined(vax) || defined(__vms) || defined(VAXVMS)
FILE *fic;
- OSD_File result;
int dummy;
fic = tmpfile();
dummy = open("dummy", O_RDWR | O_CREAT); // Open a dummy file
- result.myFileChannel = dummy - 1; // This is file channel of "fic" +1
+ myFileChannel = dummy - 1; // This is file channel of "fic" +1
close(dummy); // Close dummy file
unlink("dummy"); // Removes dummy file
#else
- OSD_File result;
- char *name = tmpnam((char*) 0) ;
-
+ char name[] = "/tmp/CSFXXXXXX";
+ myFileChannel = mkstemp( name );
TCollection_AsciiString aName ( name ) ;
OSD_Path aPath( aName ) ;
- result.SetPath( aPath ) ;
+ SetPath( aPath ) ;
- result.myFILE = fopen( name, "w+" ) ;
-
- result.myFileChannel = fileno( (FILE*)result.myFILE );
+ myFILE = fdopen( myFileChannel, "w+" ) ;
#endif
- result.myMode = OSD_ReadWrite;
-
- return (result);
+ myMode = OSD_ReadWrite;
}
return Standard_True;
}
+int OSD_File::Capture(int theDescr) {
+ // Duplicate an old file descriptor of the given one to be able to restore output to it later.
+ int oldDescr = dup(theDescr);
+ // Redirect the output to this file
+ dup2(myFileChannel, theDescr);
+
+ // Return the old descriptor
+ return oldDescr;
+}
+
+void OSD_File::Rewind() {
+ rewind((FILE*)myFILE);
+}
+
#else /* _WIN32 */
//------------------------------------------------------------------------
myFileHandle = INVALID_HANDLE_VALUE;
} // end constructor ( 2 )
+// ---------------------------------------------------------------------
+// Redirect a standard handle (fileno(stdout), fileno(stdin) or
+// fileno(stderr) to this OSD_File and return the copy of the original
+// standard handle.
+// Example:
+// OSD_File aTmp;
+// aTmp.BuildTemporary();
+// int stdfd = _fileno(stdout);
+//
+// int oldout = aTmp.Capture(stdfd);
+// cout << "Some output to the file" << endl;
+// cout << flush;
+// fflush(stdout);
+//
+// _dup2(oldout, stdfd); // Restore standard output
+// aTmp.Close();
+// ---------------------------------------------------------------------
+int OSD_File::Capture(int theDescr) {
+ // Get POSIX file descriptor from this file handle
+ int dFile = _open_osfhandle(reinterpret_cast<intptr_t>(myFileHandle), myMode);
+
+ if (0 > dFile)
+ {
+ _osd_wnt_set_error ( myError, OSD_WFile, myFileHandle );
+ return -1;
+ }
+
+ // Duplicate an old file descriptor of the given one to be able to restore output to it later.
+ int oldDescr = _dup(theDescr);
+ // Redirect the output to this file
+ _dup2(dFile, theDescr);
+
+ // Return the old descriptor
+ return oldDescr;
+}
+
+void OSD_File::Rewind() {
+ SetFilePointer( myFileHandle, 0, NULL, FILE_BEGIN );
+}
+
// protect against occasional use of myFileHande in Windows code
#define myFileChannel myFileChannel_is_only_for_Linux
} OSD_WNT_KEY;
-OSD_File OSD_File :: BuildTemporary () {
+ void OSD_File::BuildTemporary () {
OSD_Protection prt;
- OSD_File retVal;
HKEY hKey;
TCHAR tmpPath[ MAX_PATH ];
BOOL fOK = FALSE;
GetTempFileName ( tmpPath, "CSF", 0, tmpPath );
- retVal.SetPath ( OSD_Path ( tmpPath ) );
- retVal.Build ( OSD_ReadWrite, prt );
-
- return retVal;
+ if ( IsOpen() )
+ Close();
+ SetPath ( OSD_Path ( tmpPath ) );
+ Build ( OSD_ReadWrite, prt );
} // end OSD_File :: BuildTemporary
//-------------------------------------------------finpri???980424
-
//! bytes actually read into <NByteRead> and placed into the
//! Buffer <Buffer>.
Standard_EXPORT void ReadLine (TCollection_AsciiString& Buffer, const Standard_Integer NByte, Standard_Integer& NbyteRead);
+
+ //! Reads bytes from the data pointed to by the object file
+ //! into the buffer <Buffer>.
+ //! Data is read until <NByte-1> bytes have been read,
+ //! until a newline character is read and transferred into
+ //! <Buffer>, or until an EOF (End-of-File) condition is
+ //! encountered.
+ //! Upon successful completion, Read returns the number of
+ //! bytes actually read and placed into the Buffer <Buffer>.
+ inline Standard_Integer ReadLine (
+ TCollection_AsciiString& Buffer, const Standard_Integer NByte)
+ {
+ Standard_Integer NbyteRead;
+ ReadLine(Buffer, NByte, NbyteRead);
+ return NbyteRead;
+ }
+
//! Attempts to read Nbyte bytes from the files associated with
//! the object File.
Standard_EXPORT OSD_KindFile KindOfFile() const;
//! Makes a temporary File
- //! This returned file is already open !
- //! This file is non-persistent and will be automatically
- //! removed when its process finishes.
- Standard_EXPORT static OSD_File BuildTemporary();
+ //! This temporary file is already open !
+ Standard_EXPORT void BuildTemporary();
//! Locks current file
Standard_EXPORT void SetLock (const OSD_LockType Lock);
//! find an editor on the system and edit the given file
Standard_EXPORT Standard_Boolean Edit();
-
+ //! Set file pointer position to the beginning of the file
+ Standard_EXPORT void Rewind();
+
+ //! Redirect a standard handle (fileno(stdout), fileno(stdin) or
+ //! fileno(stderr) to this OSD_File and return the copy of the original
+ //! standard handle.
+ //! Example:
+ //! OSD_File aTmp;
+ //! aTmp.BuildTemporary();
+ //! int stdfd = _fileno(stdout);
+ //!
+ //! int oldout = aTmp.Capture(stdfd);
+ //! cout << "Some output to the file" << endl;
+ //! cout << flush;
+ //! fflush(stdout);
+ //!
+ //! _dup2(oldout, stdfd); // Restore standard output
+ //! aTmp.Close();
+ Standard_EXPORT int Capture(int theDescr);
protected: