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

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

gettext fixes + last and i int removed (were forgotten)

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