Line data Source code
1 : // Copyright (c) 2006-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/advgetopt
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 :
20 : /** \file
21 : * \brief Implementation of the options_to_strings() command.
22 : *
23 : * The getopt object holds all the command line options your program was
24 : * started with. Here we transforms these options back to shell command
25 : * line options so one can start the command again with the same options.
26 : */
27 :
28 : // self
29 : //
30 : #include "advgetopt/advgetopt.h"
31 :
32 : //#include "advgetopt/conf_file.h"
33 : //#include "advgetopt/exception.h"
34 : //#include "advgetopt/validator_double.h"
35 : //#include "advgetopt/validator_integer.h"
36 : //#include "advgetopt/version.h"
37 :
38 :
39 : // cppthread lib
40 : //
41 : #include <cppthread/log.h>
42 :
43 :
44 : // C lib
45 : //
46 : //#include <string.h>
47 :
48 :
49 : // last include
50 : //
51 : #include <snapdev/poison.h>
52 :
53 :
54 :
55 : namespace advgetopt
56 : {
57 :
58 :
59 : namespace
60 : {
61 :
62 : constexpr char const g_single_quote = '\'';
63 : constexpr char const g_space = ' ';
64 : constexpr char const * g_empty_string = "\"\"";
65 : constexpr char const * g_escaped_single_quotes = "'\\''";
66 : constexpr char const * g_simple_characters = "-+0123456789ABCEFGHIJKLMNOPQRSTUVWXYZabcefghijklmnopqrstuvwxyz_";
67 :
68 : } // no name namespace
69 :
70 :
71 : /** \brief Escape special characters from a shell argument.
72 : *
73 : * This function goes through the supplied argument. If it includes one
74 : * or more character other than `[-+0-9A-Za-z_]`, then it gets \em escaped.
75 : * This means we add single quotes at the start and end, and escape any
76 : * single quote within the argument.
77 : *
78 : * So the function may return the input string as is.
79 : *
80 : * \param[in] arg The argument to escape.
81 : *
82 : * \return The escaped argument.
83 : */
84 67 : std::string getopt::escape_shell_argument(std::string const & arg)
85 : {
86 67 : if(arg.empty())
87 : {
88 1 : return std::string(g_empty_string);
89 : }
90 :
91 66 : std::string::size_type const pos(arg.find_first_not_of(g_simple_characters));
92 66 : if(pos == std::string::npos)
93 : {
94 63 : return arg;
95 : }
96 :
97 6 : std::string result;
98 :
99 3 : result += g_single_quote;
100 3 : std::string::size_type p1(0);
101 9 : while(p1 < arg.length())
102 : {
103 5 : std::string::size_type const p2(arg.find('\'', p1));
104 5 : if(p2 == std::string::npos)
105 : {
106 2 : result += arg.substr(p1);
107 2 : break;
108 : }
109 3 : result += arg.substr(p1, p2 - p1);
110 3 : result += g_escaped_single_quotes;
111 3 : p1 = p2 + 1; // skip the '
112 : }
113 3 : result += g_single_quote;
114 :
115 3 : return result;
116 : }
117 :
118 :
119 : /** \brief Transform all the defined options back in a string.
120 : *
121 : * This function creates a string which system() can use to start the
122 : * command again with the same options. You may, of course, tweak the
123 : * options first.
124 : *
125 : * \param[in] include_progname Whether the program name should be included
126 : * in the output string. In some cases, you may want to start a different
127 : * program with similar command line options. This gives you that option.
128 : * \param[in] keep_defaults If the value is equal to the default value, it
129 : * gets ignored unless this parameter is set to true.
130 : *
131 : * \return The string representing the command line options.
132 : */
133 0 : std::string getopt::options_to_string(bool include_progname, bool keep_defaults) const
134 : {
135 0 : std::string result;
136 :
137 0 : if(include_progname)
138 : {
139 0 : result += escape_shell_argument(get_program_fullname());
140 : }
141 :
142 0 : for(auto const & opt : f_options_by_name)
143 : {
144 0 : if(!opt.second->is_defined())
145 : {
146 0 : continue;
147 : }
148 :
149 : // same as default, there should be no need to add that parameter
150 : //
151 0 : if(!keep_defaults
152 0 : && opt.second->get_default() == opt.second->get_value())
153 : {
154 0 : continue;
155 : }
156 :
157 0 : if(!result.empty())
158 : {
159 0 : result += g_space;
160 : }
161 0 : result += escape_shell_argument(opt.second->get_value());
162 : }
163 :
164 0 : return result;
165 : }
166 :
167 :
168 :
169 6 : } // namespace advgetopt
170 : // vim: ts=4 sw=4 et
|