CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
command.cc
Go to the documentation of this file.
1 
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)
48  shortopts.push_back(':');
49 
50  longopts[i].name = strdup(params[i].key.c_str());
51  longopts[i].has_arg = params[i].is_switch ? no_argument : required_argument;
52  longopts[i].flag = NULL;
53  longopts[i].val = params[i].short_key;
54  }
55 
56  int idx;
57  int c;
58  opterr = 0; // Don't print error messages in getopt
59  optind = 2; // Skip the command itself
60  while ((c = getopt_long(argc, argv, shortopts.c_str(), longopts, &idx))
61  != -1) {
62  bool found = false;
63  for (unsigned i = 0; i < params.size(); ++i) {
64  if (c == params[i].short_key) {
65  Argument argument;
66  if (!params[i].is_switch) {
67  argument.value_str = optarg;
68  argument.value_int = String2Int64(argument.value_str);
69  }
70  result.Set(params[i], argument);
71  found = true;
72  break;
73  }
74  }
75 
76  if (!found) {
77  assert(c == '?');
78  // Easier to duplicate the next few lines than to add an RAII wrapper
79  for (unsigned i = 0; i < params.size(); ++i) {
80  free(const_cast<char *>(longopts[i].name));
81  }
82  free(longopts);
83 
84  throw EPublish(
85  GetName() + ": unrecognized parameter '" + argv[optind - 1] + "'",
86  EPublish::kFailInvocation);
87  }
88  }
89 
90  for (unsigned i = 0; i < params.size(); ++i) {
91  free(const_cast<char *>(longopts[i].name));
92  }
93  free(longopts);
94 
95  for (unsigned i = 0; i < params.size(); ++i) {
96  if (!params[i].is_optional && !result.Has(params[i].key)) {
97  throw EPublish(
98  GetName() + ": missing mandatory parameter '" + params[i].key + "'",
99  EPublish::kFailInvocation);
100  }
101  }
102 
103  for (int i = optind; i < argc; ++i) {
104  result.AppendPlain(Argument(argv[i]));
105  }
106 
107  if (result.plain_args().size() < GetMinPlainArgs()) {
108  LogCvmfs(kLogCvmfs, kLogStderr, "Usage: %s %s %s", progname().c_str(),
109  GetName().c_str(), GetUsage().c_str());
110  throw EPublish(GetName() + ": missing argument", EPublish::kFailInvocation);
111  }
112 
113  return result;
114 }
115 
116 
117 //------------------------------------------------------------------------------
118 
119 
120 CommandList::~CommandList() {
121  for (unsigned i = 0; i < commands_.size(); ++i)
122  delete commands_[i];
123 }
124 
125 Command *CommandList::Find(const std::string &name) {
126  Command *result = NULL;
127  for (unsigned i = 0; i < commands_.size(); ++i) {
128  if (commands_[i]->GetName() == name) {
129  result = commands_[i];
130  break;
131  }
132  }
133  return result;
134 }
135 
136 void CommandList::TakeCommand(Command *command) {
137  assert(Find(command->GetName()) == NULL);
138  commands_.push_back(command);
139 }
140 
141 } // namespace publish
bool Has(const std::string &key) const
Definition: command.h:108
std::string value_str
Definition: command.h:97
assert((mem||(size==0))&&"Out Of Memory")
const std::vector< Argument > & plain_args() const
Definition: command.h:128
int64_t String2Int64(const string &value)
Definition: string.cc:234
std::vector< Parameter > ParameterList
Definition: command.h:86
void Set(const Parameter &p, const Argument &a)
Definition: command.h:107
void AppendPlain(const Argument &a)
Definition: command.h:106
virtual std::string GetName() const =0
CVMFS_EXPORT void LogCvmfs(const LogSource source, const int mask, const char *format,...)
Definition: logging.cc:545