source: branches/2.2.9/mondo/src/common/libmondo-tools.c @ 2194

Last change on this file since 2194 was 2194, checked in by Bruno Cornec, 11 years ago

Some SuSE have ramdisk as modules, so modprobe brd first before testing for ramdisk presence

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