Index: src/Fragmentation/Automation/Makefile.am
===================================================================
--- src/Fragmentation/Automation/Makefile.am	(revision 267b8daa521f5d13c38827367820abbe54d9da41)
+++ src/Fragmentation/Automation/Makefile.am	(revision af9b9fff30a59d026e6a6f323b457bfda82ed6df)
@@ -147,4 +147,5 @@
   $(BOOST_ASIO_LIBS) \
   $(BOOST_SERIALIZATION_LIBS) \
+  $(BOOST_PROGRAM_OPTIONS_LIBS) \
   $(BOOST_THREAD_LIBS) \
   $(BOOST_SYSTEM_LIBS) \
Index: src/Fragmentation/Automation/controller.cpp
===================================================================
--- src/Fragmentation/Automation/controller.cpp	(revision 267b8daa521f5d13c38827367820abbe54d9da41)
+++ src/Fragmentation/Automation/controller.cpp	(revision af9b9fff30a59d026e6a6f323b457bfda82ed6df)
@@ -29,4 +29,5 @@
 #include <boost/archive/text_oarchive.hpp>
 #include <boost/archive/text_iarchive.hpp>
+#include <boost/program_options.hpp>
 #include <fstream>
 #include <iostream>
@@ -324,17 +325,100 @@
   CommandsMap.insert( std::make_pair("removeall", RemoveAllIndex) );
   CommandsMap.insert( std::make_pair("shutdown", ShutdownIndex) );
+  std::vector<std::string> Commands;
+  for (CommandsMap_t::const_iterator iter = CommandsMap.begin(); iter != CommandsMap.end(); ++iter)
+    Commands.push_back(iter->first);
+
+  // Declare the supported options.
+  boost::program_options::options_description desc("Allowed options");
+  desc.add_options()
+      ("help,h", "produce help message")
+      ("verbosity,v", boost::program_options::value<size_t>(), "set verbosity level")
+      ("server", boost::program_options::value< std::string >(), "connect to server at this address (host:port)")
+      ("command", boost::program_options::value< std::string >(), (std::string("command to send to server: ")+toString(Commands)).c_str())
+      ("executable", boost::program_options::value< std::string >(), "executable for commands 'addjobs' and 'createjobs'")
+      ("fragment-path", boost::program_options::value< std::string >(), "path to fragment files for 'receivempqcresults'")
+      ("jobcommand", boost::program_options::value< std::string >(), "command argument for executable for 'createjobs'")
+      ("jobfiles", boost::program_options::value< std::vector< std::string > >()->multitoken(), "list of files as single argument to executable for 'addjobs'")
+  ;
+
+  boost::program_options::variables_map vm;
+  boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
+  boost::program_options::notify(vm);
+
+  if (vm.count("help")) {
+    std::cout << desc << "\n";
+    return 1;
+  }
+
+  if (vm.count("verbosity")) {
+    LOG(0, "STATUS: Verbosity level was set to " << vm["verbosity"].as<size_t>() << ".");
+    setVerbosity(vm["verbosity"].as<size_t>());
+  } else {
+    LOG(0, "STATUS: Verbosity level was not set, defaulting to 5.");
+    setVerbosity(5);
+  }
+
+  std::string server;
+  std::string serverport;
+  if (vm.count("server")) {
+    server = vm["server"].as< std::string >();
+    serverport = server.substr(server.find_last_of(':')+1, std::string::npos);
+    server = server.substr(0, server.find_last_of(':'));
+    try {
+      boost::lexical_cast<size_t>(serverport);
+    } catch (boost::bad_lexical_cast) {
+      ELOG(1, "Could not interpret " << serverport << " as server:port.");
+      return 255;
+    }
+    LOG(1, "INFO: Using " << server << ":" << serverport << " as server's address.");
+  } else {
+    ELOG(1, "Requiring server's address (host:port) to connect to.");
+    return 255;
+  }
+
+  if (!vm.count("command")) {
+    ELOG(1, "Controller requires one of the following commands: "+toString(Commands));
+    return 255;
+  }
+  const std::string command = vm["command"].as< std::string >();
+  const CommandIndices commandIndex = getCommandIndex(CommandsMap, command);
+
+  // check arguments
+  switch(commandIndex) {
+    case AddJobsIndex:
+      if (!vm.count("executable") && !vm.count("jobfiles")) {
+        ELOG(1, "'"+command+"' requires at least two options: [executable] [list of input files ...].");
+        return 255;
+      }
+      break;
+    case CreateJobsIndex:
+      if (!vm.count("executable") && !vm.count("jobcommand")) {
+        ELOG(1, "'"+command+"' requires two options: [executable] [jobcommand].");
+        return 255;
+      }
+      break;
+    case CheckResultsIndex:
+      break;
+    case ReceiveResultsIndex:
+      break;
+    case ReceiveMPQCIndex:
+      if (!vm.count("fragment-path")) {
+        ELOG(1, "'"+command+"' require one option: [path to fragment files].");
+        return 255;
+      }
+      break;
+    case RemoveAllIndex:
+      break;
+    case ShutdownIndex:
+      break;
+    case UnknownCommandIndex:
+    default:
+      ELOG(1, "Unrecognized command '"+toString(command)+"'.");
+      return 255;
+      break;
+  }
+
   try
   {
-    // Check command line arguments.
-    if (argc < 4)
-    {
-      std::cerr << "Usage: " << argv[0] << " <host> <port> <command> [options to command]" << std::endl;
-      std::cerr << "List of available commands:" << std::endl;
-      for(CommandsMap_t::const_iterator iter = CommandsMap.begin();
-          iter != CommandsMap.end(); ++iter) {
-        std::cerr << "\t" << iter->first << std::endl;
-      }
-      return false;
-    }
 
     boost::asio::io_service io_service;
@@ -343,27 +427,11 @@
     // Initial phase: information gathering from server
 
-    switch(getCommandIndex(CommandsMap, argv[3])) {
+    switch(commandIndex) {
       case AddJobsIndex:
-      {
-        if (argc < 6) {
-          ELOG(1, "'addjobs' requires at least two options: [mpqc] [list of input files ...].");
-          return 255;
-        } else {
-          // get an id for every filename
-          controller.requestIds(argv[1], argv[2], argc-5);
-        }
-        break;
-      }
+        controller.requestIds(server, serverport, vm["jobfiles"].as< std::vector<std::string> >().size());
+        break;
       case CreateJobsIndex:
-      {
-        std::vector<FragmentJob::ptr> jobs;
-        if (argc < 6) {
-          return 255;
-          ELOG(1, "'createjobs' requires two options: [command] [argument].");
-        } else {
-          controller.requestIds(argv[1], argv[2], 1);
-        }
-        break;
-      }
+        controller.requestIds(server, serverport, 1);
+        break;
       case CheckResultsIndex:
         break;
@@ -371,8 +439,4 @@
         break;
       case ReceiveMPQCIndex:
-        if (argc < 5) {
-          ELOG(1, "'receivempqc' require one option: [path to fragment files].");
-          return 255;
-        }
         break;
       case RemoveAllIndex:
@@ -382,5 +446,5 @@
       case UnknownCommandIndex:
       default:
-        ELOG(1, "Unrecognized command '"+toString(argv[3])+"'.");
+        ELOG(0, "Unrecognized command '"+toString(command)+"'.");
         return 255;
         break;
@@ -395,18 +459,20 @@
     // Second phase: Building jobs and sending information to server
 
-    switch(getCommandIndex(CommandsMap, argv[3])) {
+    switch(commandIndex) {
       case AddJobsIndex:
       {
         std::vector<FragmentJob::ptr> jobs;
-        const std::string command(argv[4]);
-        for (int argcount = 5; argcount < argc; ++argcount) {
+        const std::string executable(vm["executable"].as< std::string >());
+        const std::vector< std::string > jobfiles = vm["jobfiles"].as< std::vector< std::string > >();
+        for (std::vector< std::string >::const_iterator iter = jobfiles.begin();
+            iter != jobfiles.end(); ++iter) {
           const JobId_t next_id = controller.getAvailableId();
-          const std::string filename(argv[argcount]);
+          const std::string &filename = *iter;
           LOG(1, "INFO: Creating MPQCCommandJob with filename'"
               +filename+"', and id "+toString(next_id)+".");
-          parsejob(jobs, command, filename, next_id);
+          parsejob(jobs, executable, filename, next_id);
         }
         controller.addJobs(jobs);
-        controller.sendJobs(argv[1], argv[2]);
+        controller.sendJobs(server, serverport);
         break;
       }
@@ -415,37 +481,27 @@
         const JobId_t next_id = controller.getAvailableId();
         std::vector<FragmentJob::ptr> jobs;
-        createjobs(jobs, argv[4], argv[5], next_id);
+        const std::string executable = vm["executable"].as< std::string >();
+        const std::string jobcommand = vm["jobcommand"].as< std::string >();
+        createjobs(jobs, executable, jobcommand, next_id);
         controller.addJobs(jobs);
-        controller.sendJobs(argv[1], argv[2]);
+        controller.sendJobs(server, serverport);
         break;
       }
       case CheckResultsIndex:
-      {
-        controller.checkResults(argv[1], argv[2]);
-        break;
-      }
+        controller.checkResults(server, serverport);
+        break;
       case ReceiveResultsIndex:
-      {
-        controller.receiveResults(argv[1], argv[2]);
-        break;
-      }
       case ReceiveMPQCIndex:
-      {
-        controller.receiveResults(argv[1], argv[2]);
-        break;
-      }
+        controller.receiveResults(server, serverport);
+        break;
       case RemoveAllIndex:
-      {
-        controller.removeall(argv[1], argv[2]);
-        break;
-      }
+        controller.removeall(server, serverport);
+        break;
       case ShutdownIndex:
-      {
-        controller.shutdown(argv[1], argv[2]);
-        break;
-      }
+        controller.shutdown(server, serverport);
+        break;
       case UnknownCommandIndex:
       default:
-        ELOG(0, "Unrecognized command '"+toString(argv[3])+"'.");
+        ELOG(0, "Unrecognized command '"+toString(command)+"'.");
         return 255;
         break;
@@ -460,13 +516,11 @@
     // Final phase: Print result of command
 
-    switch(getCommandIndex(CommandsMap, argv[3])) {
+    switch(commandIndex) {
       case AddJobsIndex:
       case CreateJobsIndex:
         break;
       case CheckResultsIndex:
-      {
         controller.printDoneJobs();
         break;
-      }
       case ReceiveResultsIndex:
       {
@@ -477,5 +531,5 @@
       case ReceiveMPQCIndex:
       {
-        const std::string path = argv[4];
+        const std::string path = vm["fragment-path"].as< std::string >();
         LOG(1, "INFO: Parsing fragment files from " << path << ".");
         std::vector<FragmentResult::ptr> results = controller.getReceivedResults();
@@ -492,5 +546,5 @@
       case UnknownCommandIndex:
       default:
-        ELOG(0, "Unrecognized command '"+toString(argv[3])+"'.");
+        ELOG(0, "Unrecognized command '"+toString(command)+"'.");
         return 255;
         break;
