CernVM-FS  2.12.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
command.cc
Go to the documentation of this file.
1 
5 #include "cvmfs_config.h"
6 #include "publish/command.h"
7 
8 #include <getopt.h>
9 
10 #include <cassert>
11 #include <cstdlib>
12 #include <cstring>
13 
14 #include "publish/except.h"
15 #include "util/logging.h"
16 #include "util/smalloc.h"
17 #include "util/string.h"
18 
19 using namespace std; // NOLINT
20 
21 namespace publish {
22 
23 std::string Command::GetExamples() const {
24  std::vector<std::string> examples = DoGetExamples();
25  std::string result;
26  for (unsigned i = 0; i < examples.size(); ++i) {
27  result += progname() + " " + GetName() + " " + examples[i] + "\n";
28  }
29  return result;
30 }
31 
32 
33 Command::Options Command::ParseOptions(int argc, char **argv) {
34  Options result;
35  progname_ = argv[0];
36  ParameterList params = GetParams();
37 
38  string shortopts;
39  struct option *longopts = reinterpret_cast<option *>(
40  smalloc((params.size() + 1) * sizeof(struct option)));
41  struct option lastopt;
42  memset(&lastopt, 0, sizeof(lastopt));
43  longopts[params.size()] = lastopt;
44 
45  for (unsigned i = 0; i < params.size(); ++i) {
46  shortopts.push_back(params[i].short_key);
47  if (!params[i].is_switch) shortopts.push_back(':');
48 
49  longopts[i].name = strdup(params[i].key.c_str());
50  longopts[i].has_arg = params[i].is_switch ? no_argument : required_argument;
51  longopts[i].flag = NULL;
52  longopts[i].val = params[i].short_key;
53  }
54 
55  int idx;
56  int c;
57  opterr = 0; // Don't print error messages in getopt
58  optind = 2; // Skip the command itself
59  while ((c = getopt_long(argc, argv, shortopts.c_str(), longopts, &idx)) != -1)
60  {
61  bool found = false;
62  for (unsigned i = 0; i < params.size(); ++i) {
63  if (c == params[i].short_key) {
64  Argument argument;
65  if (!params[i].is_switch) {
66  argument.value_str = optarg;
67  argument.value_int = String2Int64(argument.value_str);
68  }
69  result.Set(params[i], argument);
70  found = true;
71  break;
72  }
73  }
74 
75  if (!found) {
76  assert(c == '?');
77  // Easier to duplicate the next few lines than to add an RAII wrapper
78  for (unsigned i = 0; i < params.size(); ++i) {
79  free(const_cast<char *>(longopts[i].name));
80  }
81  free(longopts);
82 
83  throw EPublish(GetName() + ": unrecognized parameter '" +
84  argv[optind - 1] + "'", EPublish::kFailInvocation);
85  }
86  }
87 
88  for (unsigned i = 0; i < params.size(); ++i) {
89  free(const_cast<char *>(longopts[i].name));
90  }
91  free(longopts);
92 
93  for (unsigned i = 0; i < params.size(); ++i) {
94  if (!params[i].is_optional && !result.Has(params[i].key)) {
95  throw EPublish(
96  GetName() + ": missing mandatory parameter '" + params[i].key + "'",
97  EPublish::kFailInvocation);
98  }
99  }
100 
101  for (int i = optind; i < argc; ++i) {
102  result.AppendPlain(Argument(argv[i]));
103  }
104 
105  if (result.plain_args().size() < GetMinPlainArgs()) {
106  LogCvmfs(kLogCvmfs, kLogStderr, "Usage: %s %s %s",
107  progname().c_str(), GetName().c_str(), GetUsage().c_str());
108  throw EPublish(GetName() + ": missing argument", EPublish::kFailInvocation);
109  }
110 
111  return result;
112 }
113 
114 
115 //------------------------------------------------------------------------------
116 
117 
118 CommandList::~CommandList() {
119  for (unsigned i = 0; i < commands_.size(); ++i)
120  delete commands_[i];
121 }
122 
123 Command *CommandList::Find(const std::string &name) {
124  Command *result = NULL;
125  for (unsigned i = 0; i < commands_.size(); ++i) {
126  if (commands_[i]->GetName() == name) {
127  result = commands_[i];
128  break;
129  }
130  }
131  return result;
132 }
133 
134 void CommandList::TakeCommand(Command *command) {
135  assert(Find(command->GetName()) == NULL);
136  commands_.push_back(command);
137 }
138 
139 } // namespace publish
bool Has(const std::string &key) const
Definition: command.h:114
assert((mem||(size==0))&&"Out Of Memory")
const std::vector< Argument > & plain_args() const
Definition: command.h:137
int64_t String2Int64(const string &value)
Definition: string.cc:222
std::vector< Parameter > ParameterList
Definition: command.h:92
void Set(const Parameter &p, const Argument &a)
Definition: command.h:113
void AppendPlain(const Argument &a)
Definition: command.h:112
virtual std::string GetName() const =0
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:528