source: trunk/mondo/src/common/libmondo-tools.c @ 900

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

Huge patch to introduce low level functions that will bw used everywhere (mr_free, mr_asprintf, ...)
Nearly linking now due to that.

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