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

Last change on this file since 1178 was 1178, checked in by bruno, 13 years ago

Continue to merge trunk memory management enhancements for libmondo-tools.c & libmondo-string.c
Introduction + test of a new function mr_strcat

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