Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2014-2023, Regents of the University of California,
4 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26#include "command-parser.hpp"
27#include "help.hpp"
28
29#include "core/version.hpp"
30
31#include <boost/tokenizer.hpp>
32#include <fstream>
33#include <iostream>
34
35namespace nfd::tools::nfdc {
36
37static int
38main(int argc, char** argv)
39{
40 std::vector<std::string> args(argv + 1, argv + argc);
41
42 CommandParser parser;
43 registerCommands(parser);
44
45 if (args.empty()) {
46 helpList(std::cout, parser);
47 return 0;
48 }
49
50 if (args[0] == "-V" || args[0] == "--version") {
51 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
52 return 0;
53 }
54
55 struct Command
56 {
57 std::string noun, verb;
59 ExecuteCommand execute;
60 };
61
62 auto processLine = [&parser] (const std::vector<std::string>& line) -> Command {
63 try {
64 auto [noun, verb, ca, execute] = parser.parse(line, ParseMode::ONE_SHOT);
65 return {noun, verb, ca, execute};
66 }
67 catch (const std::invalid_argument& e) {
68 int ret = help(std::cout, parser, line);
69 if (ret == 2)
70 std::cerr << e.what() << std::endl;
71 return {};
72 }
73 };
74
75 std::list<Command> commands;
76
77 if (args[0] == "-f" || args[0] == "--batch") {
78 if (args.size() != 2) {
79 std::cerr << "ERROR: Invalid command line arguments: " << args[0] << " should follow with batch-file."
80 << " Use -h for more detail." << std::endl;
81 return 2;
82 }
83
84 auto processIstream = [&commands, &processLine] (std::istream& is, const std::string& inputFile) {
85 std::string line;
86 size_t lineCounter = 0;
87 while (std::getline(is, line)) {
88 ++lineCounter;
89
90 auto hasEscapeSlash = [] (const std::string& str) {
91 auto count = std::count(str.rbegin(), str.rend(), '\\');
92 return (count % 2) == 1;
93 };
94 while (!line.empty() && hasEscapeSlash(line)) {
95 std::string extraLine;
96 const auto& hasMore = std::getline(is, extraLine);
97 ++lineCounter;
98 line = line.substr(0, line.size() - 1) + extraLine;
99 if (!hasMore) {
100 break;
101 }
102 }
103 boost::tokenizer<boost::escaped_list_separator<char>> tokenizer(
104 line,
105 boost::escaped_list_separator<char>("\\", " \t", "\"'"));
106
107 auto firstNonEmptyToken = tokenizer.begin();
108 while (firstNonEmptyToken != tokenizer.end() && firstNonEmptyToken->empty()) {
109 ++firstNonEmptyToken;
110 }
111
112 // Ignore empty lines (or lines with just spaces) and lines that start with #
113 // Non empty lines with trailing comment are not allowed and may trigger syntax error
114 if (firstNonEmptyToken == tokenizer.end() || (*firstNonEmptyToken)[0] == '#') {
115 continue;
116 }
117
118 std::vector<std::string> lineArgs;
119 std::copy_if(firstNonEmptyToken, tokenizer.end(), std::back_inserter(lineArgs),
120 [] (const auto& t) { return !t.empty(); });
121
122 auto cmd = processLine(lineArgs);
123 if (cmd.noun.empty()) {
124 std::cerr << " >> Syntax error on line " << lineCounter << " of the batch in "
125 << inputFile << std::endl;
126 return 2; // not exactly correct, but should be indication of an error, which already shown
127 }
128 commands.push_back(std::move(cmd));
129 }
130 return 0;
131 };
132
133 if (args[1] == "-") {
134 auto retval = processIstream(std::cin, "standard input");
135 if (retval != 0) {
136 return retval;
137 }
138 }
139 else {
140 std::ifstream iff(args[1]);
141 if (!iff) {
142 std::cerr << "ERROR: Could not open `" << args[1] << "` batch file "
143 << "(" << strerror(errno) << ")" << std::endl;
144 return 2;
145 }
146 auto retval = processIstream(iff, args[1]);
147 if (retval != 0) {
148 return retval;
149 }
150 }
151 }
152 else {
153 commands.push_back(processLine(args));
154 }
155
156 try {
157 ndn::Face face;
158 ndn::KeyChain keyChain;
159 ndn::nfd::Controller controller(face, keyChain);
160 size_t commandCounter = 0;
161 for (auto& command : commands) {
162 ++commandCounter;
163 ExecuteContext ctx{command.noun, command.verb, command.ca, 0,
164 std::cout, std::cerr, face, keyChain, controller};
165 command.execute(ctx);
166
167 if (ctx.exitCode != 0) {
168 if (commands.size() > 1) {
169 std::cerr << " >> Failed to execute command on line " << commandCounter
170 << " of the batch file " << args[1] << std::endl;
171 std::cerr << " Note that nfdc has executed all commands on previous lines and "
172 << "stopped processing at this line" << std::endl;
173 }
174
175 return ctx.exitCode;
176 }
177 }
178 return 0;
179 }
180 catch (const std::exception& e) {
181 std::cerr << e.what() << std::endl;
182 return 1;
183 }
184}
185
186} // namespace nfd::tools::nfdc
187
188int
189main(int argc, char** argv)
190{
191 return nfd::tools::nfdc::main(argc, argv);
192}
Contains named command arguments.
std::tuple< std::string, std::string, CommandArguments, ExecuteCommand > parse(const std::vector< std::string > &tokens, ParseMode mode) const
Parse a command line.
Context for command execution.
void helpList(std::ostream &os, const CommandParser &parser, ParseMode mode, std::string_view noun)
Writes the list of available commands to a stream.
Definition help.cpp:42
void registerCommands(CommandParser &parser)
static int main(int argc, char **argv)
Definition main.cpp:38
std::function< void(ExecuteContext &)> ExecuteCommand
A function to execute a command.
int help(std::ostream &os, const CommandParser &parser, std::vector< std::string > args)
Tries to help the user, if requested on the command line.
Definition help.cpp:78
int main(int argc, char **argv)
Definition main.cpp:189
const char NFD_VERSION_BUILD_STRING[]
NFD version string, including git commit information if NFD is build from a specific git commit.