Pakman
main.cc
1 #include <iostream>
2 #include <string>
3 #include <exception>
4 #include <chrono>
5 
6 #include <getopt.h>
7 #include <libgen.h>
8 
9 #include "spdlog/spdlog.h"
10 #include "spdlog/sinks/stdout_color_sinks.h"
11 
12 #include "core/common.h"
13 #include "help.h"
14 #include "core/LongOptions.h"
15 #include "core/Arguments.h"
16 #include "core/OutputStreamHandler.h"
17 
18 #include "master/AbstractMaster.h"
19 #include "controller/AbstractController.h"
20 
21 // Program name
22 const char *g_program_name;
23 
24 // Global variables
25 std::chrono::milliseconds g_main_timeout(1);
26 std::chrono::milliseconds g_kill_timeout(100);
27 
28 bool g_ignore_errors = false;
29 bool g_force_host_spawn = false;
31 
32 bool g_program_terminated = false;
33 
34 std::string g_output_file;
35 
36 // Is help flag
37 bool is_help_flag(const std::string& flag)
38 {
39  return (flag.compare("-h") == 0) || (flag.compare("--help") == 0);
40 }
41 
42 // Add general options
43 void add_general_long_options(LongOptions& lopts)
44 {
45  lopts.add({"help", no_argument, nullptr, 'h'});
46  lopts.add({"ignore-errors", no_argument, nullptr, 'i'});
47  lopts.add({"discard-child-stderr", no_argument, nullptr, 'd'});
48  lopts.add({"verbosity", required_argument, nullptr, 'v'});
49  lopts.add({"output-file", required_argument, nullptr, 'o'});
50 }
51 
52 // Process general options
53 void process_general_options(master_t master, controller_t controller,
54  const Arguments& args)
55 {
56  if (args.isOptionalArgumentSet("help"))
57  help(master, controller, EXIT_SUCCESS);
58 
59  if (args.isOptionalArgumentSet("ignore-errors"))
60  g_ignore_errors = true;
61 
62  if (args.isOptionalArgumentSet("discard-child-stderr"))
64 
65  if (args.isOptionalArgumentSet("verbosity"))
66  {
67  std::string arg = args.optionalArgument("verbosity");
68 
69  if (arg.compare("info") == 0)
70  spdlog::set_level(spdlog::level::info);
71  else if (arg.compare("debug") == 0)
72  spdlog::set_level(spdlog::level::debug);
73  else if (arg.compare("off") == 0)
74  spdlog::set_level(spdlog::level::off);
75  else
76  help(master, controller, EXIT_FAILURE);
77  }
78 
79  if (args.isOptionalArgumentSet("output-file"))
80  g_output_file = args.optionalArgument("output-file");
81 }
82 
83 int main(int argc, char *argv[])
84 {
85  // Set g_program_name
86  g_program_name = basename(argv[0]);
87 
88  // Set logger
89  auto stderr_console = spdlog::stderr_color_st(g_program_name);
90  spdlog::set_default_logger(stderr_console);
91  spdlog::set_level(spdlog::level::info);
92 
93  // If there are less than 3 arguments, print overview help
94  if (argc < 3)
95  overview(EXIT_FAILURE);
96 
97  // Initialize master and controller
98  master_t master = no_master;
99  controller_t controller = no_controller;
100 
101  // If first argument is not master
102  if ((master = AbstractMaster::getMaster(argv[1])) == no_master)
103  {
104  // If first argument is not controller either, print overview
105  if ((controller = AbstractController::getController(argv[1]))
106  == no_controller)
107  overview(EXIT_FAILURE);
108 
109  // First argument is controller
110  // Check if second argument is "-h" or "--help"
111  if (is_help_flag(argv[2]))
112  help(master, controller, EXIT_FAILURE);
113 
114  // Else print overview
115  else
116  overview(EXIT_FAILURE);
117  }
118 
119  // Reaching this part of the code means first argument is valid master
120  // If second argument is not controller
121  if ((controller = AbstractController::getController(argv[2]))
122  == no_controller)
123  {
124  // Check if second argument is "-h" or "--help"
125  if (is_help_flag(argv[2]))
126  help(master, controller, EXIT_FAILURE);
127 
128  // Else print overview
129  else
130  overview(EXIT_FAILURE);
131  }
132 
133  /* Reaching this part of the code means that the first argument was a valid
134  * master and the second argument was a valid controller */
135 
136  // Initialize LongOptions object
137  LongOptions lopts;
138 
139  // Add general, master and controller options
140  add_general_long_options(lopts);
141  AbstractMaster::addLongOptions(master, lopts);
142  AbstractController::addLongOptions(controller, lopts);
143 
144  // Create Arguments object
145  // Set optind to 3 such that getopt skips the first 2 arguments
146  optind = 3;
147  Arguments args(lopts, argc, argv);
148 
149  // Process general options
150  process_general_options(master, controller, args);
151 
152  // Execute appropriate run function
153  try
154  {
155  AbstractMaster::run(master, controller, args);
156  }
157  catch (const std::exception& e)
158  {
159  // Print error message
160  std::string error_msg;
161  error_msg += "An exception occurred while running ";
162  error_msg += g_program_name;
163  error_msg += "!\n";
164  error_msg += " what(): ";
165  error_msg += e.what();
166  error_msg += "\n";
167  std::cerr << error_msg;
168 
169  // Clean up
170  AbstractMaster::cleanup(master);
172 
173  // Return nonzero exit code
174  return EXIT_FAILURE;
175  }
176 
177  // Cleanup
179 
180  // Exit
181  return 0;
182 }
void overview(int status)
Definition: help.cc:32
static controller_t getController(const std::string &arg)
static void cleanup(master_t master)
controller_t
Definition: common.h:45
static void run(master_t master, controller_t controller, const Arguments &args)
master_t
Definition: common.h:37
bool g_force_host_spawn
Definition: main.cc:29
bool g_program_terminated
Definition: main.cc:32
std::chrono::milliseconds g_kill_timeout
const char * g_program_name
Definition: main.cc:22
bool g_discard_child_stderr
Definition: main.cc:30
std::chrono::milliseconds g_main_timeout
static void addLongOptions(master_t master, LongOptions &lopts)
void help(master_t master, controller_t controller, int status)
Definition: help.cc:64
static master_t getMaster(const std::string &arg)
bool isOptionalArgumentSet(const std::string &option_name) const
Definition: Arguments.cc:38
bool g_ignore_errors
Definition: main.cc:28
void add(struct option long_opt)
Definition: LongOptions.cc:20
std::string g_output_file
Definition: main.cc:34
static void addLongOptions(controller_t controller, LongOptions &lopts)
std::string optionalArgument(const std::string &option_name) const
Definition: Arguments.cc:45