mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-02 17:46:22 +03:00
Found via `codespell -q 3 -S "*.fr" -L aadd,abnd,abord,acces,acount,adn,afile,aline,alo,alocation,alog,als,anc,ane,anid,anormal,anout,ans,anumber,aother,aparent,apoints,aprogram,asender,asign,asnd,ba,bbuild,bloc,bord,bu,caf,cas,childrens,childs,classe,clen,commun,cylindre,discret,don,dout,dum,ede,enew,entite,entites,extrem,fo,fonction,geometrie,guid,hilight,hilights,hist,identic,ii,indx,inout,invalide,ist,iterm,llength,lod,maked,mape,mke,modeling,methode,mye,myu,nam,nd,nin,normale,normales,ons,parametre,parametres,periode,pinter,pres,projet,remplace,reste,resul,secont,serie,siz,shs,slin,som,somme,syntaxe,sur,te,thei,theis,ther,theres,thes,thev,thex,thet,tol,transfert,unhilight,unhilights,va,vas,verifie,vertexes,weight`
649 lines
17 KiB
C++
649 lines
17 KiB
C++
// Created on: 1995-02-23
|
|
// Created by: Remi LEQUETTE
|
|
// Copyright (c) 1995-1999 Matra Datavision
|
|
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
#include <Draw_Interpretor.hxx>
|
|
|
|
#include <Draw_Appli.hxx>
|
|
#include <Message.hxx>
|
|
#include <Message_PrinterOStream.hxx>
|
|
#include <OSD.hxx>
|
|
#include <OSD_Path.hxx>
|
|
#include <Standard_SStream.hxx>
|
|
#include <Standard_ErrorHandler.hxx>
|
|
#include <Standard_Macro.hxx>
|
|
#include <TCollection_AsciiString.hxx>
|
|
#include <TCollection_ExtendedString.hxx>
|
|
|
|
#include <string.h>
|
|
#include <tcl.h>
|
|
#include <fcntl.h>
|
|
#ifndef _WIN32
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
// for capturing of cout and cerr (dup(), dup2())
|
|
#ifdef _WIN32
|
|
#include <io.h>
|
|
#include <sys/stat.h>
|
|
#endif
|
|
|
|
#if !defined(STDOUT_FILENO)
|
|
#define STDOUT_FILENO fileno(stdout)
|
|
#endif
|
|
#if !defined(STDERR_FILENO)
|
|
#define STDERR_FILENO fileno(stderr)
|
|
#endif
|
|
|
|
#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 1)))
|
|
#define TCL_USES_UTF8
|
|
#endif
|
|
|
|
// logging helpers
|
|
namespace
|
|
{
|
|
void dumpArgs(Standard_OStream& os, int argc, const char* argv[])
|
|
{
|
|
for (int i = 0; i < argc; i++)
|
|
os << argv[i] << " ";
|
|
os << std::endl;
|
|
}
|
|
|
|
void flush_standard_streams()
|
|
{
|
|
fflush(stderr);
|
|
fflush(stdout);
|
|
std::cerr << std::flush;
|
|
std::cout << std::flush;
|
|
}
|
|
|
|
int capture_start(int theFDStd, int theFDLog)
|
|
{
|
|
Standard_ASSERT_RETURN(theFDLog >= 0, "Invalid descriptor of log file", -1);
|
|
|
|
// Duplicate a file descriptor of the standard stream to be able to restore output to it later
|
|
int aFDSave = dup(theFDStd);
|
|
if (aFDSave < 0)
|
|
{
|
|
perror("Error capturing standard stream to log: dup() returned");
|
|
return -1;
|
|
}
|
|
|
|
// Redirect the stream to the log file
|
|
if (dup2(theFDLog, theFDStd) < 0)
|
|
{
|
|
close(aFDSave);
|
|
perror("Error capturing standard stream to log: dup2() returned");
|
|
return -1;
|
|
}
|
|
|
|
// remember saved file descriptor of standard stream
|
|
return aFDSave;
|
|
}
|
|
|
|
void capture_end(int theFDStd, int& theFDSave)
|
|
{
|
|
if (theFDSave < 0)
|
|
return;
|
|
|
|
// restore normal descriptors of console stream
|
|
if (dup2(theFDSave, theFDStd) < 0)
|
|
{
|
|
perror("Error returning capturing standard stream to log: dup2() returned");
|
|
return;
|
|
}
|
|
|
|
// close saved file descriptor
|
|
close(theFDSave);
|
|
theFDSave = -1;
|
|
}
|
|
|
|
} // anonymous namespace
|
|
|
|
static Standard_Integer CommandCmd(ClientData theClientData,
|
|
Tcl_Interp* interp,
|
|
Standard_Integer argc,
|
|
const char* argv[])
|
|
{
|
|
Standard_Integer code = TCL_OK;
|
|
Draw_Interpretor::CallBackData* aCallback = (Draw_Interpretor::CallBackData*)theClientData;
|
|
Draw_Interpretor& di = *(aCallback->myDI);
|
|
|
|
// log command execution, except commands manipulating log itself and echo
|
|
Standard_Boolean isLogManipulation =
|
|
(strcmp(argv[0], "dlog") == 0 || strcmp(argv[0], "decho") == 0);
|
|
Standard_Boolean doLog = (di.GetDoLog() && !isLogManipulation);
|
|
Standard_Boolean doEcho = (di.GetDoEcho() && !isLogManipulation);
|
|
|
|
// flush cerr and cout
|
|
flush_standard_streams();
|
|
|
|
// capture cout and cerr to log
|
|
int aFDstdout = STDOUT_FILENO;
|
|
int aFDstderr = STDERR_FILENO;
|
|
int aFDerr_save = -1;
|
|
int aFDout_save = -1;
|
|
if (doLog)
|
|
{
|
|
aFDout_save = capture_start(aFDstdout, di.GetLogFileDescriptor());
|
|
aFDerr_save = capture_start(aFDstderr, di.GetLogFileDescriptor());
|
|
}
|
|
|
|
if (doEcho || doLog)
|
|
dumpArgs(std::cout, argc, argv);
|
|
|
|
// run command
|
|
try
|
|
{
|
|
OCC_CATCH_SIGNALS
|
|
|
|
// get exception if control-break has been pressed
|
|
OSD::ControlBreak();
|
|
|
|
Standard_Integer fres = aCallback->Invoke(di, argc, argv /*anArgs.GetArgv()*/);
|
|
if (fres != 0)
|
|
{
|
|
code = TCL_ERROR;
|
|
}
|
|
}
|
|
catch (Standard_Failure const& anException)
|
|
{
|
|
// fail if Draw_ExitOnCatch is set
|
|
const char* toExitOnCatch = Tcl_GetVar(interp, "Draw_ExitOnCatch", TCL_GLOBAL_ONLY);
|
|
if (toExitOnCatch != NULL && Draw::Atoi(toExitOnCatch))
|
|
{
|
|
Message::SendFail() << "An exception was caught " << anException;
|
|
#ifdef _WIN32
|
|
Tcl_Exit(0);
|
|
#else
|
|
Tcl_Eval(interp, "exit");
|
|
#endif
|
|
}
|
|
|
|
Standard_SStream ss;
|
|
ss << "An exception was caught " << anException << std::ends;
|
|
Tcl_SetResult(interp, (char*)(ss.str().c_str()), TCL_VOLATILE);
|
|
code = TCL_ERROR;
|
|
}
|
|
catch (std::exception const& theStdException)
|
|
{
|
|
const char* toExitOnCatch = Tcl_GetVar(interp, "Draw_ExitOnCatch", TCL_GLOBAL_ONLY);
|
|
if (toExitOnCatch != NULL && Draw::Atoi(toExitOnCatch))
|
|
{
|
|
Message::SendFail() << "An exception was caught " << theStdException.what() << " ["
|
|
<< typeid(theStdException).name() << "]";
|
|
#ifdef _WIN32
|
|
Tcl_Exit(0);
|
|
#else
|
|
Tcl_Eval(interp, "exit");
|
|
#endif
|
|
}
|
|
|
|
Standard_SStream ss;
|
|
ss << "An exception was caught " << theStdException.what() << " ["
|
|
<< typeid(theStdException).name() << "]" << std::ends;
|
|
Tcl_SetResult(interp, (char*)(ss.str().c_str()), TCL_VOLATILE);
|
|
code = TCL_ERROR;
|
|
}
|
|
catch (...)
|
|
{
|
|
const char* toExitOnCatch = Tcl_GetVar(interp, "Draw_ExitOnCatch", TCL_GLOBAL_ONLY);
|
|
if (toExitOnCatch != NULL && Draw::Atoi(toExitOnCatch))
|
|
{
|
|
Message::SendFail() << "UNKNOWN exception was caught ";
|
|
#ifdef _WIN32
|
|
Tcl_Exit(0);
|
|
#else
|
|
Tcl_Eval(interp, "exit");
|
|
#endif
|
|
}
|
|
|
|
Standard_SStream ss;
|
|
ss << "UNKNOWN exception was caught " << std::ends;
|
|
Tcl_SetResult(interp, (char*)(ss.str().c_str()), TCL_VOLATILE);
|
|
code = TCL_ERROR;
|
|
}
|
|
|
|
// log command result
|
|
if (doLog || doEcho)
|
|
{
|
|
const char* aResultStr = Tcl_GetStringResult(interp);
|
|
if (aResultStr != 0 && aResultStr[0] != '\0')
|
|
{
|
|
std::cout << aResultStr << std::endl;
|
|
}
|
|
}
|
|
|
|
// flush streams
|
|
flush_standard_streams();
|
|
|
|
// end capturing cout and cerr
|
|
if (doLog)
|
|
{
|
|
capture_end(aFDstderr, aFDerr_save);
|
|
capture_end(aFDstdout, aFDout_save);
|
|
}
|
|
|
|
return code;
|
|
}
|
|
|
|
static void CommandDelete(ClientData theClientData)
|
|
{
|
|
Draw_Interpretor::CallBackData* aCallback = (Draw_Interpretor::CallBackData*)theClientData;
|
|
delete aCallback;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Draw_Interpretor::Draw_Interpretor()
|
|
: // the tcl interpreter is not created immediately as it is kept
|
|
// by a global variable and created and deleted before the main()
|
|
myInterp(NULL),
|
|
isAllocated(Standard_False),
|
|
myDoLog(Standard_False),
|
|
myDoEcho(Standard_False),
|
|
myToColorize(Standard_True),
|
|
myFDLog(-1)
|
|
{
|
|
//
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Draw_Interpretor::Draw_Interpretor(const Draw_PInterp& theInterp)
|
|
: myInterp(theInterp),
|
|
isAllocated(Standard_False),
|
|
myDoLog(Standard_False),
|
|
myDoEcho(Standard_False),
|
|
myToColorize(Standard_True),
|
|
myFDLog(-1)
|
|
{
|
|
//
|
|
}
|
|
|
|
//=======================================================================
|
|
// function : Init
|
|
// purpose : It is necessary to call this function
|
|
//=======================================================================
|
|
|
|
void Draw_Interpretor::Init()
|
|
{
|
|
if (isAllocated)
|
|
Tcl_DeleteInterp(myInterp);
|
|
isAllocated = Standard_True;
|
|
myInterp = Tcl_CreateInterp();
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Draw_Interpretor::SetToColorize(Standard_Boolean theToColorize)
|
|
{
|
|
myToColorize = theToColorize;
|
|
for (Message_SequenceOfPrinters::Iterator aPrinterIter(Message::DefaultMessenger()->Printers());
|
|
aPrinterIter.More();
|
|
aPrinterIter.Next())
|
|
{
|
|
if (Handle(Message_PrinterOStream) aPrinter =
|
|
Handle(Message_PrinterOStream)::DownCast(aPrinterIter.Value()))
|
|
{
|
|
aPrinter->SetToColorize(theToColorize);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Draw_Interpretor::add(const Standard_CString theCommandName,
|
|
const Standard_CString theHelp,
|
|
const Standard_CString theFileName,
|
|
Draw_Interpretor::CallBackData* theCallback,
|
|
const Standard_CString theGroup)
|
|
{
|
|
Standard_ASSERT_RAISE(myInterp != NULL, "Attempt to add command to Null interpreter");
|
|
|
|
Tcl_CreateCommand(myInterp, theCommandName, CommandCmd, (ClientData)theCallback, CommandDelete);
|
|
|
|
// add the help
|
|
Tcl_SetVar2(myInterp, "Draw_Helps", theCommandName, theHelp, TCL_GLOBAL_ONLY);
|
|
Tcl_SetVar2(myInterp,
|
|
"Draw_Groups",
|
|
theGroup,
|
|
theCommandName,
|
|
TCL_GLOBAL_ONLY | TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
|
|
|
|
// add path to source file (keep not more than two last subdirectories)
|
|
if (theFileName == NULL || *theFileName == '\0')
|
|
{
|
|
return;
|
|
}
|
|
|
|
OSD_Path aPath(theFileName);
|
|
Standard_Integer nbTrek = aPath.TrekLength();
|
|
for (Standard_Integer i = 2; i < nbTrek; ++i)
|
|
{
|
|
aPath.RemoveATrek(1);
|
|
}
|
|
aPath.SetDisk("");
|
|
aPath.SetNode("");
|
|
TCollection_AsciiString aSrcPath;
|
|
aPath.SystemName(aSrcPath);
|
|
if (aSrcPath.Value(1) == '/')
|
|
{
|
|
aSrcPath.Remove(1);
|
|
}
|
|
Tcl_SetVar2(myInterp, "Draw_Files", theCommandName, aSrcPath.ToCString(), TCL_GLOBAL_ONLY);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean Draw_Interpretor::Remove(Standard_CString const n)
|
|
{
|
|
Standard_PCharacter pN;
|
|
//
|
|
pN = (Standard_PCharacter)n;
|
|
|
|
Standard_Integer result = Tcl_DeleteCommand(myInterp, pN);
|
|
return result == 0;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_CString Draw_Interpretor::Result() const
|
|
{
|
|
#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
|
|
return Tcl_GetStringResult(myInterp);
|
|
#else
|
|
return myInterp->result;
|
|
#endif
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Draw_Interpretor::Reset()
|
|
{
|
|
Tcl_ResetResult(myInterp);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Draw_Interpretor& Draw_Interpretor::Append(const Standard_CString s)
|
|
{
|
|
Tcl_AppendResult(myInterp, s, (Standard_CString)0);
|
|
return *this;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Draw_Interpretor& Draw_Interpretor::Append(const TCollection_AsciiString& s)
|
|
{
|
|
return Append(s.ToCString());
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Draw_Interpretor& Draw_Interpretor::Append(const TCollection_ExtendedString& theString)
|
|
{
|
|
#ifdef TCL_USES_UTF8
|
|
// Convert string to UTF-8 format for Tcl
|
|
char* str = new char[theString.LengthOfCString() + 1];
|
|
theString.ToUTF8CString(str);
|
|
Tcl_AppendResult(myInterp, str, (Standard_CString)0);
|
|
delete[] str;
|
|
#else
|
|
// put as ascii string, replacing non-ascii characters by '?'
|
|
TCollection_AsciiString str(theString, '?');
|
|
Tcl_AppendResult(myInterp, str.ToCString(), (Standard_CString)0);
|
|
#endif
|
|
return *this;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Draw_Interpretor& Draw_Interpretor::Append(const Standard_Integer i)
|
|
{
|
|
char c[100];
|
|
Sprintf(c, "%d", i);
|
|
Tcl_AppendResult(myInterp, c, (Standard_CString)0);
|
|
return *this;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Draw_Interpretor& Draw_Interpretor::Append(const Standard_Real r)
|
|
{
|
|
char s[100];
|
|
Sprintf(s, "%.17g", r);
|
|
Tcl_AppendResult(myInterp, s, (Standard_CString)0);
|
|
return *this;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Draw_Interpretor& Draw_Interpretor::Append(const Standard_SStream& s)
|
|
{
|
|
return Append(s.str().c_str());
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Draw_Interpretor::AppendElement(const Standard_CString s)
|
|
{
|
|
Tcl_AppendElement(myInterp, s);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer Draw_Interpretor::Eval(const Standard_CString line)
|
|
{
|
|
return Tcl_Eval(myInterp, line);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer Draw_Interpretor::RecordAndEval(const Standard_CString line,
|
|
const Standard_Integer flags)
|
|
{
|
|
return Tcl_RecordAndEval(myInterp, line, flags);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer Draw_Interpretor::EvalFile(const Standard_CString fname)
|
|
{
|
|
return Tcl_EvalFile(myInterp, fname);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Integer Draw_Interpretor::PrintHelp(const Standard_CString theCommandName)
|
|
{
|
|
TCollection_AsciiString aCmd = TCollection_AsciiString("help ") + theCommandName;
|
|
Standard_PCharacter aLinePtr = (Standard_PCharacter)aCmd.ToCString();
|
|
return Tcl_Eval(myInterp, aLinePtr);
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Standard_Boolean Draw_Interpretor::Complete(const Standard_CString line)
|
|
{
|
|
Standard_PCharacter pLine;
|
|
//
|
|
pLine = (Standard_PCharacter)line;
|
|
return Tcl_CommandComplete(pLine) != 0;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Draw_Interpretor::~Draw_Interpretor()
|
|
{
|
|
SetDoLog(Standard_False);
|
|
if (myFDLog >= 0)
|
|
{
|
|
close(myFDLog);
|
|
myFDLog = 0;
|
|
}
|
|
|
|
// MKV 01.02.05
|
|
#if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)))
|
|
try
|
|
{
|
|
OCC_CATCH_SIGNALS
|
|
Tcl_Exit(0);
|
|
}
|
|
catch (Standard_Failure const&)
|
|
{
|
|
#ifdef OCCT_DEBUG
|
|
std::cout << "Tcl_Exit have an exception" << std::endl;
|
|
#endif
|
|
}
|
|
#else
|
|
#ifdef _WIN32
|
|
Tcl_Exit(0);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
Draw_PInterp Draw_Interpretor::Interp() const
|
|
{
|
|
Standard_DomainError_Raise_if(myInterp == NULL, "No call for Draw_Interpretor::Init()");
|
|
return myInterp;
|
|
}
|
|
|
|
void Draw_Interpretor::Set(const Draw_PInterp& PIntrp)
|
|
{
|
|
if (isAllocated)
|
|
Tcl_DeleteInterp(myInterp);
|
|
isAllocated = Standard_False;
|
|
myInterp = PIntrp;
|
|
}
|
|
|
|
//=================================================================================================
|
|
|
|
void Draw_Interpretor::SetDoLog(Standard_Boolean doLog)
|
|
{
|
|
if (myDoLog == doLog)
|
|
return;
|
|
|
|
// create log file if not opened yet
|
|
if (doLog && myFDLog < 0)
|
|
{
|
|
#ifdef _WIN32
|
|
char tmpfile[L_tmpnam + 1];
|
|
tmpnam(tmpfile);
|
|
myFDLog = open(tmpfile, O_RDWR | O_CREAT | O_EXCL | O_TEMPORARY, S_IREAD | S_IWRITE);
|
|
#else
|
|
// according to Linux Filesystem Hierarchy Standard, 3.17,
|
|
// /tmp/ is the right directory for temporary files
|
|
char tmpfile[256] = "/tmp/occt_draw_XXXXXX";
|
|
myFDLog = mkstemp(tmpfile);
|
|
if (myFDLog >= 0)
|
|
{
|
|
// printf ("Tmp file: %s\n", tmpfile);
|
|
unlink(tmpfile); // make sure the file will be deleted on close
|
|
}
|
|
#endif
|
|
if (myFDLog < 0)
|
|
{
|
|
perror("Error creating temporary file for capturing console output");
|
|
printf("path: %s\n", tmpfile);
|
|
return;
|
|
}
|
|
}
|
|
|
|
myDoLog = doLog;
|
|
}
|
|
|
|
void Draw_Interpretor::SetDoEcho(Standard_Boolean doEcho)
|
|
{
|
|
myDoEcho = doEcho;
|
|
}
|
|
|
|
Standard_Boolean Draw_Interpretor::GetDoLog() const
|
|
{
|
|
return myDoLog;
|
|
}
|
|
|
|
Standard_Boolean Draw_Interpretor::GetDoEcho() const
|
|
{
|
|
return myDoEcho;
|
|
}
|
|
|
|
void Draw_Interpretor::ResetLog()
|
|
{
|
|
if (myFDLog < 0)
|
|
return;
|
|
|
|
// flush cerr and cout, for the case if they are bound to the log
|
|
flush_standard_streams();
|
|
|
|
lseek(myFDLog, 0, SEEK_SET);
|
|
|
|
#ifdef _WIN32
|
|
if (_chsize_s(myFDLog, 0) != 0)
|
|
#else
|
|
if (ftruncate(myFDLog, 0) != 0)
|
|
#endif
|
|
{
|
|
perror("Error truncating the console log");
|
|
}
|
|
}
|
|
|
|
void Draw_Interpretor::AddLog(const Standard_CString theStr)
|
|
{
|
|
if (myFDLog < 0 || !theStr || !theStr[0])
|
|
return;
|
|
|
|
// flush cerr and cout, for the case if they are bound to the log
|
|
flush_standard_streams();
|
|
|
|
// write as plain bytes
|
|
if (write(myFDLog, theStr, (unsigned int)strlen(theStr)) < 0)
|
|
{
|
|
perror("Error writing to console log");
|
|
}
|
|
}
|
|
|
|
TCollection_AsciiString Draw_Interpretor::GetLog()
|
|
{
|
|
TCollection_AsciiString aLog;
|
|
if (myFDLog < 0)
|
|
return aLog;
|
|
|
|
// flush cerr and cout
|
|
flush_standard_streams();
|
|
|
|
// rewind the file to its start
|
|
lseek(myFDLog, 0, SEEK_SET);
|
|
|
|
// read the whole log to string; this implementation
|
|
// is not optimized but should be sufficient
|
|
const int BUFSIZE = 4096;
|
|
char buffer[BUFSIZE + 1];
|
|
for (;;)
|
|
{
|
|
int nbRead = (int)read(myFDLog, buffer, BUFSIZE);
|
|
if (nbRead <= 0)
|
|
{
|
|
break;
|
|
}
|
|
buffer[nbRead] = '\0';
|
|
aLog.AssignCat(buffer);
|
|
}
|
|
|
|
return aLog;
|
|
}
|