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