source: MondoRescue/branches/stable/mondo/src/common/libmondo-tools.c @ 1140

Last change on this file since 1140 was 1140, checked in by Bruno Cornec, 13 years ago

Try to fix some valgrind reports (note that this version still doesn't work)

  • Property svn:keywords set to Id
File size: 40.3 KB
Line 
1/* libmondo-tools.c                                  misc tools
2   $Id: libmondo-tools.c 1140 2007-02-12 01:05:43Z bruno $
3*/
4
5
6/**
7 * @file
8 * Miscellaneous tools that didn't really fit anywhere else.
9 */
10
11#include "my-stuff.h"
12#include "mr_mem.h"
13#include "mr_msg.h"
14#include "mr_file.h"
15
16#include "mondostructures.h"
17#include "libmondo-tools.h"
18#include "libmondo-gui-EXT.h"
19#include "libmondo-files-EXT.h"
20#include "libmondo-fork-EXT.h"
21#include "libmondo-raid-EXT.h"
22#include <sys/socket.h>
23#include <netdb.h>
24#include <netinet/in.h>
25#include <arpa/inet.h>
26
27/*@unused@*/
28//static char cvsid[] = "$Id: libmondo-tools.c 1140 2007-02-12 01:05:43Z bruno $";
29
30extern int g_tape_buffer_size_MB;
31extern char *g_erase_tmpdir_and_scratchdir;
32extern char *g_serial_string;
33extern bool g_text_mode;
34extern int g_currentY;
35extern int g_current_media_number;
36
37/**
38 * @addtogroup globalGroup
39 * @{
40 */
41bool g_remount_cdrom_at_end,    ///< TRUE if we unmounted the CD-ROM and should remount it when done with the backup.
42 g_remount_floppy_at_end;       ///< TRUE if we unmounted the floppy and should remount it when done with the backup.
43bool g_cd_recovery;             ///< TRUE if we're making an "autonuke" backup.
44double g_kernel_version;
45
46/**
47 * The place where /boot is mounted.
48 */
49char *g_boot_mountpt = NULL;
50
51/**
52 * The location of Mondo's home directory.
53 */
54char *g_mondo_home = NULL;
55
56/**
57 * The serial string (used to differentiate between backups) of the current backup.
58 */
59char *g_serial_string = NULL;
60
61/**
62 * The location where tmpfs is mounted, or "" if it's not mounted.
63 */
64char *g_tmpfs_mountpt = NULL;
65char *g_magicdev_command = NULL;
66
67/**
68 * The default maximum level to log messages at or below.
69 */
70int g_loglevel = DEFAULT_DEBUG_LEVEL;
71
72/* @} - end of globalGroup */
73
74
75extern pid_t g_buffer_pid;
76extern pid_t g_main_pid;
77
78extern t_bkptype g_backup_media_type;
79
80extern bool am_I_in_disaster_recovery_mode(void);
81
82
83/**
84 * @addtogroup utilityGroup
85 * @{
86 */
87/**
88 * Assertion handler. Prints a friendly message to the user,
89 * offering to ignore all, dump core, break to debugger,
90 * exit, or ignore. Intended to be used with an assert() macro.
91 *
92 * @param file The file in which the assertion triggered.
93 * @param function The function (@c __FUNCTION__) in which the assertion triggered.
94 * @param line The line number of the assert() statement.
95 * @param exp The expression that failed (as a string).
96 */
97void _mondo_assert_fail(const char *file,
98                        const char *function, int line, const char *exp)
99{
100    static int ignoring_assertions = 0;
101    bool is_valid = TRUE;
102
103    log_it("ASSERTION FAILED: `%s' at %s:%d in %s", exp, file, line,
104           function);
105    if (ignoring_assertions) {
106        log_it("Well, the user doesn't care...");
107        return;
108    }
109#ifndef _XWIN
110    if (!g_text_mode)
111        newtSuspend();
112#endif
113    printf("ASSERTION FAILED: `%s'\n", exp);
114    printf("\tat %s:%d in %s\n\n", file, line, function);
115    printf("(I)gnore, ignore (A)ll, (D)ebug, a(B)ort, or (E)xit? ");
116    do {
117        is_valid = TRUE;
118        switch (toupper(getchar())) {
119        case 'A':               // ignore (A)ll
120            ignoring_assertions = 1;
121            break;
122        case 'B':               // a(B)ort
123            signal(SIGABRT, SIG_DFL);   /* prevent SIGABRT handler from running */
124            raise(SIGABRT);
125            break;              /* "can't get here" */
126        case 'D':               // (D)ebug, aka asm("int 3")
127#ifdef __IA32__
128            __asm__ __volatile__("int $3"); // break to debugger
129#endif
130            break;
131        case 'E':               // (E)xit
132            fatal_error("Failed assertion -- see above for details");
133            break;              /* "can't get here" */
134        case 'I':               // (I)gnore
135            break;
136            /* These next two work as follows:
137               the `default' catches the user's invalid choice and says so;
138               the '\n' catches the newline on the end and prints the prompt again.
139             */
140        case '\n':
141            printf
142                ("(I)gnore, ignore (A)ll, (D)ebug, a(B)ort, or (E)xit? ");
143            break;
144        default:
145            is_valid = FALSE;
146            printf("Invalid choice.\n");
147            break;
148        }
149    } while (!is_valid);
150
151    if (ignoring_assertions) {
152        log_it("Ignoring ALL assertions from now on.");
153    } else {
154        log_it("Ignoring assertion: %s", exp);
155    }
156
157    getchar();                  // skip \n
158
159#ifndef _XWIN
160    if (!g_text_mode)
161        newtResume();
162#endif
163}
164
165/**
166 * Clean's up users' KDE desktops.
167 * @bug Details about this function are unknown.
168 */
169void clean_up_KDE_desktop_if_necessary(void)
170{
171    char *tmp;
172
173    malloc_string(tmp);
174    strcpy(tmp,
175           "for i in `find /root /home -type d -name Desktop -maxdepth 2`; do \
176file=$i/.directory; if [ -f \"$file\" ] ; then mv -f $file $file.old ; \
177awk '{if (index($0, \"rootimagesmindi\")) { while (length($0)>2) { getline;} ; } \
178else { print $0;};}' $file.old  > $file ; fi ; done");
179    run_program_and_log_output(tmp, 5);
180    mr_free(tmp);
181}
182
183
184/**
185 * Locate mondoarchive's home directory. Searches in /usr/share/mondo,
186 * /usr/local/share/mondo, /opt, or if all else fails, search /usr.
187 *
188 * @param home_sz String to store the home directory ("" if it could not be found).
189 * @return 0 for success, nonzero for failure.
190 */
191int find_and_store_mondoarchives_home(char *home_sz)
192{
193    assert(home_sz != NULL);
194    strcpy(home_sz, MONDO_SHARE);
195    return (0);
196}
197
198
199char *get_architecture()
200{
201#ifdef __IA32__
202    return ("i386");
203#endif
204#ifdef __IA64__
205    return ("ia64");
206#endif
207    return ("unknown");
208}
209
210
211
212double get_kernel_version()
213{
214    char *p, tmp[200];
215    double d;
216#ifdef __FreeBSD__
217    // JOSH - FIXME :)
218    d = 5.2;                    // :-)
219#else
220    strcpy(tmp, call_program_and_get_last_line_of_output("uname -r"));
221    p = strchr(tmp, '.');
222    if (p) {
223        p = strchr(++p, '.');
224        if (p) {
225            while (*p) {
226                *p = *(p + 1);
227                p++;
228            }
229        }
230    }
231//  mr_msg(1, "tmp = '%s'", tmp);
232    d = atof(tmp);
233#endif
234    mr_msg(1, "g_kernel_version = %f", d);
235    return (d);
236}
237
238
239
240
241
242/**
243 * Get the current time.
244 * @return number of seconds since the epoch.
245 */
246long get_time()
247{
248    return (long) time((void *) 0);
249}
250
251
252
253
254
255
256
257/**
258 * Initialize a RAID volume structure, setting fields to zero. The
259 * actual hard drive is unaffected.
260 *
261 * @param raidrec The RAID volume structure to initialize.
262 * @note This function is system dependent.
263 */
264#ifdef __FreeBSD__
265void initialize_raidrec(struct vinum_volume *raidrec)
266{
267    int i, j;
268    raidrec->volname[0] = '\0';
269    raidrec->plexes = 0;
270    for (i = 0; i < 9; ++i) {
271        raidrec->plex[i].raidlevel = -1;
272        raidrec->plex[i].stripesize = 0;
273        raidrec->plex[i].subdisks = 0;
274        for (j = 0; j < 9; ++j) {
275            strcpy(raidrec->plex[i].sd[j].which_device, "");
276        }
277    }
278}
279#else
280void initialize_raidrec(struct raid_device_record *raidrec)
281{
282    assert(raidrec != NULL);
283    raidrec->raid_device[0] = '\0';
284    raidrec->raid_level = -9;
285    raidrec->persistent_superblock = 1;
286    raidrec->chunk_size = 64;
287    raidrec->parity = -1;
288    raidrec->data_disks.entries = 0;
289    raidrec->spare_disks.entries = 0;
290    raidrec->parity_disks.entries = 0;
291    raidrec->failed_disks.entries = 0;
292    raidrec->additional_vars.entries = 0;
293}
294#endif
295
296
297
298
299/**
300 * Insert modules that Mondo requires.
301 * Currently inserts @c dos, @c fat, @c vfat, and @c osst for Linux;
302 * @c msdosfs and @c ext2fs for FreeBSD.
303 */
304void insmod_crucial_modules(void)
305{
306#ifdef __FreeBSD__
307    system("kldstat | grep msdosfs || kldload msdosfs 2> /dev/null");
308    system("kldstat | grep ext2fs  || kldload ext2fs 2> /dev/null");
309#else
310    system("modprobe dos &> /dev/null");
311    system("modprobe fat &> /dev/null");
312    system("modprobe vfat &> /dev/null");
313    //  system("modprobe osst &> /dev/null");
314#endif
315}
316
317
318/**
319 * Log a trace message to the trace file.
320 * @bug This function seems orphaned. Please remove.
321 */
322void log_trace(char *o)
323{
324    /*@ pointers **************************************************** */
325    FILE *fout;
326
327    /*@ buffers ***************************************************** */
328    char output[MAX_STR_LEN];
329
330    /*@ int    ****************************************************** */
331    int i;
332
333    /*@ end vars *************************************************** */
334
335    if (o[0] == '\0') {
336        return;
337    }
338    strcpy(output, o);
339    i = (int) strlen(output);
340    if (i <= 0) {
341        return;
342    }
343    if (output[i - 1] < 32) {
344        output[i - 1] = '\0';
345    }
346    if (g_text_mode
347        /* && !strstr(last_line_of_file(MONDO_LOGFILE),output) */ ) {
348        printf("%s\n", output);
349    }
350
351    fout = fopen(MONDO_TRACEFILE, "a");
352    if (fout) {
353        fprintf(fout, "%s\n", output);
354        paranoid_fclose(fout);
355    } else {
356        log_OS_error("Cannot write to tracefile");
357    }
358}
359
360
361
362
363
364/**
365 * Finish configuring the backup information structure. Call this function
366 * to set the parameters that depend on those that can be given on the command
367 * line.
368 *
369 * @param bkpinfo The backup information structure. Fields modified/used:
370 * - Used: @c bkpinfo->backup_data
371 * - Used: @c bkpinfo->backup_media_type
372 * - Used: @c bkpinfo->cdrw_speed
373 * - Used: @c bkpinfo->compression_level
374 * - Used: @c bkpinfo->include_paths
375 * - Used: @c bkpinfo->prefix
376 * - Used: @c bkpinfo->isodir
377 * - Used: @c bkpinfo->manual_cd_tray
378 * - Used: @c bkpinfo->make_cd_use_lilo
379 * - Used: @c bkpinfo->media_device
380 * - Used: @c bkpinfo->nfs_mount
381 * - Used: @c bkpinfo->nonbootable_backup
382 * - Used: @c bkpinfo->scratchdir
383 * - Used: @c bkpinfo->tmpdir
384 * - Used: @c bkpinfo->use_lzo
385 * - Modified: @c bkpinfo->call_before_iso
386 * - Modified: @c bkpinfo->call_make_iso
387 * - Modified: @c bkpinfo->optimal_set_size
388 * - Modified: @c bkpinfo->zip_exe
389 * - Modified: @c bkpinfo->zip_suffix
390 *
391 * @return number of errors, or 0 for success.
392 * @note Also creates directories that are specified in the @c bkpinfo structure but
393 * do not exist.
394 */
395int post_param_configuration(struct s_bkpinfo *bkpinfo)
396{
397    char *extra_cdrom_params;
398    char *mondo_mkisofs_sz;
399    char *command;
400    char *mtpt;
401    char *hostname, *ip_address;
402    int retval = 0;
403    long avm = 0;
404    char *colon;
405    char *cdr_exe;
406    char *tmp;
407    char call_before_iso_user[MAX_STR_LEN] = "\0";
408    int rdsiz_MB;
409    char *iso_dev;
410    char *iso_mnt;
411    char *iso_tmp;
412    char *iso_path;
413    FILE *fd1 = NULL;
414
415    assert(bkpinfo != NULL);
416    malloc_string(extra_cdrom_params);
417    malloc_string(mondo_mkisofs_sz);
418    malloc_string(command);
419    malloc_string(mtpt);
420    malloc_string(hostname);
421    malloc_string(ip_address);
422    malloc_string(cdr_exe);
423    malloc_string(tmp);
424    malloc_string(iso_dev);
425    malloc_string(iso_mnt);
426    malloc_string(iso_tmp);
427    malloc_string(iso_path);
428    bkpinfo->optimal_set_size =
429        (IS_THIS_A_STREAMING_BACKUP(bkpinfo->backup_media_type) ? 16 : 16) *
430        1024;
431
432    mr_msg(1, "Foo");
433    if (bkpinfo->backup_media_type == tape) {
434        mr_msg(1, "Bar");
435        sprintf(tmp, "mt -f %s status", bkpinfo->media_device);
436        mr_msg(1, "tmp = '%s'", tmp);
437        if (run_program_and_log_output(tmp, 3)) {
438            fatal_error
439                ("Unable to open tape device. If you haven't specified it with -d, do so. If you already have, check your parameter. I think it's wrong.");
440        }
441    }
442    make_hole_for_dir(bkpinfo->scratchdir);
443    make_hole_for_dir(bkpinfo->tmpdir);
444    if (bkpinfo->backup_media_type == iso)
445        make_hole_for_dir(bkpinfo->isodir);
446
447    run_program_and_log_output("uname -a", 5);
448    run_program_and_log_output("cat /etc/*-release", 5);
449    run_program_and_log_output("cat /etc/*issue*", 5);
450    sprintf(g_tmpfs_mountpt, "%s/tmpfs", bkpinfo->tmpdir);
451    sprintf(command, "mkdir -p %s", g_tmpfs_mountpt);
452    paranoid_system(command);
453    rdsiz_MB = PPCFG_RAMDISK_SIZE + g_tape_buffer_size_MB;
454#ifdef __FreeBSD__
455    strcpy(tmp,
456           call_program_and_get_last_line_of_output
457           ("vmstat | tail -1 | tr -s ' ' | cut -d' ' -f6"));
458    avm += atol(tmp);
459    strcpy(tmp,
460           call_program_and_get_last_line_of_output
461           ("swapinfo | grep -v Device | tr -s ' ' | cut -d' ' -f4 | tr '\n' '+' | sed 's/+$//' | bc"));
462    avm += atol(tmp);
463    sprintf(command, "mdmfs -s %d%c md9 %s", rdsiz_MB, 'm',
464            g_tmpfs_mountpt);
465#else
466    strcpy(tmp,
467           call_program_and_get_last_line_of_output
468           ("free | grep ':' | tr -s ' ' '\t' | cut -f2 | head -n1"));
469    avm += atol(tmp);
470    sprintf(command, "mount /dev/shm -t tmpfs %s -o size=%d%c",
471            g_tmpfs_mountpt, rdsiz_MB, 'm');
472    run_program_and_log_output("cat /proc/cpuinfo", 5);
473    run_program_and_log_output
474        ("rpm -q newt newt-devel slang slang-devel ncurses ncurses-devel gcc",
475         5);
476#endif
477    if (avm / 1024 > rdsiz_MB * 3) {
478        if (run_program_and_log_output(command, 5)) {
479            g_tmpfs_mountpt[0] = '\0';
480            log_it("Failed to mount tmpfs");
481        } else {
482            log_it("Tmpfs mounted OK - %d MB", rdsiz_MB);
483        }
484    } else {
485        g_tmpfs_mountpt[0] = '\0';
486        log_it("It doesn't seem you have enough swap to use tmpfs. Fine.");
487    }
488
489    if (bkpinfo->use_lzo) {
490        strcpy(bkpinfo->zip_exe, "lzop");
491        strcpy(bkpinfo->zip_suffix, "lzo");
492    } else if (bkpinfo->use_gzip) {
493        strcpy(bkpinfo->zip_exe, "gzip");
494        strcpy(bkpinfo->zip_suffix, "gz");
495    } else if (bkpinfo->compression_level != 0) {
496        strcpy(bkpinfo->zip_exe, "bzip2");
497        strcpy(bkpinfo->zip_suffix, "bz2");
498    } else {
499        bkpinfo->zip_exe[0] = bkpinfo->zip_suffix[0] = '\0';
500    }
501
502// DVD
503
504    if (bkpinfo->backup_media_type == dvd) {
505        extra_cdrom_params[0] = '\0';
506        mondo_mkisofs_sz[0] = '\0';
507        if (find_home_of_exe("growisofs")) {
508            strcpy(cdr_exe, "growisofs");
509        }                       // unlikely to be used
510        else {
511            fatal_error("Please install growisofs.");
512        }
513        if (bkpinfo->nonbootable_backup) {
514            strcat(mondo_mkisofs_sz, MONDO_GROWISOFS_NONBOOT);
515        } else if
516#ifdef __FreeBSD__
517            (TRUE)
518#else
519            (bkpinfo->make_cd_use_lilo)
520#endif
521#ifdef __IA64__
522    {
523        strcat(mondo_mkisofs_sz, MONDO_GROWISOFS_REGULAR_ELILO);
524    }
525#else
526    {
527        strcat(mondo_mkisofs_sz, MONDO_GROWISOFS_REGULAR_LILO);
528    }
529#endif
530        else
531        {
532            strcat(mondo_mkisofs_sz, MONDO_GROWISOFS_REGULAR_SYSLINUX);
533        }
534        if (bkpinfo->manual_cd_tray) {
535            fatal_error("Manual CD tray + DVD not supported yet.");
536            // -m isn't supported by growisofs, BTW...
537        } else {
538            sprintf(bkpinfo->call_make_iso,
539                    "%s %s -Z %s . 2>> _ERR_",
540                    mondo_mkisofs_sz,
541                    extra_cdrom_params, bkpinfo->media_device);
542        }
543        if (getenv ("SUDO_COMMAND")) {
544            sprintf(command, "strings `which growisofs` | grep -c SUDO_COMMAND");
545            if (!strcmp(call_program_and_get_last_line_of_output(command), "1")) {
546                popup_and_OK("Fatal Error: Can't write DVDs as sudo because growisofs doesn't support this - see the growisofs manpage for details.");
547                fatal_error("Can't write DVDs as sudo because growisofs doesn't support this - see the growisofs manpage for details.");
548            }       
549        }
550        mr_msg(2, "call_make_iso (DVD res) is ... %s",
551                bkpinfo->call_make_iso);
552    }                           // end of DVD code
553
554// CD-R or CD-RW
555    if (bkpinfo->backup_media_type == cdrw
556        || bkpinfo->backup_media_type == cdr) {
557        extra_cdrom_params[0] = '\0';
558        if (!bkpinfo->manual_cd_tray) {
559            strcat(extra_cdrom_params, "-waiti ");
560        }
561        if (bkpinfo->backup_media_type == cdrw) {
562            strcat(extra_cdrom_params, "blank=fast ");
563        }
564        if (find_home_of_exe("cdrecord")) {
565            strcpy(cdr_exe, "cdrecord");
566        } else if (find_home_of_exe("dvdrecord")) {
567            strcpy(cdr_exe, "dvdrecord");
568        } else {
569            fatal_error("Please install either cdrecord or dvdrecord.");
570        }
571        if (bkpinfo->nonbootable_backup) {
572            strcpy(mondo_mkisofs_sz, MONDO_MKISOFS_NONBOOT);
573        } else if
574#ifdef __FreeBSD__
575            (TRUE)
576#else
577            (bkpinfo->make_cd_use_lilo)
578#endif
579#ifdef __IA64__
580    {
581        strcat(mondo_mkisofs_sz, MONDO_MKISOFS_REGULAR_ELILO);
582    }
583#else
584    {
585        strcpy(mondo_mkisofs_sz, MONDO_MKISOFS_REGULAR_LILO);
586    }
587#endif
588        else
589        {
590            strcpy(mondo_mkisofs_sz, MONDO_MKISOFS_REGULAR_SYSLINUX);
591        }
592        if (bkpinfo->manual_cd_tray) {
593            if (bkpinfo->call_before_iso[0] == '\0') {
594            sprintf(bkpinfo->call_before_iso,
595                        "%s -o %s/temporary.iso . 2>> _ERR_",
596                        mondo_mkisofs_sz, bkpinfo->tmpdir);
597                } else {
598                strncpy(call_before_iso_user, bkpinfo->call_before_iso, MAX_STR_LEN);
599                sprintf (bkpinfo->call_before_iso,
600                                    "( %s -o %s/temporary.iso . 2>> _ERR_ ; %s )",
601                        mondo_mkisofs_sz, bkpinfo->tmpdir, call_before_iso_user);
602            }
603            log_it("bkpinfo->call_before_iso = %s", bkpinfo->call_before_iso);
604            sprintf(bkpinfo->call_make_iso,
605                    "%s %s -v %s fs=4m dev=%s speed=%d %s/temporary.iso",
606                    cdr_exe, (bkpinfo->please_dont_eject) ? " " : "-eject",
607                    extra_cdrom_params, bkpinfo->media_device,
608                    bkpinfo->cdrw_speed, bkpinfo->tmpdir);
609        } else {
610            sprintf(bkpinfo->call_make_iso,
611                    "%s . 2>> _ERR_ | %s %s %s fs=4m dev=%s speed=%d -",
612                    mondo_mkisofs_sz, cdr_exe,
613                    (bkpinfo->please_dont_eject) ? " " : "-eject",
614                    extra_cdrom_params, bkpinfo->media_device,
615                    bkpinfo->cdrw_speed);
616        }
617    }                           // end of CD code
618
619    /*
620       if (bkpinfo->backup_data && bkpinfo->backup_media_type == tape)
621       {
622       sprintf (tmp,
623       "dd if=/dev/zero of=%s bs=%ld count=32 2> /dev/null",
624       bkpinfo->media_device, bkpinfo->internal_tape_block_size);
625       if (system(tmp))
626       {
627       retval++;
628       fprintf (stderr,
629       "Cannot write to tape device. Is the tape set read-only?\n");
630       }
631       } // end of tape code
632     */
633
634
635    if (bkpinfo->backup_media_type == iso) {
636
637/* Patch by Conor Daly <conor.daly@met.ie>
638 * 23-june-2004
639 * Break up isodir into iso_mnt and iso_path
640 * These will be used along with iso-dev at restore time
641 * to locate the ISOs where ever they're mounted
642 */
643
644        log_it("isodir = %s", bkpinfo->isodir);
645        sprintf(command, "df -P %s | tail -n1 | cut -d' ' -f1",
646                bkpinfo->isodir);
647        log_it("command = %s", command);
648        sprintf(iso_dev, "%s",
649                call_program_and_get_last_line_of_output(command));
650        log_it("res of it = %s", iso_dev);
651
652        fd1 = mr_fopen(MONDORESTORECFG, "a");
653        mr_fprintf(fd1, "iso-dev %s\n", iso_dev);
654
655        sprintf(command, "mount | grep -w %s | tail -n1 | cut -d' ' -f3",
656                iso_dev);
657        log_it("command = %s", command);
658        sprintf(iso_mnt, "%s",
659                call_program_and_get_last_line_of_output(command));
660
661        log_it("res of it = %s", iso_mnt);
662        mr_fprintf(fd1, "iso-mnt %s\n", iso_mnt);
663        log_it("isomnt: %s, %d", iso_mnt, strlen(iso_mnt));
664
665        sprintf(iso_tmp, "%s", bkpinfo->isodir);
666        if (strlen(iso_tmp) < strlen(iso_mnt)) {
667            iso_path[0] = '\0';
668        } else {
669            sprintf(iso_path, "%s", iso_tmp + strlen(iso_mnt));
670        }
671        log_it("isodir: %s", iso_path);
672        mr_fprintf(fd1, "isodir %s\n", iso_path);
673
674        log_it("iso-prefix: %s",  bkpinfo->prefix);
675        mr_fprintf(fd1, "iso-prefix %s\n", bkpinfo->prefix);
676
677        mr_fclose(fd1);
678    }                           // end of iso code
679
680    if (bkpinfo->backup_media_type == nfs) {
681        strcpy(hostname, bkpinfo->nfs_mount);
682        colon = strchr(hostname, ':');
683        if (!colon) {
684            log_it("nfs mount doesn't have a colon in it");
685            retval++;
686        } else {
687            struct hostent *hent;
688
689            *colon = '\0';
690            hent = gethostbyname(hostname);
691            if (!hent) {
692                log_it("Can't resolve NFS mount (%s): %s", hostname,
693                       hstrerror(h_errno));
694                retval++;
695            } else {
696                strcpy(ip_address, inet_ntoa
697                       ((struct in_addr)
698                        *((struct in_addr *) hent->h_addr)));
699                strcat(ip_address, strchr(bkpinfo->nfs_mount, ':'));
700                strcpy(bkpinfo->nfs_mount, ip_address);
701            }
702        }
703        store_nfs_config(bkpinfo);
704    }
705
706    log_it("Finished processing incoming params");
707    if (retval) {
708        fprintf(stderr, "Type 'man mondoarchive' for help.\n");
709    }
710    sprintf(tmp, "%s", MONDO_TMPISOS);  /* added #define 22 apr 2002 */
711    if (does_file_exist(tmp)) {
712        unlink(tmp);
713    }
714    if (strlen(bkpinfo->tmpdir) < 2 || strlen(bkpinfo->scratchdir) < 2) {
715        log_it("tmpdir or scratchdir are blank/missing");
716        retval++;
717    }
718    if (bkpinfo->include_paths[0] == '\0') {
719        //      fatal_error ("Why no backup path?");
720        strcpy(bkpinfo->include_paths, "/");
721    }
722    chmod(bkpinfo->scratchdir, 0700);
723    chmod(bkpinfo->tmpdir, 0700);
724    g_backup_media_type = bkpinfo->backup_media_type;
725    mr_free(mtpt);
726    mr_free(extra_cdrom_params);
727    mr_free(mondo_mkisofs_sz);
728    mr_free(command);
729    mr_free(hostname);
730    mr_free(ip_address);
731    mr_free(cdr_exe);
732    mr_free(tmp);
733    mr_free(iso_dev);
734    mr_free(iso_mnt);
735    mr_free(iso_tmp);
736    mr_free(iso_path);
737    return (retval);
738}
739
740
741
742/**
743 * Do some miscellaneous setup tasks to be performed before filling @c bkpinfo.
744 * Seeds the random-number generator, loads important modules, checks the sanity
745 * of the user's Linux distribution, and deletes logfile.
746 * @param bkpinfo The backup information structure. Will be initialized.
747 * @return number of errors (0 for success)
748 */
749int pre_param_configuration(struct s_bkpinfo *bkpinfo)
750{
751    int res = 0;
752
753    make_hole_for_dir(MNT_CDROM);
754    assert(bkpinfo != NULL);
755    srandom((unsigned long) (time(NULL)));
756    insmod_crucial_modules();
757    reset_bkpinfo(bkpinfo);     // also sets defaults ('/'=backup path, 3=compression level)
758    if (bkpinfo->disaster_recovery) {
759        if (!does_nonMS_partition_exist()) {
760            fatal_error
761                ("I am in disaster recovery mode\nPlease don't run mondoarchive.");
762        }
763    }
764
765    unlink(MONDO_TRACEFILE);
766    run_program_and_log_output("rm -Rf /tmp/changed.files*", FALSE);
767    if (find_and_store_mondoarchives_home(g_mondo_home)) {
768        fprintf(stderr,
769                "Cannot find Mondo's homedir. I think you have >1 'mondo' directory on your hard disk. Please delete the superfluous 'mondo' directories and try again\n");
770        res++;
771        return (res);
772    }
773    res += some_basic_system_sanity_checks();
774    if (res) {
775        log_it("Your distribution did not pass Mondo's sanity test.");
776    }
777    g_current_media_number = 1;
778    bkpinfo->postnuke_tarball[0] = bkpinfo->nfs_mount[0] = '\0';
779    return (res);
780}
781
782
783
784
785/**
786 * Reset all fields of the backup information structure to a sensible default.
787 * @param bkpinfo The @c bkpinfo to reset.
788 */
789void reset_bkpinfo(struct s_bkpinfo *bkpinfo)
790{
791    int i;
792
793    mr_msg(1, "Hi");
794    assert(bkpinfo != NULL);
795    memset((void *) bkpinfo, 0, sizeof(struct s_bkpinfo));
796    bkpinfo->manual_cd_tray = FALSE;
797    bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
798    bkpinfo->media_device[0] = '\0';
799    for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
800        bkpinfo->media_size[i] = -1;
801    }
802    bkpinfo->boot_loader = '\0';
803    bkpinfo->boot_device[0] = '\0';
804    bkpinfo->zip_exe[0] = '\0';
805    bkpinfo->zip_suffix[0] = '\0';
806    bkpinfo->restore_path[0] = '\0';
807    bkpinfo->use_lzo = FALSE;
808    bkpinfo->use_gzip = FALSE;
809    bkpinfo->do_not_compress_these[0] = '\0';
810    bkpinfo->verify_data = FALSE;
811    bkpinfo->backup_data = FALSE;
812    bkpinfo->restore_data = FALSE;
813    bkpinfo->disaster_recovery =
814        (am_I_in_disaster_recovery_mode()? TRUE : FALSE);
815    if (bkpinfo->disaster_recovery) {
816        strcpy(bkpinfo->isodir, "/");
817    } else {
818        strcpy(bkpinfo->isodir, "/root/images/mondo");
819    }
820    strcpy(bkpinfo->prefix, STD_PREFIX);
821
822    bkpinfo->scratchdir[0] = '\0';
823    bkpinfo->make_filelist = TRUE;  // unless -J supplied to mondoarchive
824    sprintf(bkpinfo->tmpdir, "/tmp/tmpfs/mondo.tmp.%d", (int) (random() % 32768));  // for mondorestore
825    bkpinfo->optimal_set_size = 0;
826    bkpinfo->backup_media_type = none;
827    strcpy(bkpinfo->include_paths, "/");
828    bkpinfo->exclude_paths[0] = '\0';
829    bkpinfo->call_before_iso[0] = '\0';
830    bkpinfo->call_make_iso[0] = '\0';
831    bkpinfo->call_burn_iso[0] = '\0';
832    bkpinfo->call_after_iso[0] = '\0';
833    bkpinfo->image_devs[0] = '\0';
834    bkpinfo->postnuke_tarball[0] = '\0';
835    bkpinfo->kernel_path[0] = '\0';
836    bkpinfo->nfs_mount[0] = '\0';
837    bkpinfo->nfs_remote_dir[0] = '\0';
838    bkpinfo->wipe_media_first = FALSE;
839    bkpinfo->differential = FALSE;
840    bkpinfo->cdrw_speed = 0;
841// patch by Herman Kuster 
842    bkpinfo->differential = 0;
843// patch end
844    bkpinfo->compression_level = 3;
845}
846
847
848
849
850/**
851 * Get the remaining free space (in MB) on @p partition.
852 * @param partition The partition to check free space on (either a device or a mountpoint).
853 * @return The free space on @p partition, in MB.
854 */
855long free_space_on_given_partition(char *partition)
856{
857    char command[MAX_STR_LEN], out_sz[MAX_STR_LEN];
858    long res;
859
860    assert_string_is_neither_NULL_nor_zerolength(partition);
861
862    sprintf(command, "df -m -P %s &> /dev/null", partition);
863    if (system(command)) {
864        return (-1);
865    }                           // partition does not exist
866    sprintf(command, "df -m -P %s | tail -n1 | tr -s ' ' '\t' | cut -f4",
867            partition);
868    strcpy(out_sz, call_program_and_get_last_line_of_output(command));
869    if (strlen(out_sz) == 0) {
870        return (-1);
871    }                           // error within df, probably
872    res = atol(out_sz);
873    return (res);
874}
875
876
877
878/**
879 * Check the user's system for sanity. Checks performed:
880 * - make sure user has enough RAM (32mb required, 64mb recommended)
881 * - make sure user has enough free space in @c /
882 * - check kernel for ramdisk support
883 * - make sure afio, cdrecord, mkisofs, bzip2, awk, md5sum, strings, mindi, and buffer exist
884 * - make sure CD-ROM is unmounted
885 * - make sure /etc/modules.conf exists
886 * - make sure user's mountlist is OK by running <tt>mindi --makemountlist</tt>
887 *
888 * @return number of problems with the user's setup (0 for success)
889 */
890int some_basic_system_sanity_checks()
891{
892
893    /*@ buffers ************ */
894    char tmp[MAX_STR_LEN];
895
896    /*@ int's *************** */
897    int retval = 0;
898    long Lres;
899
900
901    mvaddstr_and_log_it(g_currentY, 0, "Checking sanity of your Linux distribution");
902#ifndef __FreeBSD__
903    if (system("which mkfs.vfat &> /dev/null")
904        && !system("which mkfs.msdos &> /dev/null")) {
905        log_it
906            ("OK, you've got mkfs.msdos but not mkfs.vfat; time for the fairy to wave her magic wand...");
907        run_program_and_log_output
908            ("ln -sf `which mkfs.msdos` /sbin/mkfs.vfat", FALSE);
909    }
910    strcpy(tmp,
911           call_program_and_get_last_line_of_output
912           ("free | grep Mem | head -n1 | tr -s ' ' '\t' | cut -f2"));
913    if (atol(tmp) < 35000) {
914        retval++;
915        log_to_screen("You must have at least 32MB of RAM to use Mondo.");
916    }
917    if (atol(tmp) < 66000) {
918        log_to_screen
919            ("WARNING! You have very little RAM. Please upgrade to 64MB or more.");
920    }
921#endif
922
923    Lres = free_space_on_given_partition("/var/cache");
924    log_it("Free space on given partition = %ld MB", Lres);
925
926    if (Lres < 50) {
927              fatal_error("Your /var/cache partition has <50MB free. Please adjust your partition table to something saner."); 
928    }
929
930    if (system("which " MKE2FS_OR_NEWFS " > /dev/null 2> /dev/null")) {
931        retval++;
932        log_to_screen
933            ("Unable to find " MKE2FS_OR_NEWFS " in system path.");
934        fatal_error
935            ("Please use \"su -\", not \"su\" to become root. OK? ...and please don't e-mail the mailing list or me about this. Just read the message. :)");
936    }
937#ifndef __FreeBSD__
938    if (run_program_and_log_output
939        ("grep ramdisk /proc/devices", FALSE)) {
940        if (!ask_me_yes_or_no
941            ("Your kernel has no ramdisk support. That's mind-numbingly stupid but I'll allow it if you're planning to use a failsafe kernel. Are you?"))
942        {
943            //          retval++;
944            log_to_screen
945                ("It looks as if your kernel lacks ramdisk and initrd support.");
946            log_to_screen
947                ("I'll allow you to proceed but FYI, if I'm right, your kernel is broken.");
948        }
949    }
950#endif
951    retval += whine_if_not_found(MKE2FS_OR_NEWFS);
952    retval += whine_if_not_found("mkisofs");
953    if (system("which dvdrecord > /dev/null 2> /dev/null")) {
954        retval += whine_if_not_found("cdrecord");
955    }
956    retval += whine_if_not_found("bzip2");
957    retval += whine_if_not_found("gzip");
958    retval += whine_if_not_found("awk");
959    retval += whine_if_not_found("md5sum");
960    retval += whine_if_not_found("strings");
961    retval += whine_if_not_found("mindi");
962    retval += whine_if_not_found("buffer");
963
964    // abort if Windows partition but no ms-sys and parted
965    if (!run_program_and_log_output
966        ("mount | grep -w vfat | grep -vE \"/dev/fd|nexdisk\"", 0)
967        ||
968        !run_program_and_log_output
969        ("mount | grep -w dos | grep -vE \"/dev/fd|nexdisk\"", 0)) {
970        log_to_screen("I think you have a Windows 9x partition.");
971        retval += whine_if_not_found("parted");
972#ifndef __IA64__
973        /* IA64 always has one vfat partition for EFI even without Windows */
974        // retval +=
975        if (!find_home_of_exe("ms-sys")) {
976            log_to_screen("Please install ms-sys just in case.");
977        }
978#endif
979    }
980
981    if (!find_home_of_exe("cmp")) {
982        if (!find_home_of_exe("true")) {
983            whine_if_not_found("cmp");
984        } else {
985            log_to_screen
986                ("Your system lacks the 'cmp' binary. I'll create a dummy cmp for you.");
987            if (run_program_and_log_output
988                ("cp -f `which true` /usr/bin/cmp", 0)) {
989                fatal_error("Failed to create dummy 'cmp' file.");
990            }
991        }
992    }
993    run_program_and_log_output
994        ("umount `mount | grep cdr | cut -d' ' -f3 | tr '\n' ' '`", 5);
995    strcpy(tmp,
996           call_program_and_get_last_line_of_output
997           ("mount | grep -E \"cdr(om|w)\""));
998    if (strcmp("", tmp)) {
999        if (strstr(tmp, "autofs")) {
1000            log_to_screen
1001                ("Your CD-ROM is mounted via autofs. I therefore cannot tell");
1002            log_to_screen
1003                ("if a CD actually is inserted. If a CD is inserted, please");
1004            log_to_screen("eject it. Thank you.");
1005            log_it
1006                ("Ignoring autofs CD-ROM 'mount' since we hope nothing's in it.");
1007        } else
1008            if (run_program_and_log_output("uname -a | grep Knoppix", 5)) {
1009            retval++;
1010            fatal_error
1011                ("Your CD-ROM drive is mounted. Please unmount it.");
1012        }
1013    }
1014#ifndef __FreeBSD__
1015    if (!does_file_exist("/etc/modules.conf")) {
1016        if (does_file_exist("/etc/conf.modules")) {
1017            log_it("Linking /etc/modules.conf to /etc/conf.modules");
1018            run_program_and_log_output
1019                ("ln -sf /etc/conf.modules /etc/modules.conf", 5);
1020        } else if (does_file_exist("/etc/modprobe.d")) {
1021            log_it
1022                ("Directory /etc/modprobe.d found. mindi will use its contents.");
1023        } else if (does_file_exist("/etc/modprobe.conf")) {
1024            log_it("Linking /etc/modules.conf to /etc/modprobe.conf");
1025            run_program_and_log_output
1026                ("ln -sf /etc/modprobe.conf /etc/modules.conf", 5);
1027        } else {
1028            retval++;
1029            log_to_screen
1030                ("Please find out what happened to /etc/modules.conf");
1031        }
1032    }
1033#endif
1034
1035    run_program_and_log_output("cat /etc/fstab", 5);
1036#ifdef __FreeBSD__
1037    run_program_and_log_output("vinum printconfig", 5);
1038#else
1039    run_program_and_log_output("cat /etc/raidtab", 5);
1040#endif
1041
1042    if (run_program_and_log_output("mindi -V", 1)) {
1043        log_to_screen("Could not ascertain mindi's version number.");
1044        log_to_screen
1045            ("You have not installed Mondo and/or Mindi properly.");
1046        log_to_screen("Please uninstall and reinstall them both.");
1047        fatal_error("Please reinstall Mondo and Mindi.");
1048    }
1049    if (run_program_and_log_output
1050        ("mindi --makemountlist /tmp/mountlist.txt.test", 5)) {
1051        log_to_screen
1052            ("Mindi --makemountlist /tmp/mountlist.txt.test failed for some reason.");
1053        log_to_screen
1054            ("Please run that command by hand and examine /var/log/mindi.log");
1055        log_to_screen
1056            ("for more information. Perhaps your /etc/fstab file is insane.");
1057        log_to_screen
1058            ("Perhaps Mindi's MakeMountlist() subroutine has a bug. We'll see.");
1059        retval++;
1060    }
1061
1062    if (!run_program_and_log_output("parted2fdisk -l | grep -i raid", 1)
1063        && !does_file_exist("/etc/raidtab")) {
1064        log_to_screen
1065            ("You have RAID partitions but no /etc/raidtab - creating one from /proc/mdstat");
1066        create_raidtab_from_mdstat("/etc/raidtab");
1067    }
1068
1069    if (retval) {
1070        mvaddstr_and_log_it(g_currentY++, 74, "Failed.");
1071    } else {
1072        mvaddstr_and_log_it(g_currentY++, 74, "Done.");
1073    }
1074    return (retval);
1075}
1076
1077/**
1078 * Retrieve the line containing @p label from the config file.
1079 * @param config_file The file to read from, usually @c /tmp/mondo-restore.cfg.
1080 * @param label What to read from the file.
1081 * @param value Where to put it.
1082 * @return 0 for success, 1 for failure.
1083 */
1084int read_cfg_var(char *config_file, char *label, char *value)
1085{
1086    /*@ buffer ****************************************************** */
1087    char command[MAX_STR_LEN * 2];
1088    char tmp[MAX_STR_LEN];
1089
1090    /*@ end vars *************************************************** */
1091
1092    assert_string_is_neither_NULL_nor_zerolength(config_file);
1093    assert_string_is_neither_NULL_nor_zerolength(label);
1094    if (!does_file_exist(config_file)) {
1095        sprintf(tmp, "(read_cfg_var) Cannot find %s config file",
1096                config_file);
1097        log_to_screen(tmp);
1098        value[0] = '\0';
1099        return (1);
1100    } else if (strstr(value, "/dev/") && strstr(value, "t0")
1101               && !strcmp(label, "media-dev")) {
1102        mr_msg(2, "FYI, I shan't read new value for %s - already got %s",
1103                label, value);
1104        return (0);
1105    } else {
1106        sprintf(command, "grep '%s .*' %s| cut -d' ' -f2,3,4,5",
1107                label, config_file);
1108        strcpy(value, call_program_and_get_last_line_of_output(command));
1109        if (strlen(value) == 0) {
1110            return (1);
1111        } else {
1112            return (0);
1113        }
1114    }
1115}
1116
1117
1118
1119/**
1120 * Remount @c supermount if it was unmounted earlier.
1121 */
1122void remount_supermounts_if_necessary()
1123{
1124    if (g_remount_cdrom_at_end) {
1125        run_program_and_log_output("mount " MNT_CDROM, FALSE);
1126    }
1127    if (g_remount_floppy_at_end) {
1128        run_program_and_log_output("mount " MNT_FLOPPY, FALSE);
1129    }
1130}
1131
1132/**
1133 * Unmount @c supermount if it's mounted.
1134 */
1135void unmount_supermounts_if_necessary()
1136{
1137    if (run_program_and_log_output
1138        ("mount | grep cdrom | grep super", FALSE) == 0) {
1139        g_remount_cdrom_at_end = TRUE;
1140        run_program_and_log_output("umount " MNT_CDROM, FALSE);
1141    }
1142    if (run_program_and_log_output
1143        ("mount | grep floppy | grep super", FALSE) == 0) {
1144        g_remount_floppy_at_end = TRUE;
1145        run_program_and_log_output("umount " MNT_FLOPPY, FALSE);
1146    }
1147}
1148
1149/**
1150 * Whether we had to stop autofs (if so, restart it at end).
1151 */
1152bool g_autofs_stopped = FALSE;
1153
1154/**
1155 * Path to the autofs initscript ("" if none exists).
1156 */
1157char g_autofs_exe[MAX_STR_LEN];
1158
1159/**
1160 * Autofs initscript in Xandros Linux distribution.
1161 */
1162#define XANDROS_AUTOFS_FNAME "/etc/init.d/xandros-autofs"
1163
1164/**
1165 * Autofs initscript in most Linux distributions.
1166 */
1167#define STOCK_AUTOFS_FNAME "/etc/rc.d/init.d/autofs"
1168
1169/**
1170 * If autofs is mounted, stop it (restart at end).
1171 */
1172void stop_autofs_if_necessary()
1173{
1174    char tmp[MAX_STR_LEN];
1175
1176    g_autofs_exe[0] = '\0';
1177    if (does_file_exist(XANDROS_AUTOFS_FNAME)) {
1178        strcpy(g_autofs_exe, XANDROS_AUTOFS_FNAME);
1179    } else if (does_file_exist(STOCK_AUTOFS_FNAME)) {
1180        strcpy(g_autofs_exe, STOCK_AUTOFS_FNAME);
1181    }
1182
1183    if (!g_autofs_exe[0]) {
1184        mr_msg(3, "No autofs detected.");
1185    } else {
1186        mr_msg(3, "%s --- autofs detected", g_autofs_exe);
1187// FIXME -- only disable it if it's running ---  sprintf(tmp, "%s status", autofs_exe);
1188        sprintf(tmp, "%s stop", g_autofs_exe);
1189        if (run_program_and_log_output(tmp, 2)) {
1190            log_it("Failed to stop autofs - I assume it wasn't running");
1191        } else {
1192            g_autofs_stopped = TRUE;
1193            log_it("Stopped autofs OK");
1194        }
1195    }
1196}
1197
1198/**
1199 * If autofs was stopped earlier, restart it.
1200 */
1201void restart_autofs_if_necessary()
1202{
1203    char tmp[MAX_STR_LEN];
1204
1205    if (!g_autofs_stopped || !g_autofs_exe[0]) {
1206        mr_msg(3, "No autofs detected.");
1207        return;
1208    }
1209    sprintf(tmp, "%s start", g_autofs_exe);
1210    if (run_program_and_log_output(tmp, 2)) {
1211        log_it("Failed to start autofs");
1212    } else {
1213        g_autofs_stopped = FALSE;
1214        log_it("Started autofs OK");
1215    }
1216}
1217
1218
1219/**
1220 * If this is a distribution like Gentoo that doesn't keep /boot mounted, mount it.
1221 */
1222void mount_boot_if_necessary()
1223{
1224    char tmp[MAX_STR_LEN];
1225    char command[MAX_STR_LEN];
1226
1227    mr_msg(1, "Started sub");
1228    mr_msg(4, "About to set g_boot_mountpt[0] to '\\0'");
1229    g_boot_mountpt[0] = '\0';
1230    mr_msg(4, "Done. Great. Seeting command to something");
1231    strcpy(command,
1232           "grep -v \":\" /etc/fstab | grep -vE '^#.*$' | grep -E \"[   ]/boot[     ]\" | tr -s ' ' '\t' | cut -f1 | head -n1");
1233    mr_msg(4, "Cool. Command = '%s'", command);
1234    strcpy(tmp, call_program_and_get_last_line_of_output(command));
1235    mr_msg(4, "tmp = '%s'", tmp);
1236    if (tmp[0]) {
1237        log_it("/boot is at %s according to /etc/fstab", tmp);
1238        if (strstr(tmp, "LABEL=")) {
1239            if (!run_program_and_log_output("mount /boot", 5)) {
1240                strcpy(g_boot_mountpt, "/boot");
1241                mr_msg(1, "Mounted /boot");
1242            } else {
1243                log_it("...ignored cos it's a label :-)");
1244            }
1245        } else {
1246            sprintf(command, "mount | grep -E '^%s'", tmp);
1247            mr_msg(3, "command = %s", command);
1248            if (run_program_and_log_output(command, 5)) {
1249                strcpy(g_boot_mountpt, tmp);
1250                sprintf(tmp,
1251                        "%s (your /boot partition) is not mounted. I'll mount it before backing up",
1252                        g_boot_mountpt);
1253                log_it(tmp);
1254                sprintf(tmp, "mount %s", g_boot_mountpt);
1255                if (run_program_and_log_output(tmp, 5)) {
1256                    g_boot_mountpt[0] = '\0';
1257                    mr_msg(1, "Plan B");
1258                    if (!run_program_and_log_output("mount /boot", 5)) {
1259                        strcpy(g_boot_mountpt, "/boot");
1260                        mr_msg(1, "Plan B worked");
1261                    } else {
1262                        mr_msg(1,
1263                                "Plan B failed. Unable to mount /boot for backup purposes. This probably means /boot is mounted already, or doesn't have its own partition.");
1264                    }
1265                }
1266            }
1267        }
1268    }
1269    mr_msg(1, "Ended sub");
1270}
1271
1272
1273/**
1274 * If we mounted /boot earlier, unmount it.
1275 */
1276void unmount_boot_if_necessary()
1277{
1278    char tmp[MAX_STR_LEN];
1279
1280    mr_msg(3, "starting");
1281    if (g_boot_mountpt[0]) {
1282        sprintf(tmp, "umount %s", g_boot_mountpt);
1283        if (run_program_and_log_output(tmp, 5)) {
1284            log_it("WARNING - unable to unmount /boot");
1285        }
1286    }
1287    mr_msg(3, "leaving");
1288}
1289
1290
1291
1292/**
1293 * Write a line to a configuration file. Writes a line of the form,
1294 * @c label @c value.
1295 * @param config_file The file to write to. Usually @c mondo-restore.cfg.
1296 * @param label What to call this bit of data you're writing.
1297 * @param value The bit of data you're writing.
1298 * @return 0 for success, 1 for failure.
1299 */
1300int write_cfg_var(char *config_file, char *label, char *value)
1301{
1302    /*@ buffers ***************************************************** */
1303    char command[MAX_STR_LEN * 2];
1304    char tempfile[MAX_STR_LEN];
1305    char tmp[MAX_STR_LEN];
1306
1307
1308    /*@ end vars *************************************************** */
1309    assert_string_is_neither_NULL_nor_zerolength(config_file);
1310    assert_string_is_neither_NULL_nor_zerolength(label);
1311    assert(value != NULL);
1312    if (!does_file_exist(config_file)) {
1313        sprintf(tmp, "(write_cfg_file) Cannot find %s config file",
1314                config_file);
1315        log_to_screen(tmp);
1316        return (1);
1317    }
1318    strcpy(tempfile,
1319           call_program_and_get_last_line_of_output
1320           ("mktemp -q /tmp/mojo-jojo.blah.XXXXXX"));
1321    if (does_file_exist(config_file)) {
1322        sprintf(command, "grep -vE '^%s .*$' %s > %s",
1323                label, config_file, tempfile);
1324        paranoid_system(command);
1325    }
1326    sprintf(command, "echo \"%s %s\" >> %s", label, value, tempfile);
1327    paranoid_system(command);
1328    sprintf(command, "mv -f %s %s", tempfile, config_file);
1329    paranoid_system(command);
1330    unlink(tempfile);
1331    return (0);
1332}
1333
1334
1335/**
1336 * The standard log_debug_msg() (mr_msg() also due to a macro). Writes some describing
1337 * information to the logfile.
1338 */
1339void standard_log_debug_msg(int debug_level, const char *szFile,
1340                            const char *szFunction, int nLine,
1341                            const char *fmt, ...)
1342{
1343    va_list args;
1344    int i;
1345    static int depth = 0;
1346    char *tmp;
1347    FILE *fout;
1348
1349    if (depth > 5) {
1350        depth--;
1351        return;
1352    }
1353    depth++;
1354
1355    malloc_string(tmp);
1356
1357    if (debug_level <= g_loglevel) {
1358        va_start(args, fmt);
1359        if (!(fout = fopen(MONDO_LOGFILE, "a"))) {
1360            return;
1361        }                       // fatal_error("Failed to openout to logfile - sheesh..."); }
1362
1363        // add tabs to distinguish log levels
1364        if (debug_level > 0) {
1365            for (i = 1; i < debug_level; i++)
1366                fprintf(fout, "\t");
1367            if (getpid() == g_main_pid)
1368                fprintf(fout, "[Main] %s->%s#%d: ", szFile, szFunction,
1369                        nLine);
1370            else if (getpid() == g_buffer_pid && g_buffer_pid > 0)
1371                fprintf(fout, "[Buff] %s->%s#%d: ", szFile, szFunction,
1372                        nLine);
1373            else
1374                fprintf(fout, "[TH=%d] %s->%s#%d: ", getpid(), szFile,
1375                        szFunction, nLine);
1376        }
1377        vfprintf(fout, fmt, args);
1378
1379        // do not slow down the progran if standard debug level
1380        // must be enabled: if no flush, the log won't be up-to-date if there
1381        // is a segfault
1382        //if (g_dwDebugLevel != 1)
1383
1384        va_end(args);
1385        fprintf(fout, "\n");
1386        paranoid_fclose(fout);
1387    }
1388    depth--;
1389    mr_free(tmp);
1390}
1391
1392/**
1393 * Function pointer to the @c log_debug_msg function to use. Points to standard_log_debug_msg() by default.
1394 */
1395void (*log_debug_msg) (int, const char *, const char *, int, const char *,
1396                       ...) = standard_log_debug_msg;
1397
1398
1399/**
1400 * If @p y, malloc @p x, else free @p x.
1401 * @bug This function seems orphaned. Please remove.
1402 */
1403#define do_alloc_or_free_depending(x,y) { if(y) {x=mr_malloc(MAX_STR_LEN);} else {mr_free(x);} }
1404
1405/**
1406 * Allocate or free important globals, depending on @p mal.
1407 * @param mal If TRUE, malloc; if FALSE, free.
1408 */
1409void do_libmondo_global_strings_thing(int mal)
1410{
1411    if (mal) {
1412        iamhere("Malloc'ing globals");
1413        malloc_string(g_boot_mountpt);
1414        malloc_string(g_mondo_home);
1415        malloc_string(g_tmpfs_mountpt);
1416        malloc_string(g_erase_tmpdir_and_scratchdir);
1417        malloc_string(g_serial_string);
1418        malloc_string(g_magicdev_command);
1419    } else {
1420        iamhere("Freeing globals");
1421        mr_free(g_boot_mountpt);
1422        mr_free(g_mondo_home);
1423        mr_free(g_tmpfs_mountpt);
1424        mr_free(g_erase_tmpdir_and_scratchdir);
1425        mr_free(g_serial_string);
1426        mr_free(g_magicdev_command);
1427    }
1428
1429    /*
1430       char**list_of_arrays[] = {
1431       &g_boot_mountpt,
1432       &g_mondo_home,
1433       &g_tmpfs_mountpt,
1434       &g_erase_tmpdir_and_scratchdir,
1435       &g_serial_string,
1436       &g_magicdev_command,
1437       NULL};
1438
1439       char**ppcurr;
1440       int i;
1441
1442       for(i=0;list_of_arrays[i];i++)
1443       {
1444       mr_msg(5, "Allocating %d", i);
1445       ppcurr = list_of_arrays[i];
1446       if (mal)
1447       { *ppcurr = malloc(MAX_STR_LEN); }
1448       else
1449       {
1450       if (*ppcurr)
1451       {
1452       free(*ppcurr);
1453       }
1454       }
1455       }
1456       mr_msg(5, "Returning");
1457     */
1458}
1459
1460/**
1461 * Allocate important globals.
1462 * @see do_libmondo_global_strings_thing
1463 */
1464void malloc_libmondo_global_strings(void)
1465{
1466    do_libmondo_global_strings_thing(1);
1467}
1468
1469/**
1470 * Free important globals.
1471 * @see do_libmondo_global_strings_thing
1472 */
1473void free_libmondo_global_strings(void)
1474{
1475    do_libmondo_global_strings_thing(0);
1476}
1477
1478
1479
1480/**
1481 * Stop @c magicdev if it's running.
1482 * The command used to start it is saved in @p g_magicdev_command.
1483 */
1484void stop_magicdev_if_necessary()
1485{
1486    strcpy(g_magicdev_command,
1487           call_program_and_get_last_line_of_output
1488           ("ps ax | grep -w magicdev | grep -v grep | tr -s '\t' ' '| cut -d' ' -f6-99"));
1489    if (g_magicdev_command[0]) {
1490        mr_msg(1, "g_magicdev_command = '%s'", g_magicdev_command);
1491        paranoid_system("killall magicdev");
1492    }
1493}
1494
1495
1496/**
1497 * Restart magicdev if it was stopped.
1498 */
1499void restart_magicdev_if_necessary()
1500{
1501    char *tmp;
1502
1503    malloc_string(tmp);
1504    if (g_magicdev_command && g_magicdev_command[0]) {
1505        sprintf(tmp, "%s &", g_magicdev_command);
1506        paranoid_system(tmp);
1507    }
1508    mr_free(tmp);
1509}
1510
1511/* @} - end of utilityGroup */
Note: See TracBrowser for help on using the repository browser.