Index: src/Fragmentation/Automation/Jobs/FragmentJob.cpp
===================================================================
--- src/Fragmentation/Automation/Jobs/FragmentJob.cpp	(revision 7670865494307829aa075e60d6056fe423885484)
+++ src/Fragmentation/Automation/Jobs/FragmentJob.cpp	(revision d920b9e35d1332c01a14e561aa60b85bbe881b3b)
@@ -20,11 +20,4 @@
 #include "CodePatterns/MemDebug.hpp"
 
-#include <cstdlib>
-#include <fstream>
-#include <string>
-
-#include "CodePatterns/Info.hpp"
-#include "CodePatterns/Log.hpp"
-#include "CodePatterns/toString.hpp"
 #include "FragmentJob.hpp"
 #include "Results/FragmentResult.hpp"
@@ -34,18 +27,13 @@
  */
 FragmentJob::FragmentJob() :
-  JobId(-1),
-  outputfile("")
+  JobId(JobId::IllegalJob)
 {}
 
 /** Constructor for class FragmentJob.
  *
- * \param _command command to execute
- * \param _outputfile configuration file for solver
  * \param _JobId unique id of this job
  */
-FragmentJob::FragmentJob(const std::string &_command, const std::string &_outputfile, const JobId_t _JobId) :
-  JobId(_JobId),
-  command(_command),
-  outputfile(_outputfile)
+FragmentJob::FragmentJob(const JobId_t _JobId) :
+  JobId(_JobId)
 {}
 
@@ -56,42 +44,4 @@
 {}
 
-/** Work routine of this FragmentJob.
- *
- * This function encapsulates all the work that has to be done to generate
- * a FragmentResult. Hence, the FragmentWorker does not need to know anything
- * about the operation: it just receives it and executes this function.
- *
- * \return result of this job
- */
-FragmentResult::ptr FragmentJob::Work()
-{
-  Info info((std::string(__FUNCTION__)+std::string(", id #")+toString(getId())).c_str());
-  FragmentResult::ptr s( new FragmentResult(getId()) );
-
-  // write outputfile to file
-  std::string inputfilename =
-      std::string("/tmp/dummy_")
-      +toString(getId());
-  std::string outputfilename = inputfilename+std::string(".out");
-  inputfilename += std::string(".dat");
-  std::ofstream output(outputfilename.c_str());
-  output << outputfile << std::endl;
-  output.close();
-
-  // fork into subprocess and launch command
-  s->exitflag = std::system((command+std::string(" ")+inputfilename
-                        +std::string(" >")+outputfilename).c_str());
-  std::ifstream resultfile;
-  resultfile.open(outputfilename.c_str(), ifstream::in);
-  char line[1024];
-  while (resultfile.good()) {
-    resultfile.getline(line, 1023);
-    s->result += line;
-  }
-  resultfile.close();
-
-  return s;
-}
-
 /** Comparator for class FragmentJob.
  * \param other instance to compare to
@@ -100,6 +50,4 @@
 bool FragmentJob::operator==(const FragmentJob &other) const
 {
-  return (command == other.command)
-      && (outputfile == other.outputfile)
-      && (getId() == other.getId());
+  return (getId() == other.getId());
 }
Index: src/Fragmentation/Automation/Jobs/FragmentJob.hpp
===================================================================
--- src/Fragmentation/Automation/Jobs/FragmentJob.hpp	(revision 7670865494307829aa075e60d6056fe423885484)
+++ src/Fragmentation/Automation/Jobs/FragmentJob.hpp	(revision d920b9e35d1332c01a14e561aa60b85bbe881b3b)
@@ -43,9 +43,8 @@
   typedef boost::shared_ptr<FragmentJob> ptr;
 
-  FragmentJob();
-  FragmentJob(const std::string &_command, const std::string &_outputfile, const JobId_t _JobId);
+  FragmentJob(const JobId_t _JobId);
   ~FragmentJob();
 
-  FragmentResult::ptr Work();
+  virtual FragmentResult::ptr Work() = 0;
 
   bool operator==(const FragmentJob &other) const;
@@ -55,11 +54,12 @@
   }
 
-  //!> string containing the command to launch the solver
-  std::string command;
+private:
+  /** private default cstor for serialization only
+   *
+   * Use normal cstor with JobId::IllegalJob if you want to instantiate
+   * a job without id.
+   */
+  FragmentJob();
 
-  //!> string containing the configuration file for the solver
-  std::string outputfile;
-
-private:
   friend class boost::serialization::access;
   // serialization
@@ -68,6 +68,4 @@
   {
     ar & boost::serialization::base_object<JobId>(*this);
-    ar & command;
-    ar & outputfile;
   }
 };
Index: src/Fragmentation/Automation/Jobs/SystemCommandJob.cpp
===================================================================
--- src/Fragmentation/Automation/Jobs/SystemCommandJob.cpp	(revision d920b9e35d1332c01a14e561aa60b85bbe881b3b)
+++ src/Fragmentation/Automation/Jobs/SystemCommandJob.cpp	(revision d920b9e35d1332c01a14e561aa60b85bbe881b3b)
@@ -0,0 +1,163 @@
+/*
+ * Project: MoleCuilder
+ * Description: creates and alters molecular systems
+ * Copyright (C)  2010 University of Bonn. All rights reserved.
+ * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
+ */
+
+/*
+ * SystemCommandJob.cpp
+ *
+ *  Created on: Feb 5, 2012
+ *      Author: heber
+ */
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/iostreams/stream.hpp>
+
+#include "CodePatterns/MemDebug.hpp"
+
+// include headers that implement a archive in simple text format
+// otherwise BOOST_CLASS_EXPORT_IMPLEMENT has no effect
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/archive/text_iarchive.hpp>
+
+#include "SystemCommandJob.hpp"
+
+#include <cstdio>
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <streambuf>
+#include <boost/filesystem.hpp>
+
+
+#include "CodePatterns/Info.hpp"
+#include "CodePatterns/Log.hpp"
+#include "CodePatterns/toString.hpp"
+
+/** Constructor for class SystemCommandJob.
+ *
+ */
+SystemCommandJob::SystemCommandJob() :
+  FragmentJob(JobId::IllegalJob)
+{}
+
+/** Constructor for class SystemCommandJob.
+ *
+ * \param _command command to execute
+ * \param _outputfile configuration file for solver
+ * \param _JobId unique id of this job
+ */
+SystemCommandJob::SystemCommandJob(const std::string &_command, const std::string &_outputfile, const JobId_t _JobId) :
+  FragmentJob(_JobId),
+  command(_command),
+  outputfile(_outputfile)
+{}
+
+/** Destructor for class SystemCommandJob.
+ *
+ */
+SystemCommandJob::~SystemCommandJob()
+{}
+
+/** Work routine of this SystemCommandJob.
+ *
+ * This function encapsulates all the work that has to be done to generate
+ * a FragmentResult. Hence, the FragmentWorker does not need to know anything
+ * about the operation: it just receives it and executes this function.
+ *
+ * We obtain FragmentResult::exitflag from std::system's return value and
+ * FragmentResult::result from the contents of the piped output file.
+ *
+ * \return result of this job
+ */
+FragmentResult::ptr SystemCommandJob::Work()
+{
+  Info info((std::string(__FUNCTION__)+std::string(", id #")+toString(getId())).c_str());
+
+  // the following is taken from http://stackoverflow.com/questions/2746168/how-to-construct-a-c-fstream-from-a-posix-file-descriptor
+  char tmpTemplate[24];
+  strncpy(tmpTemplate, "/tmp/XXXXXX_", 14);
+  const std::string idstring(toString(getId()));
+  const size_t idlength = idstring.length();
+  ASSERT(idlength <= 8,
+    "SystemCommandJob::Work() - the id contains more than 8 digits.");
+  strcat(tmpTemplate, toString(getId()).c_str());
+  mkstemps(tmpTemplate, idlength+1);
+
+  // write outputfile to temporary file
+  LOG(2, "DEBUG: Temporary file is " << tmpTemplate << ".");
+  std::ofstream output(tmpTemplate);
+  ASSERT(output.is_open(),
+    "SystemCommandJob::Work() - the temporary file could not be opened.");
+  output << outputfile << std::endl;
+
+  // fork into subprocess and launch command
+  std::string command_args = command+std::string(" ")+tmpTemplate;
+  LOG(1, "INFO: Executing '" << command_args << "'.");
+  FILE *stdoutstream = popen(command_args.c_str(), "r");
+  FragmentResult::ptr s;
+  {
+    boost::iostreams::stream<boost::iostreams::file_descriptor_source> stdoutfile(fileno(stdoutstream), boost::iostreams::never_close_handle);
+    stdoutfile.set_auto_close(false); // https://svn.boost.org/trac/boost/ticket/3517
+    std::istreambuf_iterator<char> beginiter = (std::istreambuf_iterator<char>(stdoutfile));
+    std::string resultstring( beginiter, std::istreambuf_iterator<char>());
+    // construct result
+    LOG(2, "DEBUG: First 50 characters of output: " << resultstring.substr(0,50));
+    s = extractResult(resultstring);
+  }
+  const int exitflag = pclose(stdoutstream);
+  if (exitflag != 0)
+    ELOG(1, "Job " << getId() << " failed on executing: " << command_args);
+  s->exitflag = exitflag;
+
+  // close temporary file and remove it
+  output.close();
+  boost::filesystem::path tmpPath(tmpTemplate);
+  if (boost::filesystem::exists(boost::filesystem::status(tmpPath))) {
+    LOG(2, "DEBUG: Removing " << tmpPath.string());
+    boost::filesystem::remove(tmpPath);
+  }
+
+  // return result
+  return s;
+}
+
+/** Default function for result extraction is just copy.
+ *
+ * @param resultstring output of system command
+ * @return copy of \a resultstring
+ */
+FragmentResult::ptr SystemCommandJob::extractResult(const std::string &resultstring)
+{
+  return FragmentResult::ptr (new FragmentResult(getId(), resultstring) );
+}
+
+
+/** Comparator for class SystemCommandJob.
+ * \param other instance to compare to
+ * \return every member variable is the same, else - is not
+ */
+bool SystemCommandJob::operator==(const SystemCommandJob &other) const
+{
+  if (command != other.command) {
+    LOG(1, "INFO: command's of two SystemCommandJobs differ: " << command << " != " << other.command << ".");
+    return false;
+  }
+  if (outputfile != other.outputfile) {
+    LOG(1, "INFO: outputfile's of two SystemCommandJobs differ: " << outputfile << " != " << other.outputfile << ".");
+    return false;
+  }
+  return (dynamic_cast<const FragmentJob &>(*this) == dynamic_cast<const FragmentJob &>(other));
+}
+
+// we need to explicitly instantiate the serialization functions as
+// its is only serialized through its base class FragmentJob
+BOOST_CLASS_EXPORT_IMPLEMENT(SystemCommandJob)
Index: src/Fragmentation/Automation/Jobs/SystemCommandJob.hpp
===================================================================
--- src/Fragmentation/Automation/Jobs/SystemCommandJob.hpp	(revision d920b9e35d1332c01a14e561aa60b85bbe881b3b)
+++ src/Fragmentation/Automation/Jobs/SystemCommandJob.hpp	(revision d920b9e35d1332c01a14e561aa60b85bbe881b3b)
@@ -0,0 +1,78 @@
+/*
+ * SystemCommandJob.hpp
+ *
+ *  Created on: Feb 5, 2011
+ *      Author: heber
+ */
+
+#ifndef SYSTEMCOMMANDJOB_HPP_
+#define SYSTEMCOMMANDJOB_HPP_
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <boost/serialization/export.hpp>
+
+#include <string>
+
+#include "Jobs/FragmentJob.hpp"
+
+class SystemCommandJobTest;
+
+/** SystemCommandJob is an extension of FragmentJob that executes a system
+ * command operating onto a specific outputfile.
+ *
+ * Implement extractResult() to get the desired result from the captured
+ * output of the system command.
+ *
+ * Important is that this class is fully serializable such that it can be
+ * transfered to a scheduler (server) and be deserialized by the Worker.
+ */
+class SystemCommandJob : public FragmentJob
+{
+  //!> grant unit test access
+  friend class SystemCommandJobTest;
+public:
+  SystemCommandJob(const std::string &_command, const std::string &_outputfile, const JobId_t _JobId);
+  ~SystemCommandJob();
+
+  FragmentResult::ptr Work();
+
+  bool operator==(const SystemCommandJob &other) const;
+
+  bool operator!=(const SystemCommandJob &other) const {
+    return !(*this == other);
+  }
+
+private:
+  virtual FragmentResult::ptr extractResult(const std::string &resultstring);
+
+  //!> string containing the command to launch the solver
+  std::string command;
+
+  //!> string containing the configuration file for the solver
+  std::string outputfile;
+
+protected:
+  //!> private default cstor for serialization only
+  SystemCommandJob();
+
+private:
+  friend class boost::serialization::access;
+  // serialization
+  template <typename Archive>
+  void serialize(Archive& ar, const unsigned int version)
+  {
+    ar & boost::serialization::base_object<FragmentJob>(*this);
+    ar & command;
+    ar & outputfile;
+  }
+};
+
+// we need to give this class a unique key for serialization
+// its is only serialized through its base class FragmentJob
+BOOST_CLASS_EXPORT_KEY(SystemCommandJob)
+
+#endif /* SYSTEMCOMMANDJOB_HPP_ */
