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

Last change on this file since 1188 was 1188, checked in by bruno, 12 years ago

Stable merges again

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