source: branches/stable/mondo/src/mondoarchive/mondo-cli.c @ 1770

Last change on this file since 1770 was 1770, checked in by Bruno Cornec, 12 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

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