1 /*********************************************************************/
2 // dar - disk archive - a backup/restoration program
3 // Copyright (C) 2002-2052 Denis Corbin
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 //
19 // to contact the author : http://dar.linux.free.fr/email.html
20 /*********************************************************************/
21
22 #include "../my_config.h"
23
24 extern "C"
25 {
26 #if HAVE_STRING_H
27 #include <string.h>
28 #endif
29
30 #if HAVE_STRINGS_H
31 #include <strings.h>
32 #endif
33
34 #if STDC_HEADERS
35 # include <string.h>
36 #else
37 # if !HAVE_STRCHR
38 # define strchr index
39 # define strrchr rindex
40 # endif
41 char *strchr (), *strrchr ();
42 # if !HAVE_MEMCPY
43 # define memcpy(d, s, n) bcopy ((s), (d), (n))
44 # define memmove(d, s, n) bcopy ((s), (d), (n))
45 # endif
46 #endif
47
48 #include "getopt_decision.h"
49 } // end extern "C"
50
51 #include <string>
52 #include <iostream>
53 #include <new>
54
55 #include "user_interaction.hpp"
56 #include "zapette.hpp"
57 #include "sar.hpp"
58 #include "path.hpp"
59 #include "tuyau.hpp"
60 #include "erreurs.hpp"
61 #include "tools.hpp"
62 #include "dar_suite.hpp"
63 #include "integers.hpp"
64 #include "libdar.hpp"
65 #include "shell_interaction.hpp"
66 #include "line_tools.hpp"
67 #include "entrepot_local.hpp"
68
69 #define ONLY_ONCE "Only one -%c is allowed, ignoring this extra option"
70 #define OPT_STRING "i:o:hVE:Qj9:"
71
72 using namespace libdar;
73 using namespace std;
74
75 #define DAR_SLAVE_VERSION "1.4.10"
76
77 static bool command_line(shell_interaction & dialog,
78 S_I argc, char * const argv[], path * &chemin, string & filename,
79 string &input_pipe, string &output_pipe, string & execute,
80 infinint & min_digits);
81 static void show_usage(shell_interaction & dialog, const char *command);
82 static void show_version(shell_interaction & dialog, const char *command);
83 static S_I little_main(shell_interaction & dialog, S_I argc, char * const argv[], const char **env);
84
main(S_I argc,char * const argv[],const char ** env)85 int main(S_I argc, char * const argv[], const char **env)
86 {
87 return dar_suite_global(argc,
88 argv,
89 env,
90 OPT_STRING,
91 #if HAVE_GETOPT_LONG
92 nullptr,
93 #endif
94 '\0', // should never be met as option, thus early read the whole command-line for -j and -Q options
95 &little_main);
96 }
97
little_main(shell_interaction & dialog,S_I argc,char * const argv[],const char ** env)98 static S_I little_main(shell_interaction & dialog, S_I argc, char * const argv[], const char **env)
99 {
100 path *chemin = nullptr;
101 string filename;
102 string input_pipe;
103 string output_pipe;
104 string execute;
105 infinint min_digits;
106
107 if(command_line(dialog, argc, argv, chemin, filename, input_pipe, output_pipe, execute, min_digits))
108 {
109 tuyau *input = nullptr;
110 tuyau *output = nullptr;
111 sar *source = nullptr;
112 entrepot_local entrep = entrepot_local("", "", false);
113
114 if(chemin == nullptr)
115 throw SRC_BUG;
116
117 entrep.set_location(*chemin);
118 try
119 {
120 source = new (nothrow) sar(dialog, filename, EXTENSION, entrep, true, min_digits, false, execute);
121 if(source == nullptr)
122 throw Ememory("little_main");
123
124 tools_open_pipes(dialog, input_pipe, output_pipe, input, output);
125
126 slave_zapette zap = slave_zapette(input, output, source);
127 input = output = nullptr; // now managed by zap;
128 source = nullptr; // now managed by zap;
129
130 try
131 {
132 zap.action();
133 }
134 catch(Erange &e)
135 {
136 dialog.warning(e.get_message());
137 throw Edata(e.get_message());
138 }
139 }
140 catch(...)
141 {
142 delete chemin;
143 if(input != nullptr)
144 delete input;
145 if(output != nullptr)
146 delete output;
147 if(source != nullptr)
148 delete source;
149 throw;
150 }
151 delete chemin;
152 if(input != nullptr)
153 delete input;
154 if(output != nullptr)
155 delete output;
156 if(source != nullptr)
157 delete source;
158
159 return EXIT_OK;
160 }
161 else
162 return EXIT_SYNTAX;
163 }
164
command_line(shell_interaction & dialog,S_I argc,char * const argv[],path * & chemin,string & filename,string & input_pipe,string & output_pipe,string & execute,infinint & min_digits)165 static bool command_line(shell_interaction & dialog,
166 S_I argc,char * const argv[], path * &chemin, string & filename,
167 string &input_pipe, string &output_pipe, string & execute,
168 infinint & min_digits)
169 {
170 S_I lu;
171 execute = "";
172
173 if(argc < 1)
174 {
175 dialog.warning(gettext("Cannot read arguments on command line, aborting"));
176 return false;
177 }
178
179 while((lu = getopt(argc, argv, OPT_STRING)) != EOF)
180 {
181 switch(lu)
182 {
183 case 'i':
184 if(optarg == nullptr)
185 throw Erange("command_line", gettext("Missing argument to -i option"));
186 if(input_pipe == "")
187 input_pipe = optarg;
188 else
189 dialog.warning(tools_printf(gettext(ONLY_ONCE), char(lu)));
190 break;
191 case 'o':
192 if(optarg == nullptr)
193 throw Erange("command_line", gettext("Missing argument to -o option"));
194 if(output_pipe == "")
195 output_pipe = optarg;
196 else
197 dialog.warning(tools_printf(gettext(ONLY_ONCE), char(lu)));
198 break;
199 case 'h':
200 show_usage(dialog, argv[0]);
201 return false;
202 case 'V':
203 show_version(dialog, argv[0]);
204 return false;
205 case 'E':
206 if(optarg == nullptr)
207 throw Erange("command_line", gettext("Missing argument to -E option"));
208 if(execute == "")
209 execute = optarg;
210 else
211 execute += string(" ; ") + optarg;
212 break;
213 case 'Q':
214 break; // ignore this option already parsed during initialization (dar_suite.cpp)
215 case '9':
216 if(optarg == nullptr)
217 throw Erange("command_line", tools_printf(gettext("Missing argument to --min-digits"), char(lu)));
218 else
219 {
220 infinint tmp2, tmp3;
221 line_tools_get_min_digits(optarg, min_digits, tmp2, tmp3);
222 }
223 break;
224 case ':':
225 throw Erange("command_line", tools_printf(gettext("Missing parameter to option -%c"), char(optopt)));
226 case '?':
227 throw Erange("command_line", tools_printf(gettext("Ignoring unknown option -%c"), char(optopt)));
228 default:
229 throw Erange("command_line", tools_printf(gettext("Ignoring unknown option -%c"), char(lu)));
230 }
231 }
232
233 if(optind + 1 > argc)
234 {
235 dialog.warning(gettext("Missing archive basename, see -h option for help"));
236 return false;
237 }
238
239 if(optind + 1 < argc)
240 {
241 dialog.warning(gettext("Too many argument on command line, see -h option for help"));
242 return false;
243 }
244
245 tools_split_path_basename(argv[optind], chemin, filename);
246 tools_check_basename(dialog, *chemin, filename, EXTENSION);
247 return true;
248 }
249
show_usage(shell_interaction & dialog,const char * command)250 static void show_usage(shell_interaction & dialog, const char *command)
251 {
252 string cmd;
253 tools_extract_basename(command, cmd);
254 dialog.change_non_interactive_output(&cout);
255
256 dialog.printf("\nusage : \n");
257 dialog.printf(" command1 | %s [options] [<path>/]basename | command2\n", cmd.c_str());
258 dialog.printf(" %s [options] [-i input_pipe] [-o output_pipe] [<path>/]basename\n", cmd.c_str());
259 dialog.printf(" %s -h\n", cmd.c_str());
260 dialog.printf(" %s -V\n\n", cmd.c_str());
261 dialog.printf(gettext("\n"));
262 dialog.printf(gettext("Common options:\n"));
263 dialog.printf(gettext(" -i <named pipe> pipe to use instead of std input to read orders from dar\n"));
264 dialog.printf(gettext(" -o <named pipe> pipe to use instead of std output to write data to dar\n"));
265 dialog.printf(gettext(" -E <string>\t command line to execute between slices of the archive\n"));
266 dialog.printf(gettext("\n"));
267 dialog.printf(gettext("See man page for more options.\n"));
268 }
269
show_version(shell_interaction & dialog,const char * command)270 static void show_version(shell_interaction & dialog, const char *command)
271 {
272 string cmd;
273 tools_extract_basename(command, cmd);
274 U_I maj, med, min;
275
276 get_version(maj, med, min);
277 dialog.change_non_interactive_output(&cout);
278 dialog.printf("\n %s version %s Copyright (C) 2002-2052 Denis Corbin\n\n", cmd.c_str(), DAR_SLAVE_VERSION);
279 if(maj > 2)
280 dialog.printf(gettext(" Using libdar %u.%u.%u built with compilation time options:\n"), maj, med, min);
281 else
282 dialog.printf(gettext(" Using libdar %u.%u built with compilation time options:\n"), maj, min);
283 tools_display_features(dialog);
284 dialog.printf("\n");
285 dialog.printf(gettext(" compiled the %s with %s version %s\n"), __DATE__, CC_NAT, __VERSION__);
286 dialog.printf(gettext(" %s is part of the Disk ARchive suite (Release %s)\n"), cmd.c_str(), PACKAGE_VERSION);
287 dialog.warning(tools_printf(gettext(" %s comes with ABSOLUTELY NO WARRANTY;"), cmd.c_str())
288 + tools_printf(gettext(" for details\n type `dar -W'."))
289 + tools_printf(gettext(" This is free software, and you are welcome\n to redistribute it under certain conditions;"))
290 + tools_printf(gettext(" type `dar -L | more'\n for details.\n\n")));
291 }
292