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

Last change on this file since 956 was 956, checked in by bruno, 13 years ago

merge -r938:954 $SVN_M/branches/stable

  • Property svn:keywords set to Id
File size: 27.0 KB
Line 
1/***************************************************************************
2 * $Id: mondo-cli.c 956 2006-11-21 00:42:46Z 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['o']
802        &&
803        !run_program_and_log_output
804        ("grep -Ei suse /etc/issue.net | grep -E '9.0' | grep 64", TRUE)) {
805        bkpinfo->make_cd_use_lilo = TRUE;
806        log_to_screen
807            (_("Forcing you to use LILO. SuSE 9.0 (64-bit) has a broken mkfs.vfat binary."));
808    }
809
810    if (flag_set['o']) {
811        bkpinfo->make_cd_use_lilo = TRUE;
812    }
813#ifndef __FreeBSD__
814    else {
815        if (!is_this_a_valid_disk_format("vfat")) {
816            bkpinfo->make_cd_use_lilo = TRUE;
817            log_to_screen
818                (_("Your kernel appears not to support vfat filesystems. I am therefore"));
819            log_to_screen
820                (_("using LILO instead of SYSLINUX as the CD/floppy's boot loader."));
821        }
822        if (run_program_and_log_output("which mkfs.vfat", FALSE)) {
823            bkpinfo->make_cd_use_lilo = TRUE;
824#ifdef __IA32__
825            log_to_screen
826                (_("Your filesystem is missing 'mkfs.vfat', so I cannot use SYSLINUX as"));
827            log_to_screen
828                (_("your boot loader. I shall therefore use LILO instead."));
829#endif
830#ifdef __IA64__
831            log_to_screen
832                (_("Your filesystem is missing 'mkfs.vfat', so I cannot prepare the EFI"));
833            log_to_screen(_("environment correctly. Please install it."));
834            fatal_error("Aborting");
835#endif
836        }
837#ifdef __IA64__
838        /* We force ELILO usage on IA64 */
839        bkpinfo->make_cd_use_lilo = TRUE;
840#endif
841    }
842#endif
843
844    if (bkpinfo->make_cd_use_lilo && !does_file_exist("/boot/boot.b")) {
845        paranoid_system("touch /boot/boot.b");
846    }
847
848    i = flag_set['O'] + flag_set['V'];
849    if (i == 0) {
850        retval++;
851        log_to_screen(_("Specify backup (-O), verify (-V) or both (-OV).\n"));
852    }
853
854/* and finally... */
855
856    return (retval);
857}
858
859
860
861/**
862 * Get the switches from @p argc and @p argv using getopt() and place them in
863 * @p flag_set and @p flag_val.
864 * @param argc The argument count (@p argc passed to main()).
865 * @param argv The argument vector (@p argv passed to main()).
866 * @param flag_val An array indexed by switch letter - if a switch is set and
867 * has an argument then set flag_val[switch] to that argument.
868 * @param flag_set An array indexed by switch letter - if a switch is set then
869 * set flag_set[switch] to TRUE, else set it to FALSE.
870 * @return The number of problems with the command line (0 for success).
871 */
872int
873retrieve_switches_from_command_line(int argc, char *argv[],
874                                    char *flag_val[128],
875                                    bool flag_set[128])
876{
877    /*@ ints ** */
878    int opt = 0;
879    char *tmp;
880    int i = 0;
881    int len;
882
883    /*@ bools *** */
884    bool bad_switches = FALSE;
885
886    assert(flag_val != NULL);
887    assert(flag_set != NULL);
888
889    for (i = 0; i < 128; i++) {
890        flag_val[i] = NULL;
891        flag_set[i] = FALSE;
892    }
893    while ((opt =
894            getopt(argc, argv,
895                   "0123456789A:B:C:DE:FHI:J:K:LNOP:QRS:T:VWb:c:d:ef:gik:l:mn:op:rs:tuw:x:z"))
896           != -1) {
897        if (opt == '?') {
898            bad_switches = TRUE;
899            /*log_it("Invalid option: %c\n",optopt); */
900        } else {
901            if (flag_set[optopt]) {
902                bad_switches = TRUE;
903                mr_asprintf(&tmp, _("Switch -%c previously defined as %s\n"), opt,
904                        flag_val[i]);
905                log_to_screen(tmp);
906                mr_free(tmp);
907            } else {
908                flag_set[opt] = TRUE;
909                if (optarg) {
910                    len = strlen(optarg);
911                    if (optarg[0] != '/' && optarg[len - 1] == '/') {
912                        optarg[--len] = '\0';
913                        log_to_screen
914                            (_("Warning - param '%s' should not have trailing slash!"),
915                             optarg);
916                    }
917                    if (opt == 'd') {
918                        if (strchr(flag_val[opt], '/')
919                            && flag_val[opt][0] != '/') {
920                            mr_asprintf(&tmp,
921                                    _("-%c flag --- must be absolute path --- '%s' isn't absolute"),
922                                    opt, flag_val[opt]);
923                            log_to_screen(tmp);
924                            mr_free(tmp);
925                            bad_switches = TRUE;
926                        }
927                    }
928                    mr_asprintf(&flag_val[opt], optarg);
929                }
930            }
931        }
932    }
933    for (i = optind; i < argc; i++) {
934        bad_switches = TRUE;
935        mr_asprintf(&tmp, _("Invalid arg -- %s\n"), argv[i]);
936        log_to_screen(tmp);
937        mr_free(tmp);
938    }
939    return (bad_switches);
940}
941
942
943
944
945/**
946 * Print a not-so-helpful help message and exit.
947 */
948void help_screen()
949{
950    log_msg(1, "Type 'man mondo-archive' for more information\n");
951    exit(1);
952}
953
954
955/**
956 * Terminate Mondo in response to a signal.
957 * @param sig The signal number received.
958 */
959void terminate_daemon(int sig)
960{
961    char *tmp;
962    char *tmp2;
963
964    switch (sig) {
965    case SIGINT:
966        mr_asprintf(&tmp, _("SIGINT signal received from OS"));
967        mr_asprintf(&tmp2, _("You interrupted me :-)"));
968        break;
969    case SIGKILL:
970        mr_asprintf(&tmp, _("SIGKILL signal received from OS"));
971        mr_asprintf(&tmp2,
972               _("I seriously have no clue how this signal even got to me. Something's wrong with your system."));
973        break;
974    case SIGTERM:
975        mr_asprintf(&tmp, _("SIGTERM signal received from OS"));
976        mr_asprintf(&tmp2, _("Got terminate signal"));
977        break;
978    case SIGHUP:
979        mr_asprintf(&tmp, _("SIGHUP signal received from OS"));
980        mr_asprintf(&tmp2, _("Hangup on line"));
981        break;
982    case SIGSEGV:
983        mr_asprintf(&tmp, _("SIGSEGV signal received from OS"));
984        mr_asprintf(&tmp2,
985               _("Internal programming error. Please send a backtrace as well as your log."));
986        break;
987    case SIGPIPE:
988        mr_asprintf(&tmp, _("SIGPIPE signal received from OS"));
989        mr_asprintf(&tmp2, _("Pipe was broken"));
990        break;
991    case SIGABRT:
992        mr_asprintf(&tmp, _("SIGABRT signal received from OS"));
993        mr_asprintf(&tmp2,
994                _("Abort - probably failed assertion. I'm sleeping for a few seconds so you can read the message."));
995        break;
996    default:
997        mr_asprintf(&tmp, _("(Unknown)"));
998        mr_asprintf(&tmp2, _("(Unknown)"));
999    }
1000
1001    log_to_screen(tmp);
1002    log_to_screen(tmp2);
1003    mr_free(tmp);
1004    mr_free(tmp2);
1005    if (sig == SIGABRT) {
1006        sleep(10);
1007    }
1008    kill_buffer();
1009    fatal_error
1010        ("Mondoarchive is terminating in response to a signal from the OS");
1011    finish(254);                // just in case
1012}
1013
1014
1015/**
1016 * Turn signal-trapping on or off.
1017 * @param on If TRUE, turn it on; if FALSE, turn it off (we still trap it, just don't do as much).
1018 */
1019void set_signals(int on)
1020{
1021    int signals[] =
1022        { SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT, SIGKILL, SIGSTOP, 0 };
1023    int i;
1024
1025    signal(SIGPIPE, sigpipe_occurred);
1026    for (i = 0; signals[i]; i++) {
1027        if (on) {
1028            signal(signals[i], terminate_daemon);
1029        } else {
1030            signal(signals[i], termination_in_progress);
1031        }
1032    }
1033}
1034
1035
1036/**
1037 * Exit immediately without cleaning up.
1038 * @param sig The signal we are exiting due to.
1039 */
1040void termination_in_progress(int sig)
1041{
1042    log_msg(1, "Termination in progress");
1043    usleep(1000);
1044    pthread_exit(0);
1045}
1046
1047/* @} - end of cliGroup */
Note: See TracBrowser for help on using the repository browser.