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

Last change on this file since 1043 was 1043, checked in by Bruno Cornec, 14 years ago

merge -r978:1042 $SVN_M/branches/stable

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