source: MondoRescue/trunk/mondo/src/mondoarchive/mondo-cli.c@ 914

Last change on this file since 914 was 914, checked in by Bruno Cornec, 17 years ago

merge -r902:913 $SVN_M/branches/stable

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