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);
}