source: MondoRescue/branches/3.0/mondo/src/common/libmondo-cli.c

Last change on this file was 3192, checked in by Bruno Cornec, 11 years ago
  • revert r3188 & r3189 as I started to work on branch 3.0 before deciding it was much better to do it in 3.2. This will allow some small maintenance work on 3.0 if needed, while pushing all the rest to 3.2 and providing early access to it.
  • Property svn:keywords set to Id
File size: 32.1 KB
Line 
1/***************************************************************************
2$Id: libmondo-cli.c 3192 2013-09-25 07:03:25Z bruno $
3*******************************************************************/
4
5/**
6 * @file
7 * Functions for handling command-line arguments passed to mondoarchive.
8 */
9
10/** @def BOOT_LOADER_CHARS The characters allowed for boot loader on this platform. */
11
12#include <pthread.h>
13#include "my-stuff.h"
14#include "mr_mem.h"
15#include "mr_str.h"
16#include "mondostructures.h"
17#include "libmondo-cli-EXT.h"
18#include "libmondo.h"
19
20extern int g_loglevel;
21extern bool g_text_mode;
22extern bool g_fail_immediately;
23extern char g_startdir[MAX_STR_LEN]; ///< ????? @bug ?????
24extern char *MONDO_OPTIONS;
25
26/*@ file pointer **************************************************/
27extern FILE *g_tape_stream;
28
29/*@ long long *****************************************************/
30extern long long g_tape_posK;
31
32/*@ long **********************************************************/
33extern long g_noof_sets;
34
35/*@ bool******** **************************************************/
36bool g_debugging = FALSE; ///< ????? @bug ????? @ingroup globalGroup
37bool g_running_live = FALSE; ///< ????? @bug ????? @ingroup globalGroup
38extern bool g_cd_recovery;
39
40extern void setup_tmpdir(char *path);
41extern void setup_scratchdir(char *path);
42void mr_make_devlist_from_pathlist(char *pathlist, char mode);
43extern double g_kernel_version;
44extern int g_current_media_number;
45extern pid_t g_main_pid;
46extern char *resolve_softlinks_to_get_to_actual_device_file(char *);
47
48/* Do we use extended attributes and acl ?
49 * By default no, use -z option to force their usage */
50extern char *g_getfacl;
51extern char *g_getfattr;
52
53/* Reference to global bkpinfo */
54extern struct s_bkpinfo *bkpinfo;
55
56extern void free_MR_global_filenames(void);
57
58long g_max_biggie_size = BIGGIEMAXSIZE;
59
60/**
61 * @addtogroup cliGroup
62 * @{
63 */
64/**
65 * Populate @p bkpinfo from the command-line parameters stored in @p argc and @p argv.
66 * @param argc The argument count, including the program name; @p argc passed to main().
67 * @param argv The argument vector; @p argv passed to main().
68 * @param bkpinfo The backup information structure to populate.
69 * @return The number of problems with the command line (0 for success).
70 */
71int
72handle_incoming_parameters(int argc, char *argv[])
73{
74 /*@ int *** */
75 int res = 0;
76 int retval = 0;
77 int i = 0, j;
78
79 /*@ buffers *************** */
80 char *tmp = NULL;
81 char flag_val[128][MAX_STR_LEN];
82 bool flag_set[128];
83
84 for (i = 0; i < 128; i++) {
85 flag_val[i][0] = '\0';
86 flag_set[i] = FALSE;
87 }
88 bkpinfo->media_size = 650; /* default */
89 res = retrieve_switches_from_command_line(argc, argv, flag_val, flag_set);
90 retval += res;
91 if (!retval) {
92 res = process_switches(flag_val, flag_set);
93 retval += res;
94 }
95
96 log_msg(3, "Switches:-");
97 for (i = 0; i < 128; i++) {
98 if (flag_set[i]) {
99 mr_asprintf(tmp, "-%c %s", i, flag_val[i]);
100 log_msg(3, tmp);
101 mr_free(tmp);
102 }
103 }
104
105 return (retval);
106}
107
108
109/**
110 * Store the sizespec(s) stored in @p value into @p bkpinfo.
111 * @param bkpinfo The backup information structure; the @c bkpinfo->media_size field will be populated.
112 * @param value The sizespec (e.g. "2g", "40m").
113 * @return 0, always.
114 * @bug Return code not needed.
115 */
116int process_the_s_switch(char *value)
117{
118 assert(bkpinfo != NULL);
119 assert(value != NULL);
120
121 bkpinfo->media_size = -1; /* dummy value */
122 bkpinfo->media_size = friendly_sizestr_to_sizelong(value);
123 log_msg(3, "media_size = %ld", bkpinfo->media_size);
124 if (bkpinfo->media_size <= 0) {
125 log_msg(1, "You gave media an invalid size %s\n", value);
126 return (-1);
127 }
128 return (0);
129}
130
131/**
132 * Process mondoarchive's command-line switches.
133 * @param bkpinfo The backup information structure to populate.
134 * @param flag_val An array of the argument passed to each switch (the letter is the index).
135 * If a switch is not set or has no argument, the field in @p flag_val doesn't matter.
136 * @param flag_set An array of <tt>bool</tt>s indexed by switch letter: TRUE if it's set,
137 * FALSE if it's not.
138 * @return The number of problems with the switches, or 0 for success.
139 * @bug Maybe include a list of all switches (inc. intentionally undocumented ones not in the manual!) here?
140 */
141int
142process_switches(char flag_val[128][MAX_STR_LEN], bool flag_set[128])
143{
144
145 /*@ ints *** */
146 int i = 0;
147 int retval = 0;
148
149 /*@ buffers ** */
150 char *tmp = NULL;
151 char *tmp1 = NULL;
152 char *psz = NULL;
153 char *p = NULL;
154 char *q = NULL;
155
156 long itbs = 0L;
157
158 struct stat buf;
159
160 malloc_string(tmp);
161
162 assert(bkpinfo != NULL);
163 assert(flag_val != NULL);
164 assert(flag_set != NULL);
165
166 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
167
168 /* compulsory */
169 i = flag_set['c'] + flag_set['i'] + flag_set['n'] +
170 flag_set['t'] + flag_set['u'] + flag_set['r'] +
171 flag_set['w'] + flag_set['C'] + flag_set['U'];
172 if ((i == 0) && (! bkpinfo->restore_data)) {
173 retval++;
174 log_to_screen("You must specify the media type\n");
175 }
176 if (i > 1) {
177 retval++;
178 log_to_screen("Please specify only one media type\n");
179 }
180
181 if (flag_set['K']) {
182 g_loglevel = atoi(flag_val['K']);
183 log_msg(1,"Loglevel forced to %d",g_loglevel);
184 if (g_loglevel < 3) {
185 g_loglevel = 3;
186 }
187 }
188
189 if ((flag_set['L'] && flag_set['0']) && (! bkpinfo->restore_data)) {
190 retval++;
191 log_to_screen("You cannot have 'no compression' _and_ LZOP.\n");
192 }
193 if (! bkpinfo->restore_data) {
194 bkpinfo->backup_data = flag_set['O'];
195 }
196 bkpinfo->verify_data = flag_set['V'];
197
198 if (flag_set['I'] && !bkpinfo->backup_data) {
199 log_to_screen("-I switch is ignored if just verifying");
200 }
201 if (flag_set['E'] && !bkpinfo->backup_data) {
202 log_to_screen("-E switch is ignored if just verifying");
203 }
204
205 if (!find_home_of_exe("afio")) {
206 if (find_home_of_exe("star")) {
207 flag_set['R'] = TRUE;
208 log_msg(1, "Using star instead of afio");
209 } else {
210 fatal_error
211 ("Neither afio nor star is installed. Please install at least one.");
212 }
213 }
214
215 if (flag_set['R']) {
216 bkpinfo->use_star = TRUE;
217 if (flag_set['L']) {
218 fatal_error("You may not use star and lzop at the same time.");
219 }
220 if (!find_home_of_exe("star")) {
221 fatal_error
222 ("Please install 'star' RPM or tarball if you are going to use -R. Thanks.");
223 }
224 }
225
226 if ((flag_set['W']) && (! bkpinfo->restore_data)) {
227 bkpinfo->nonbootable_backup = TRUE;
228 log_to_screen("Warning - you have opted for non-bootable backup");
229 if (flag_set['f'] || flag_set['l']) {
230 log_to_screen
231 ("You don't need to specify bootloader or bootdevice");
232 }
233 }
234
235 if (flag_set['I']) {
236 if (bkpinfo->include_paths[0] == '-') {
237 retval++;
238 log_to_screen("Please supply a sensible value with '-I'\n");
239 }
240 if (!strcmp(bkpinfo->include_paths, "/")) {
241 log_msg(2, "'/' is pleonastic.");
242 bkpinfo->include_paths[0] = '\0';
243 }
244 if (bkpinfo->include_paths[0]) {
245 strcat(bkpinfo->include_paths, "|");
246 }
247
248 mr_asprintf(tmp1, "%s", flag_val['I']);
249 p = tmp1;
250 q = tmp1;
251
252 /* Cut the flag_val['I'] in parts containing all paths to test them */
253 while (p != NULL) {
254 q = strchr(p, '|');
255 if (q != NULL) {
256 *q = '\0';
257 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
258 log_msg(1, "ERROR ! %s doesn't exist", p);
259 fatal_error("ERROR ! You specified a directory to include which doesn't exist");
260 }
261 p = q+1 ;
262 } else {
263 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
264 log_msg(1, "ERROR ! %s doesn't exist", p);
265 fatal_error("ERROR ! You specified a directory to include which doesn't exist");
266 }
267 p = NULL;
268 }
269 }
270 paranoid_free(tmp1);
271 mr_make_devlist_from_pathlist(flag_val['I'], 'I');
272 log_msg(4, "Finished with the -I option");
273 }
274
275 if (g_kernel_version >= 2.6 && !flag_set['d']
276 && (flag_set['c'] || flag_set['w']) && (! bkpinfo->restore_data)) {
277 fatal_error
278 ("If you are using the 2.6.x kernel, please specify the CD-R(W) device.");
279 }
280
281
282 if (flag_set['J']) {
283 if (flag_set['I']) {
284 retval++;
285 log_to_screen
286 ("Please do not use -J in combination with -I. If you want to make a list of files to backup, that's fine, use -J <filename> but please don't muddy the waters by combining -J with -I. Thanks. :-)");
287 }
288 bkpinfo->make_filelist = FALSE;
289 strcpy(bkpinfo->include_paths, flag_val['J']);
290 }
291
292 if ((flag_set['c'] || flag_set['w'] || flag_set['C'] || flag_set['r']) && (! bkpinfo->restore_data)) {
293 if (!flag_set['r'] && g_kernel_version <= 2.5
294 && strstr(flag_val['d'], "/dev/")) {
295 fatal_error
296 ("Please don't give a /dev entry. Give a SCSI node for the parameter of the -d flag.");
297 }
298 if (flag_set['r'] && g_kernel_version <= 2.5
299 && !strstr(flag_val['d'], "/dev/")) {
300 fatal_error
301 ("Please give a /dev entry, not a SCSI node, as the parameter of the -d flag.");
302 }
303 if (g_kernel_version >= 2.6 && !strstr(flag_val['d'], "/dev/")) {
304 log_to_screen
305 ("Linus says 2.6 has a broken ide-scsi module. Proceed at your own risk...");
306 }
307
308 if (system("which cdrecord > /dev/null 2> /dev/null")
309 && system("which dvdrecord > /dev/null 2> /dev/null")) {
310 fatal_error
311 ("Please install dvdrecord/cdrecord and try again.");
312 }
313 if (flag_set['C']) {
314 bkpinfo->cdrw_speed = atoi(flag_val['C']);
315 if (bkpinfo->cdrw_speed < 1) {
316 fatal_error
317 ("You specified a silly speed for a CD-R[W] drive");
318 }
319 if (!flag_set['L']) {
320 log_to_screen
321 ("You must use -L with -C. Therefore I am setting it for you.");
322 flag_set['L'] = 1;
323 flag_val['L'][0] = '\0';
324 }
325 } else {
326 log_msg(3, "flag_val['c'] = %s", flag_val['c']);
327 log_msg(3, "flag_val['w'] = %s", flag_val['w']);
328// log_msg(3, "flag_set['r'] = %i", flag_set['r'] );
329 if (flag_set['c']) {
330 bkpinfo->cdrw_speed = atoi(flag_val['c']);
331 } else if (flag_set['w']) {
332 bkpinfo->cdrw_speed = atoi(flag_val['w']);
333 } else if (flag_set['r']) {
334 bkpinfo->cdrw_speed = 1; /*atoi(flag_val['r']); */
335 }
336
337 if (bkpinfo->cdrw_speed < 1) {
338 fatal_error
339 ("You specified a silly speed for a CD-R[W] drive");
340 }
341 }
342 }
343
344 if ((flag_set['t'] && !flag_set['d']) && (! bkpinfo->restore_data)) {
345 log_it("Hmm! No tape drive specified. Let's see what we can do.");
346 if (find_tape_device_and_size(flag_val['d'], tmp)) {
347 fatal_error
348 ("Tape device not specified. I couldn't find it either.");
349 }
350 flag_set['d'] = TRUE;
351 sprintf(tmp,
352 "You didn't specify a tape streamer device. I'm assuming %s",
353 flag_val['d']);
354 log_to_screen(tmp);
355 }
356
357 if (flag_set['U']) // USB
358 {
359 if (! flag_set['d']) {
360 fatal_error
361 ("You need to specify a device file with -d for bootable USB device usage");
362 }
363 if ((!flag_set['s']) && (! bkpinfo->restore_data)) {
364 fatal_error("You did not specify a size (-s) for your USB device. Aborting");
365 }
366 }
367
368 if (flag_set['r']) // DVD
369 {
370 if (flag_set['m']) {
371 fatal_error
372 ("Manual CD tray (-m) not yet supported in conjunction w/ DVD drives. Drop -m.");
373 }
374 if (!flag_set['d']) {
375 if (!find_dvd_device(flag_val['d'], FALSE)) {
376 flag_set['d'] = TRUE;
377 log_to_screen("I guess DVD drive is at %s", flag_val['d']);
378 }
379 }
380 if (strchr(flag_val['d'], ',')) {
381 fatal_error
382 ("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
383 }
384 if (! bkpinfo->restore_data) {
385 if (!find_home_of_exe("growisofs")) {
386 fatal_error
387 ("Please install growisofs (probably part of dvd+rw-tools). If you want DVD support, you need it.");
388 }
389 if (!find_home_of_exe("dvd+rw-format")) {
390 fatal_error
391 ("Please install dvd+rw-format (probably part of dvd+rw-tools). If you want DVD support, you need it.");
392 }
393 if (!flag_set['s']) {
394 sprintf(flag_val['s'], "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4582 MB
395 strcat(flag_val['s'], "m");
396 log_to_screen
397 ("You did not specify a size (-s) for DVD. I'm guessing %s.",
398 flag_val['s']);
399 flag_set['s'] = 1;
400 }
401 }
402/*
403 if (flag_set['Z']) {
404 bkpinfo->blank_dvd_first = TRUE;
405 }
406*/
407 }
408
409 if (flag_set['t'] || flag_set['u']) { /* tape size */
410 if (strchr(flag_val['d'], ',')) {
411 fatal_error
412 ("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
413 }
414 if ((flag_set['O']) && (! bkpinfo->restore_data)) {
415 if (flag_set['s']) {
416 if (flag_set['t']) {
417 fatal_error
418 ("For the moment, please don't specify a tape size. Mondo should handle end-of-tape gracefully anyway.");
419 }
420 if (process_the_s_switch(flag_val['s'])) {
421 fatal_error("Bad -s switch");
422 }
423 } else if (flag_set['u'] || flag_set['t']) {
424 bkpinfo->media_size = 0;
425 } else {
426 retval++;
427 log_to_screen("Tape size not specified.\n");
428 }
429 }
430 } else if (! bkpinfo->restore_data) { /* CD|USB size */
431 if (flag_set['s']) {
432 if (process_the_s_switch(flag_val['s'])) {
433 fatal_error("Bad -s switch");
434 }
435 }
436 if (flag_set['w']) {
437 bkpinfo->wipe_media_first = TRUE;
438 } /* CD-RW */
439 }
440
441 if (flag_set['n']) {
442 strncpy(bkpinfo->netfs_mount, flag_val['n'], MAX_STR_LEN);
443 if (!flag_set['d']) {
444 strncpy(bkpinfo->netfs_remote_dir, "/", MAX_STR_LEN);
445 }
446 /* test for protocol */
447 p = strstr(bkpinfo->netfs_mount, "://");
448 if (p == NULL) {
449 /* protocol not found assuming NFS for compatibility */
450 mr_asprintf(q,"nfs");
451
452 p = strchr(bkpinfo->netfs_mount, ':');
453 if (p == NULL) {
454 fatal_error("No protocol specified for remote share mount, nor any old NFS syntax found.\nPlease do man mondoarchive as syntax changed");
455 }
456 /* p points on to the string server:/path */
457 p = bkpinfo->netfs_mount;
458
459 } else {
460 /* Isolate the protocol */
461 *p = '\0';
462 mr_asprintf(q,"%s",bkpinfo->netfs_mount);
463
464 /* Skip proto now */
465 p++;
466 p++;
467 p++;
468 }
469 /* whatever done before proto is pointed to by q */
470 bkpinfo->netfs_proto = q;
471
472 /* p points on to the string server:/path */
473 /* Store the 2 values */
474 /* using memmove instead of strcpy as per #584 */
475 memmove(bkpinfo->netfs_mount, p, MAX_STR_LEN);
476
477 /* test if we specified a user */
478 p = strchr(bkpinfo->netfs_mount, '@');
479 if (p != NULL) {
480 /* User found. Store the 2 values */
481 p++;
482 /* new netfs mount */
483 strcpy(tmp,p);
484 p--;
485 *p = '\0';
486 mr_asprintf(q,"%s",bkpinfo->netfs_mount);
487 bkpinfo->netfs_user = q;
488 strcpy(bkpinfo->netfs_mount,tmp);
489 }
490 sprintf(tmp, "mount | grep -E \"^[a-z]*#*[%s@]*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_user,
491 bkpinfo->netfs_mount);
492 strncpy(bkpinfo->isodir,
493 call_program_and_get_last_line_of_output(tmp),
494 MAX_STR_LEN / 4);
495 if (strlen(bkpinfo->isodir) < 3) {
496 log_to_screen("Network share is not mounted. Trying to mount it for you.\n");
497 if (bkpinfo->netfs_user) {
498 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
499 sprintf(tmp, "sshfs %s@%s", bkpinfo->netfs_user, bkpinfo->netfs_mount);
500 } else if (strstr(bkpinfo->netfs_proto, "smbfs")) {
501 sprintf(tmp, "mount -t cifs %s -o user=%s", bkpinfo->netfs_mount, bkpinfo->netfs_user);
502 } else if (strstr(bkpinfo->netfs_proto, "nfs")) {
503 sprintf(tmp, "mount %s@%s", bkpinfo->netfs_user, bkpinfo->netfs_mount);
504 } else {
505 log_to_screen("Protocol %s not supported yet for network backups.\n", bkpinfo->netfs_proto);
506 fatal_error("Bad Protocol\n");
507 }
508 } else {
509 if (strstr(bkpinfo->netfs_proto, "sshfs")) {
510 sprintf(tmp, "sshfs %s", bkpinfo->netfs_mount);
511 } else if (strstr(bkpinfo->netfs_proto, "smbfs")) {
512 sprintf(tmp, "mount -t cifs %s", bkpinfo->netfs_mount);
513 } else if (strstr(bkpinfo->netfs_proto, "nfs")) {
514 sprintf(tmp, "mount %s", bkpinfo->netfs_mount);
515 } else {
516 log_to_screen("Protocol %s not supported yet for network backups.\n", bkpinfo->netfs_proto);
517 fatal_error("Bad Protocol\n");
518 }
519 }
520 if (system(tmp)) {
521 log_to_screen("Unable to mount Network share %s. Please mount manually.\n", bkpinfo->netfs_mount);
522 retval++;
523 } else {
524 if (bkpinfo->netfs_user) {
525 sprintf(tmp, "mount | grep -E \"^[%s@]*%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_user,
526 bkpinfo->netfs_mount);
527 } else {
528 sprintf(tmp, "mount | grep -E \"^%s[/]* .*\" | cut -d' ' -f3", bkpinfo->netfs_mount);
529 }
530 strncpy(bkpinfo->isodir,
531 call_program_and_get_last_line_of_output(tmp),
532 MAX_STR_LEN / 4);
533 if (strlen(bkpinfo->isodir) < 3) {
534 retval++;
535 log_to_screen("Network share %s is strangely not mounted. Please mount manually...\n", bkpinfo->netfs_mount);
536 }
537 }
538 }
539 log_msg(3, "proto = %s", bkpinfo->netfs_proto);
540 log_msg(3, "mount = %s", bkpinfo->netfs_mount);
541 if (bkpinfo->netfs_user) {
542 log_msg(3, "user = %s", bkpinfo->netfs_user);
543 }
544 log_msg(3, "isodir= %s", bkpinfo->isodir);
545 }
546
547 if (flag_set['c']) {
548 bkpinfo->backup_media_type = cdr;
549 }
550 if (flag_set['C']) {
551 bkpinfo->backup_media_type = cdstream;
552 }
553 if (flag_set['i']) {
554 bkpinfo->backup_media_type = iso;
555 }
556 if (flag_set['n']) {
557 bkpinfo->backup_media_type = netfs;
558 /* Never try to eject a Network device */
559 bkpinfo->please_dont_eject = TRUE;
560 }
561 if (flag_set['r']) {
562 bkpinfo->backup_media_type = dvd;
563 }
564 if (flag_set['t']) {
565 bkpinfo->backup_media_type = tape;
566 }
567 if (flag_set['u']) {
568 bkpinfo->backup_media_type = udev;
569 }
570 if (flag_set['w']) {
571 bkpinfo->backup_media_type = cdrw;
572 }
573 if (flag_set['U']) {
574 bkpinfo->backup_media_type = usb;
575 /* Never try to eject a USB device */
576 bkpinfo->please_dont_eject = TRUE;
577 }
578 if (flag_set['z']) {
579 if (find_home_of_exe("getfattr")) {
580 mr_asprintf(g_getfattr,"getfattr");
581 }
582 if (find_home_of_exe("getfacl")) {
583 mr_asprintf(g_getfacl,"getfacl");
584 }
585 }
586
587 /* optional, popular */
588 if (flag_set['g']) {
589 g_text_mode = FALSE;
590 }
591
592 if (flag_set['E']) {
593 if (bkpinfo->exclude_paths && (bkpinfo->exclude_paths[0] == '-')) {
594 retval++;
595 log_to_screen("Please supply a sensible value with '-E'\n");
596 }
597 mr_asprintf(tmp1, "%s", flag_val['E']);
598
599 p = tmp1;
600 q = tmp1;
601
602 /* Cut the flag_val['E'] in parts containing all paths to test them */
603 while (p != NULL) {
604 q = strchr(p, '|');
605 if (q != NULL) {
606 *q = '\0';
607 /* Fix bug 14 where ending / cause a problem later
608 * so handled here for the moment */
609 q--;
610 if (*q == '/') {
611 *q = '\0';
612 }
613 q++;
614 /* End of bug fix */
615 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
616 log_msg(1, "WARNING ! %s doesn't exist", p);
617 }
618 p = q+1 ;
619 } else {
620 if ((stat(p, &buf) != 0) && (! bkpinfo->restore_data)) {
621 log_msg(1, "WARNING ! %s doesn't exist", p);
622 }
623 p = NULL;
624 }
625 }
626 paranoid_free(tmp1);
627
628 mr_make_devlist_from_pathlist(flag_val['E'], 'E');
629 log_msg(4, "Finished with the -E option");
630 }
631
632 if (flag_set['e']) {
633 bkpinfo->please_dont_eject = TRUE;
634 }
635
636 if (flag_set['M']) {
637 g_max_biggie_size = atol(flag_val['M']);
638 log_msg(1, "Max size for biggie file is now %ld KB", g_max_biggie_size);
639 }
640
641 if ((flag_set['N']) && (! bkpinfo->restore_data)) // exclude Network mounts & devices
642 {
643 psz = list_of_NETFS_mounts_only();
644 log_msg(5, "-N means we'll exclude %s", psz);
645 if (bkpinfo->exclude_paths) {
646 mr_strcat(bkpinfo->exclude_paths, "|%s", psz);
647 mr_free(psz);
648 } else {
649 bkpinfo->exclude_paths = psz;
650 }
651
652 if (bkpinfo->exclude_paths != NULL) {
653 log_msg(3, "-N means we're now excluding %s", bkpinfo->exclude_paths);
654 }
655 }
656
657 if (flag_set['b']) {
658 mr_asprintf(psz, "%s", flag_val['b']);
659 log_msg(1, "psz = '%s'", psz);
660 if (psz[strlen(psz) - 1] == 'k') {
661 psz[strlen(psz) - 1] = '\0';
662 itbs = atol(psz) * 1024L;
663 } else {
664 itbs = atol(psz);
665 }
666 mr_free(psz);
667 log_msg(1, "'%s' --> %ld", flag_val['b'], itbs);
668 log_msg(1, "Internal tape block size is now %ld bytes", itbs);
669 if (itbs % 512 != 0 || itbs < 256 || itbs > 1024L * 1024) {
670 fatal_error
671 ("Are you nuts? Silly, your internal tape block size is. Abort, I shall.");
672 }
673 bkpinfo->internal_tape_block_size = itbs;
674 }
675
676 if ((flag_set['D']) && (! bkpinfo->restore_data)) {
677 bkpinfo->differential = 1;
678// bkpinfo->differential = atoi (flag_val['D']);
679 if ((bkpinfo->differential < 1) || (bkpinfo->differential > 9)) {
680 fatal_error
681 ("The D option should be between 1 and 9 inclusive");
682 }
683 }
684
685 if (flag_set['x']) {
686 strncpy(bkpinfo->image_devs, flag_val['x'], MAX_STR_LEN / 4);
687 if ((run_program_and_log_output("which ntfsclone", 2)) && (! bkpinfo->restore_data)) {
688 fatal_error("Please install ntfsprogs package/tarball.");
689 }
690 }
691
692 if (flag_set['m']) {
693 bkpinfo->manual_cd_tray = TRUE;
694 }
695
696 if ((flag_set['k']) && (! bkpinfo->restore_data)) {
697 strncpy(bkpinfo->kernel_path, flag_val['k'], MAX_STR_LEN);
698 if (!strcmp(bkpinfo->kernel_path, "failsafe")) {
699 strcpy(bkpinfo->kernel_path, "FAILSAFE");
700 }
701 if (strcmp(bkpinfo->kernel_path, "FAILSAFE")
702 && !does_file_exist(bkpinfo->kernel_path)) {
703 retval++;
704 sprintf(tmp,
705 "You specified kernel '%s', which does not exist\n",
706 bkpinfo->kernel_path);
707 log_to_screen(tmp);
708 }
709 }
710
711 if (flag_set['p']) {
712 strncpy(bkpinfo->prefix, flag_val['p'], MAX_STR_LEN / 4);
713 log_msg(1,"Prefix forced to %s",bkpinfo->prefix);
714 }
715
716 if (flag_set['d']) { /* backup directory (if ISO/NETFS) */
717 if (flag_set['i']) {
718 strncpy(bkpinfo->isodir, flag_val['d'], MAX_STR_LEN / 4);
719 sprintf(tmp, "ls -l %s", bkpinfo->isodir);
720 if (run_program_and_log_output(tmp, 2)) {
721 fatal_error
722 ("output folder does not exist - please create it");
723 }
724 } else if (flag_set['n']) {
725 strncpy(bkpinfo->netfs_remote_dir, flag_val['d'], MAX_STR_LEN);
726 } else { /* backup device (if tape/CD-R/CD-RW) */
727 strncpy(bkpinfo->media_device, flag_val['d'], MAX_STR_LEN / 4);
728 }
729 }
730
731 if ((flag_set['n']) && (! bkpinfo->restore_data)) {
732 mr_asprintf(tmp1,"%s/%s/.dummy.txt", bkpinfo->isodir,bkpinfo->netfs_remote_dir);
733 if ((bkpinfo->netfs_user) && (strstr(bkpinfo->netfs_proto,"nfs"))) {
734 sprintf(tmp, "su - %s -c \"echo hi > %s\"", bkpinfo->netfs_user, tmp1);
735 } else {
736 sprintf(tmp, "echo hi > %s", tmp1);
737 }
738 if (run_program_and_log_output(tmp, 2)) {
739 retval++;
740 sprintf(tmp,
741 "Are you sure directory '%s' exists in remote dir '%s'?\nIf so, do you have rights to write to it?\n",
742 bkpinfo->netfs_remote_dir, bkpinfo->netfs_mount);
743 log_to_screen(tmp);
744 }
745 unlink(tmp1);
746 paranoid_free(tmp1);
747 }
748
749 if (!flag_set['d']
750 && (flag_set['c'] || flag_set['w'] || flag_set['C'])) {
751 if (g_kernel_version >= 2.6) {
752 if (popup_and_get_string
753 ("Device", "Please specify the device",
754 bkpinfo->media_device, MAX_STR_LEN / 4)) {
755 retval++;
756 log_to_screen("User opted to cancel.");
757 }
758 } else if (find_cdrw_device(bkpinfo->media_device)) {
759 retval++;
760 log_to_screen
761 ("Tried and failed to find CD-R[W] drive automatically.\n");
762 } else {
763 flag_set['d'] = TRUE;
764 strncpy(flag_val['d'], bkpinfo->media_device, MAX_STR_LEN / 4);
765 }
766 }
767
768 if ((!flag_set['d'] && !flag_set['n'] && !flag_set['C']) && (! bkpinfo->restore_data)) {
769 retval++;
770 log_to_screen("Please specify the backup device/directory.\n");
771 fatal_error
772 ("You didn't use -d to specify the backup device/directory.");
773 }
774
775 for (i = '0'; i <= '9'; i++) {
776 if (flag_set[i]) {
777 bkpinfo->compression_level = i - '0';
778 } /* not '\0' but '0' */
779 }
780
781 if (flag_set['S']) {
782 setup_scratchdir(flag_val['S']);
783 sprintf(tmp, "touch %s/.foo.dat", bkpinfo->scratchdir);
784 if (run_program_and_log_output(tmp, 1)) {
785 retval++;
786 log_to_screen("Please specify a scratchdir which I can write to. :)");
787 fatal_error("I cannot write to the scratchdir you specified.");
788 }
789 sprintf(tmp, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->scratchdir, bkpinfo->scratchdir);
790 if (run_program_and_log_output(tmp, 1)) {
791 retval++;
792 log_to_screen("Please don't specify a SAMBA or VFAT or NFS scratchdir.");
793 fatal_error("I cannot write to the scratchdir you specified.");
794 }
795 }
796
797 if (flag_set['T']) {
798 setup_tmpdir(flag_val['T']);
799 sprintf(tmp, "touch %s/.foo.dat", bkpinfo->tmpdir);
800 if (run_program_and_log_output(tmp, 1)) {
801 retval++;
802 log_to_screen("Please specify a tempdir which I can write to. :)");
803 fatal_error("I cannot write to the tempdir you specified.");
804 }
805 sprintf(tmp, "ln -sf %s/.foo.dat %s/.bar.dat", bkpinfo->tmpdir, bkpinfo->tmpdir);
806 if (run_program_and_log_output(tmp, 1)) {
807 retval++;
808 log_to_screen("Please don't specify a SAMBA or VFAT or NFS tmpdir.");
809 fatal_error("I cannot write to the tempdir you specified.");
810 }
811 }
812
813 if ((flag_set['A']) && (! bkpinfo->restore_data)) {
814 strncpy(bkpinfo->call_after_iso, flag_val['A'], MAX_STR_LEN);
815 }
816
817 if ((flag_set['B']) && (! bkpinfo->restore_data)) {
818 strncpy(bkpinfo->call_before_iso, flag_val['B'], MAX_STR_LEN);
819 }
820
821 if ((flag_set['H']) && (! bkpinfo->restore_data)) {
822 g_cd_recovery = TRUE;
823 }
824
825 if ((flag_set['l']) && (! bkpinfo->restore_data)) {
826#ifdef __FreeBSD__
827# define BOOT_LOADER_CHARS "GLBMR"
828#else
829# ifdef __IA64__
830# define BOOT_LOADER_CHARS "GER"
831# else
832# define BOOT_LOADER_CHARS "GLR"
833# endif
834#endif
835 if (!strchr
836 (BOOT_LOADER_CHARS,
837 (bkpinfo->boot_loader = flag_val['l'][0]))) {
838 log_msg(1, "%c? WTF is %c? I need G, L, E or R.",
839 bkpinfo->boot_loader, bkpinfo->boot_loader);
840 fatal_error
841 ("Please specify GRUB, LILO, ELILO or RAW with the -l switch");
842 }
843#undef BOOT_LOADER_CHARS
844 }
845
846 if (flag_set['f']) {
847 strncpy(bkpinfo->boot_device,
848 resolve_softlinks_to_get_to_actual_device_file(flag_val
849 ['f']),
850 MAX_STR_LEN / 4);
851 }
852
853 if ((flag_set['P']) && (! bkpinfo->restore_data)) {
854 strncpy(bkpinfo->postnuke_tarball, flag_val['P'], MAX_STR_LEN);
855 }
856
857 if (flag_set['Q']) {
858 i = which_boot_loader(tmp);
859 log_msg(3, "boot loader is %c, residing at %s", i, tmp);
860 printf("boot loader is %c, residing at %s\n", i, tmp);
861 finish(0);
862 }
863
864 if ((flag_set['L']) && (! bkpinfo->restore_data)) {
865 bkpinfo->use_lzo = TRUE;
866 if (run_program_and_log_output("which lzop", 2)) {
867 retval++;
868 log_to_screen
869 ("Please install LZOP. You can't use '-L' until you do.\n");
870 }
871 }
872
873 if (flag_set['F']) {
874 log_msg(3, "-F means we will fail immediately at the first interaction request");
875 g_fail_immediately = TRUE;
876 }
877
878 if ((flag_set['G']) && (! bkpinfo->restore_data)) {
879 bkpinfo->use_gzip = TRUE;
880 if (run_program_and_log_output("which gzip", 2)) {
881 retval++;
882 log_to_screen
883 ("Please install gzip. You can't use '-G' until you do.\n");
884 }
885 }
886
887 bkpinfo->use_obdr = FALSE;
888 if (flag_set['o']) {
889 if ((!flag_set['t']) && (! bkpinfo->restore_data)) {
890 log_to_screen("OBDR support is only available for tapes. Use the -t option");
891 fatal_error("Aborting");
892 }
893 bkpinfo->use_obdr = TRUE;
894 }
895
896#ifndef __FreeBSD__
897 if ((!is_this_a_valid_disk_format("vfat")) && (! bkpinfo->restore_data)) {
898 bkpinfo->make_cd_use_lilo = TRUE;
899 log_to_screen
900 ("Your kernel appears not to support vfat filesystems. I am therefore");
901 log_to_screen
902 ("using LILO instead of SYSLINUX as the media boot loader.");
903 }
904 if ((run_program_and_log_output("which mkfs.vfat", 2)) && (! bkpinfo->restore_data)) {
905 bkpinfo->make_cd_use_lilo = TRUE;
906#ifdef __IA32__
907 log_to_screen
908 ("Your filesystem is missing 'mkfs.vfat', so I cannot use SYSLINUX as");
909 log_to_screen
910 ("your boot loader. I shall therefore use LILO instead.");
911#endif
912#ifdef __IA64__
913 log_to_screen
914 ("Your filesystem is missing 'mkfs.vfat', so I cannot prepare the EFI");
915 log_to_screen("environment correctly. Please install it.");
916 fatal_error("Aborting");
917#endif
918 }
919#ifdef __IA64__
920 /* We force ELILO usage on IA64 */
921 bkpinfo->make_cd_use_lilo = TRUE;
922#endif
923#endif
924
925 if (! bkpinfo->restore_data) {
926 i = flag_set['O'] + flag_set['V'];
927 if (i == 0) {
928 retval++;
929 log_to_screen("Specify backup (-O), verify (-V) or both (-OV).\n");
930 }
931 }
932
933 if ((! bkpinfo->restore_data) && (flag_set['Z'])) {
934 fatal_error
935 ("The -Z switch is only valid in restore mode");
936 }
937
938 if (flag_set['Z']) {
939 if (! strcmp(flag_val['Z'], "nuke")) {
940 bkpinfo->restore_mode = nuke;
941 } else if (! strcmp(flag_val['Z'], "interactive")) {
942 bkpinfo->restore_mode = interactive;
943 } else if (! strcmp(flag_val['Z'], "compare")) {
944 bkpinfo->restore_mode = compare;
945 } else if (! strcmp(flag_val['Z'], "mbr")) {
946 bkpinfo->restore_mode = mbr;
947 } else if (! strcmp(flag_val['Z'], "iso")) {
948 bkpinfo->restore_mode = isoonly;
949 } else if (! strcmp(flag_val['Z'], "isonuke")) {
950 bkpinfo->restore_mode = isonuke;
951 } else {
952 bkpinfo->restore_mode = interactive;
953 }
954 }
955
956/* and finally... */
957
958 paranoid_free(tmp);
959 return (retval);
960}
961
962
963
964/**
965 * Get the switches from @p argc and @p argv using getopt() and place them in
966 * @p flag_set and @p flag_val.
967 * @param argc The argument count (@p argc passed to main()).
968 * @param argv The argument vector (@p argv passed to main()).
969 * @param flag_val An array indexed by switch letter - if a switch is set and
970 * has an argument then set flag_val[switch] to that argument.
971 * @param flag_set An array indexed by switch letter - if a switch is set then
972 * set flag_set[switch] to TRUE, else set it to FALSE.
973 * @return The number of problems with the command line (0 for success).
974 */
975int
976retrieve_switches_from_command_line(int argc, char *argv[],
977 char flag_val[128][MAX_STR_LEN],
978 bool flag_set[128])
979{
980 /*@ ints ** */
981 int opt = 0;
982 char *tmp = NULL;
983 int i = 0;
984 int len;
985
986 /*@ bools *** */
987 bool bad_switches = FALSE;
988
989 assert(flag_val != NULL);
990 assert(flag_set != NULL);
991
992 for (i = 0; i < 128; i++) {
993 flag_val[i][0] = '\0';
994 flag_set[i] = FALSE;
995 }
996 while ((opt =
997 getopt(argc, argv, MONDO_OPTIONS))
998 != -1) {
999 if (opt == '?') {
1000 bad_switches = TRUE;
1001 /*log_it("Invalid option: %c\n",optopt); */
1002 } else {
1003 if (flag_set[opt]) {
1004 bad_switches = TRUE;
1005 mr_asprintf(tmp, "Switch -%c previously defined as %s\n", opt, flag_val[opt]);
1006 log_to_screen(tmp);
1007 paranoid_free(tmp);
1008 } else {
1009 flag_set[opt] = TRUE;
1010 if (optarg) {
1011 len = strlen(optarg);
1012 if (optarg[0] != '/' && optarg[len - 1] == '/') {
1013 optarg[--len] = '\0';
1014 log_to_screen
1015 ("Warning - param '%s' should not have trailing slash!",
1016 optarg);
1017 }
1018 if (opt == 'd') {
1019 if (strchr(flag_val[opt], '/')
1020 && flag_val[opt][0] != '/') {
1021 mr_asprintf(tmp, "-%c flag --- must be absolute path --- '%s' isn't absolute", opt, flag_val[opt]);
1022 log_to_screen(tmp);
1023 paranoid_free(tmp);
1024 bad_switches = TRUE;
1025 }
1026 }
1027 strcpy(flag_val[opt], optarg);
1028 }
1029 }
1030 }
1031 }
1032 for (i = optind; i < argc; i++) {
1033 bad_switches = TRUE;
1034 mr_asprintf(tmp, "Invalid arg -- %s\n", argv[i]);
1035 log_to_screen(tmp);
1036 paranoid_free(tmp);
1037 }
1038 return (bad_switches);
1039}
1040
1041
1042
1043
1044/**
1045 * Print a not-so-helpful help message and exit.
1046 */
1047void help_screen()
1048{
1049 log_msg(1, "Type 'man mondoarchive' for more information\n");
1050 exit(1);
1051}
1052
1053
1054/**
1055 * Terminate Mondo in response to a signal.
1056 * @param sig The signal number received.
1057 */
1058void terminate_daemon(int sig)
1059{
1060 char *tmp = NULL;
1061 char *tmp2 = NULL;
1062
1063 switch (sig) {
1064 case SIGINT:
1065 mr_asprintf(tmp, "SIGINT");
1066 mr_asprintf(tmp2, "You interrupted me :-)");
1067 break;
1068 case SIGKILL:
1069 mr_asprintf(tmp, "SIGKILL");
1070 mr_asprintf(tmp2, "I seriously have no clue how this signal even got to me. Something's wrong with your system.");
1071 break;
1072 case SIGTERM:
1073 mr_asprintf(tmp, "SIGTERM");
1074 mr_asprintf(tmp2, "Got terminate signal");
1075 break;
1076 case SIGHUP:
1077 mr_asprintf(tmp, "SIGHUP");
1078 mr_asprintf(tmp2, "Hangup on line");
1079 break;
1080 case SIGSEGV:
1081 mr_asprintf(tmp, "SIGSEGV");
1082 mr_asprintf(tmp2, "Internal programming error. Please send a backtrace as well as your log.");
1083 break;
1084 case SIGPIPE:
1085 mr_asprintf(tmp, "SIGPIPE");
1086 mr_asprintf(tmp2, "Pipe was broken");
1087 break;
1088 case SIGABRT:
1089 mr_asprintf(tmp, "SIGABRT");
1090 mr_asprintf(tmp2, "Abort - probably failed assertion. I'm sleeping for a few seconds so you can read the message.");
1091 break;
1092 default:
1093 mr_asprintf(tmp, "(Unknown)");
1094 mr_asprintf(tmp2, "(Unknown)");
1095 }
1096
1097 mr_strcat(tmp, " signal received from OS");
1098 log_to_screen(tmp);
1099 paranoid_free(tmp);
1100
1101 log_to_screen(tmp2);
1102 paranoid_free(tmp2);
1103 if (sig == SIGABRT) {
1104 sleep(10);
1105 }
1106 kill_buffer();
1107
1108 free_MR_global_filenames();
1109
1110 fatal_error
1111 ("MondoRescue is terminating in response to a signal from the OS");
1112 finish(254); // just in case
1113}
1114
1115
1116
1117
1118/**
1119 * Turn signal-trapping on or off.
1120 * @param on If TRUE, turn it on; if FALSE, turn it off (we still trap it, just don't do as much).
1121 */
1122void set_signals(int on)
1123{
1124 int signals[] =
1125 { SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT, SIGKILL, SIGSTOP, 0 };
1126 int i;
1127
1128 signal(SIGPIPE, sigpipe_occurred);
1129 for (i = 0; signals[i]; i++) {
1130 if (on) {
1131 signal(signals[i], terminate_daemon);
1132 } else {
1133 signal(signals[i], termination_in_progress);
1134 }
1135 }
1136}
1137
1138
1139
1140
1141/**
1142 * Exit immediately without cleaning up.
1143 * @param sig The signal we are exiting due to.
1144 */
1145void termination_in_progress(int sig)
1146{
1147 log_msg(1, "Termination in progress");
1148 usleep(1000);
1149 pthread_exit(0);
1150}
1151
1152/* @} - end of cliGroup */
Note: See TracBrowser for help on using the repository browser.