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

Last change on this file since 900 was 900, checked in by Bruno Cornec, 18 years ago

Huge patch to introduce low level functions that will bw used everywhere (mr_free, mr_asprintf, ...)
Nearly linking now due to that.

  • Property svn:keywords set to Id
File size: 26.5 KB
Line 
1/***************************************************************************
2 * $Id: mondo-cli.c 900 2006-10-24 06:49:18Z 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 -x \"%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.