diff --git a/applications/test/cstring/Make/files b/applications/test/cstring/Make/files new file mode 100644 index 0000000000..eb7e33dc8b --- /dev/null +++ b/applications/test/cstring/Make/files @@ -0,0 +1,3 @@ +Test-cstring.C + +EXE = $(FOAM_USER_APPBIN)/Test-cstring diff --git a/applications/test/cstring/Make/options b/applications/test/cstring/Make/options new file mode 100644 index 0000000000..6a9e9810b3 --- /dev/null +++ b/applications/test/cstring/Make/options @@ -0,0 +1,2 @@ +/* EXE_INC = -I$(LIB_SRC)/cfdTools/include */ +/* EXE_LIBS = -lfiniteVolume */ diff --git a/applications/test/cstring/Test-cstring.C b/applications/test/cstring/Test-cstring.C new file mode 100644 index 0000000000..fc4605cfa4 --- /dev/null +++ b/applications/test/cstring/Test-cstring.C @@ -0,0 +1,99 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Description + Test some string functionality + +\*---------------------------------------------------------------------------*/ + +#include "CStringList.H" +#include "DynamicList.H" +#include "IOstreams.H" +#include "fileNameList.H" +#include "stringList.H" +#include "wordList.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int print(int argc, char *argv[]) +{ + Info<< "argc=" << argc << endl; + for (int i=0; i dynlst; + dynlst.reserve(16); + + dynlst.append("string1 with content"); + dynlst.append("string2 other content"); + dynlst.append("string3 done"); + + { + CStringList inC(dynlst); + + Info<< "input: " << dynlst << endl; + print(inC); + } + + Info<<"command-line with " << CStringList::count(argv) << " items"<< endl; + + print(argc, argv); + { + dynlst.clear(); + for (int i=0; i cmd(3); + cmd.append("objToVTK"); + cmd.append(fName); + cmd.append(fName.lessExt() + ".vtk"); + + Pout<< "cmd: objToVTK " << fName.c_str() << endl; + Foam::system(cmd); } diff --git a/src/OSspecific/POSIX/POSIX.C b/src/OSspecific/POSIX/POSIX.C index 41645bf736..a9d19eecce 100644 --- a/src/OSspecific/POSIX/POSIX.C +++ b/src/OSspecific/POSIX/POSIX.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -38,6 +38,8 @@ Description #include "timer.H" #include "IFstream.H" #include "DynamicList.H" +#include "CStringList.H" +#include "SubList.H" #include #include @@ -49,6 +51,7 @@ Description #include #include #include +#include #include #include #include @@ -1210,9 +1213,153 @@ bool Foam::ping(const string& hostname, const label timeOut) } +namespace Foam +{ +//! \cond fileScope +static int waitpid(const pid_t pid) +{ + // child status, return code from the exec etc. + int status = 0; + + // in parent - blocking wait + // modest treatment of signals (in child) + // treat 'stopped' like exit (suspend/continue) + while (true) + { + pid_t wpid = ::waitpid(pid, &status, WUNTRACED); + + if (wpid == -1) + { + FatalErrorInFunction + << "some error occurred in child" + << exit(FatalError); + break; + } + + if (WIFEXITED(status)) + { + // child exited, get its return status + return WEXITSTATUS(status); + } + + if (WIFSIGNALED(status)) + { + // child terminated by some signal + return WTERMSIG(status); + } + + if (WIFSTOPPED(status)) + { + // child stopped by some signal + return WSTOPSIG(status); + } + + FatalErrorInFunction + << "programming error, status from waitpid() not handled: " + << status + << exit(FatalError); + } + + return -1; // should not happen +} +//! \endcond +} + + int Foam::system(const std::string& command) { - return ::system(command.c_str()); + if (command.empty()) + { + // Treat an empty command as a successful no-op. + // From 'man sh' POSIX (man sh): + // "If the command_string operand is an empty string, + // sh shall exit with a zero exit status." + return 0; + } + + pid_t child_pid = ::vfork(); // NB: vfork, not fork! + if (child_pid == -1) + { + FatalErrorInFunction + << "vfork() failed for system command " << command + << exit(FatalError); + } + + if (child_pid == 0) + { + // in child + + // execl uses the current environ + (void) ::execl + ( + "/bin/sh", // Path of the shell + "sh", // Command-name (name for the shell) + "-c", // Read commands from the command_string operand. + command.c_str(), // Command string + reinterpret_cast(0) + ); + + // obviously failed, since exec should not return at all + FatalErrorInFunction + << "exec failed: " << command + << exit(FatalError); + } + + + // in parent - blocking wait + return waitpid(child_pid); +} + + +int Foam::system(const Foam::UList& command) +{ + const int argc = command.size(); + + if (!argc) + { + // Treat an empty command as a successful no-op. + // For consistency with POSIX (man sh) behaviour for (sh -c command), + // which is what is mostly being replicated here. + return 0; + } + + // NB: use vfork, not fork! + // vfork behaves more like a thread and avoids copy-on-write problems + // triggered by fork. + // The normal system() command has a fork buried in it that causes + // issues with infiniband and openmpi etc. + pid_t child_pid = ::vfork(); + if (child_pid == -1) + { + FatalErrorInFunction + << "vfork() failed for system command " << command[0] + << exit(FatalError); + } + + if (child_pid == 0) + { + // in child: + // Need command and arguments separately. + // args is a NULL-terminated list of c-strings + + CStringList args(SubList(command, 0)); + if (argc > 1) + { + args.reset(SubList(command, argc-1, 1)); + } + + // execvp uses the current environ + (void) ::execvp(command[0].c_str(), args.strings()); + + // obviously failed, since exec should not return at all + FatalErrorInFunction + << "exec(" << command[0] << ", ...) failed" + << exit(FatalError); + } + + + // in parent - blocking wait + return waitpid(child_pid); } diff --git a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C index 04932fceea..19882241e3 100644 --- a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C +++ b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -493,10 +493,17 @@ bool Foam::dynamicCode::copyOrCreateFiles(const bool verbose) const bool Foam::dynamicCode::wmakeLibso() const { - const Foam::string wmakeCmd("wmake -s libso " + this->codePath()); - Info<< "Invoking " << wmakeCmd << endl; + DynamicList cmd(4); + cmd.append("wmake"); + cmd.append("-s"); + cmd.append("libso"); + cmd.append(this->codePath()); - if (Foam::system(wmakeCmd)) + // NOTE: could also resolve wmake command explicitly + // cmd[0] = stringOps::expand("$WM_PROJECT_DIR/wmake/wmake"); + + Info<< "Invoking wmake libso " << this->codePath().c_str() << endl; + if (Foam::system(cmd)) { return false; } diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C index 5d391afaaf..8f489589b0 100644 --- a/src/OpenFOAM/global/argList/argList.C +++ b/src/OpenFOAM/global/argList/argList.C @@ -1170,7 +1170,7 @@ void Foam::argList::displayDoc(bool source) const Info<< "Show documentation: " << docBrowser.c_str() << endl; - system(docBrowser); + Foam::system(docBrowser); } else { diff --git a/src/OpenFOAM/include/OSspecific.H b/src/OpenFOAM/include/OSspecific.H index 79a2417319..e974192cec 100644 --- a/src/OpenFOAM/include/OSspecific.H +++ b/src/OpenFOAM/include/OSspecific.H @@ -37,6 +37,7 @@ SourceFiles #define OSspecific_H #include "fileNameList.H" +#include "stringList.H" #include @@ -209,9 +210,15 @@ bool ping(const string&, const label port, const label timeOut); //- Check if machine is up by pinging port 22 (ssh) and 222 (rsh) bool ping(const string&, const label timeOut=10); -//- Execute the specified command +//- Execute the specified command via the shell. +// Uses vfork/execl internally. +// Where possible, use the list version instead. int system(const std::string& command); +//- Execute the specified command with arguments. +// Uses vfork/execvp internally +int system(const UList& command); + //- Open a shared library. Return handle to library. Print error message // if library cannot be loaded (check = true) void* dlOpen(const fileName& lib, const bool check = true); diff --git a/src/OpenFOAM/primitives/strings/lists/CStringList.H b/src/OpenFOAM/primitives/strings/lists/CStringList.H new file mode 100644 index 0000000000..c90ebcb337 --- /dev/null +++ b/src/OpenFOAM/primitives/strings/lists/CStringList.H @@ -0,0 +1,175 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Class + Foam::CStringList + +Description + An adapter for copying a list of C++ strings into a list of C-style + strings for passing to C code that expects argc/argv parameters. + + In addition to providing a C-compatible list of C-strings, + the string lists are flattened into a single string of data that can be + also be passed en mass. + + Example use: + \code + wordList myStrings; ... + CStringList cstr(myStrings); + + // pass as argc, argv: + someMain(cstr.size(), cstr.strings()); + + // access the raw characters: + os.write(cstr.data(), cstr.length()); + \endcode + +\*---------------------------------------------------------------------------*/ + +#ifndef CStringList_H +#define CStringList_H + +#include "fileNameList.H" +#include "stringList.H" +#include "wordList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class CStringList Declaration +\*---------------------------------------------------------------------------*/ + +class CStringList +{ + // Private data + + //- Number of strings + int argc_; + + //- Overall length of the raw content + // Does not include the final nul-character + size_t len_; + + //- List of strings, including trailing NULL pointer + char** argv_; + + //- Flattened content with interspersed nul-characters + char* data_; + + + // Private Member Functions + + //- Disallow default bitwise copy construct + CStringList(const CStringList&) = delete; + + //- Disallow default bitwise assignment + void operator=(const CStringList&) = delete; + + +public: + + // Constructors + + //- Construct empty, adding content later (via reset). + inline CStringList(); + + + //- Construct from a list of strings + // Copies the input characters. + template + CStringList(const UList& input); + + + //- Destructor + inline ~CStringList(); + + + // Public Members + + //- Count the number of parameters until the first NULL pointer. + // Return 0 if argv is NULL. + static inline int count(const char * const argv[]); + + + // Access + + //- Return the number of C-strings (ie, argc) + inline int size() const; + + //- Return the list of C-strings (ie, argv) + // The position at argc is a NULL pointer + inline char** strings() const; + + + //- Overall length of the flattened character (data) content + inline size_t length() const; + + //- The flattened character content, with interspersed nul-chars + inline char* data() const; + + + // Edit + + //- Clear contents and free memory + inline void clear(); + + //- Copy the input list of strings. + template + void reset(const UList& input); + + + // Other + + //- Create a list from argc/argv parameters. + // A null pointer for argv is permissible when argc is zero. + template + static List asList(int argc, const char * const argv[]); + + //- Create a list from a NULL-terminated list of argv parameters. + // A null pointer for argv is permissible. + template + static inline List asList(const char * const argv[]); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "CStringListI.H" + +#ifdef NoRepository +# include "CStringListTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/primitives/strings/lists/CStringListI.H b/src/OpenFOAM/primitives/strings/lists/CStringListI.H new file mode 100644 index 0000000000..d91a9de646 --- /dev/null +++ b/src/OpenFOAM/primitives/strings/lists/CStringListI.H @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * // + +inline int Foam::CStringList::count(const char * const argv[]) +{ + int nElem = 0; + if (argv) + { + while (argv[nElem]) + { + ++nElem; + } + } + + return nElem; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +inline Foam::CStringList::CStringList() +: + argc_(0), + len_(0), + argv_(0), + data_(0) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +inline Foam::CStringList::~CStringList() +{ + clear(); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline void Foam::CStringList::clear() +{ + argc_ = 0; + len_ = 0; + + if (data_) + { + delete[] data_; + data_ = 0; + } + if (argv_) + { + delete[] argv_; + argv_ = 0; + } +} + + +inline int Foam::CStringList::size() const +{ + return argc_; +} + + +inline size_t Foam::CStringList::length() const +{ + return len_; +} + + +inline char** Foam::CStringList::strings() const +{ + return argv_; +} + + +inline char* Foam::CStringList::data() const +{ + return data_; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/primitives/strings/lists/CStringListTemplates.C b/src/OpenFOAM/primitives/strings/lists/CStringListTemplates.C new file mode 100644 index 0000000000..db0bb2e2ff --- /dev/null +++ b/src/OpenFOAM/primitives/strings/lists/CStringListTemplates.C @@ -0,0 +1,115 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template +Foam::CStringList::CStringList +( + const UList& input +) +: + argc_(0), + len_(0), + argv_(0), + data_(0) +{ + reset(input); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template +void Foam::CStringList::reset +( + const UList& input +) +{ + clear(); + + argc_ = input.size(); + forAll(input, argI) + { + len_ += input[argI].size(); + ++len_; // nul terminator for C-strings + } + + argv_ = new char*[argc_+1]; + argv_[argc_] = NULL; // extra terminator + + if (argc_ > 0) + { + // allocation includes final nul terminator, + // but overall count does not + data_ = new char[len_--]; + + char* ptr = data_; + forAll(input, argI) + { + argv_[argI] = ptr; + + const std::string& str = + static_cast(input[argI]); + + for + ( + std::string::const_iterator iter = str.begin(); + iter != str.end(); + ++iter + ) + { + *(ptr++) = *iter; + } + *(ptr++) = '\0'; + } + } +} + + +template +Foam::List +Foam::CStringList::asList(int argc, const char * const argv[]) +{ + List lst(argc); + + for (int i=0; i < argc; ++i) + { + lst[i] = argv[i]; + } + + return lst; +} + + +template +Foam::List +Foam::CStringList::asList(const char * const argv[]) +{ + return asList(count(argv), argv); +} + + +// ************************************************************************* // diff --git a/src/postProcessing/functionObjects/systemCall/controlDict b/src/postProcessing/functionObjects/systemCall/controlDict index ff192e197c..124c5406b9 100644 --- a/src/postProcessing/functionObjects/systemCall/controlDict +++ b/src/postProcessing/functionObjects/systemCall/controlDict @@ -62,14 +62,15 @@ functions // called at the end of the run endCalls ( - "echo \*\*\* writing .bashrc \*\*\*" - "cat ~/.bashrc" - "echo \*\*\* done \*\*\*" + // Note: single quotes to avoid shell expansion + "echo '*** listing ~/.bashrc ***'" + "cat ~/.bashrc; echo '*** done ***'" ); - // called every ouput time + // called every output time writeCalls ( + // Note: can also backslash to escape shell meta-characters "echo \*\*\* writing data \*\*\*" ); } diff --git a/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.C b/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.C index 6188b29468..d162635f34 100644 --- a/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.C +++ b/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -62,9 +62,15 @@ void Foam::faceShading::writeRays vertI++; str << "l " << vertI-1 << ' ' << vertI << nl; } - string cmd("objToVTK " + fName + " " + fName.lessExt() + ".vtk"); - Pout<< "cmd:" << cmd << endl; - system(cmd); + str.flush(); + + DynamicList cmd(3); + cmd.append("objToVTK"); + cmd.append(fName); + cmd.append(fName.lessExt() + ".vtk"); + + Pout<< "cmd: objToVTK " << fName.c_str() << endl; + Foam::system(cmd); }