source: MondoRescue/branches/2.2.10/mondo/src/common/libmondo-tools.c@ 2508

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

r3287@localhost (orig r2285): bruno | 2009-07-20 11:36:47 +0200

r3285@localhost: bruno | 2009-07-20 11:17:35 +0200
Apply fix in 2.2.10 around multi USB device handling to 2.2.9 as well


r3291@localhost (orig r2288): bruno | 2009-07-21 16:48:31 +0200
Copy 2.2.10 test script in to 2.2.9 for memory problm analysis


r3293@localhost (orig r2290): bruno | 2009-07-22 14:03:44 +0200

  • Fix a printing error in mindi for the tar command
  • Fix all mr_asprintf which had no second param as a string


r3295@localhost (orig r2292): bruno | 2009-07-22 16:55:00 +0200

  • Fix #160 and #346 by rewriting the message.txt file with more valid information gathered in mindi


r3300@localhost (orig r2294): bruno | 2009-07-23 01:58:08 +0200

Man pages patch from Joe Ross (joe.ross_at_gmail.com)


r3303@localhost (orig r2297): bruno | 2009-07-23 17:43:49 +0200
Fix a remaining display error for 2.2.9. That version has been tested OK in a lab.


r3304@localhost (orig r2298): bruno | 2009-07-23 18:18:27 +0200

  • Remove memory leak for the last modification


r3308@localhost (orig r2302): bruno | 2009-07-24 21:18:50 +0200
Improve logging of mountlist.txt


r3310@localhost (orig r2304): bruno | 2009-07-27 19:45:10 +0200

  • popup_and_get_string needs an allocated buffer for the moment so fixing the calls with dyn. ones
  • Fix a bug in mem.c for mr_strcat, which wasn't modifying the right pointer level


r3311@localhost (orig r2305): bruno | 2009-07-27 19:49:35 +0200
Avoid a memory leak in the previous patch


r3314@localhost (orig r2308): bruno | 2009-07-27 20:59:06 +0200
Fix a bug in mr_strcat backported from 2.2.10. Should solve our seg faults.


r3315@localhost (orig r2309): bruno | 2009-07-28 02:14:23 +0200
Cosmetic changes to allow for quality to not giv false positive


r3343@localhost (orig r2311): bruno | 2009-08-18 02:13:43 +0200
Fix for initramfs detection with 2.6.30 (Hugo Vanwoerkom hvw59601_at_care2.com)


r3367@localhost (orig r2333): bruno | 2009-08-18 16:26:26 +0200
Adds a precision for -U option in man page on raw device usage and not partition name


r3373@localhost (orig r2336): bruno | 2009-08-20 17:37:41 +0200

  • Precise the combined usage of -E and -I in mondoarchive (Case 4601017223)


r3379@localhost (orig r2342): bruno | 2009-08-21 16:27:10 +0200


r3383@localhost (orig r2344): bruno | 2009-08-24 13:37:09 +0200

r3382@localhost: bruno | 2009-08-24 13:30:25 +0200
In NFS mode also propose access to expert, interactive, ... entry at boot prompt


r3388@localhost (orig r2346): bruno | 2009-08-27 11:41:16 +0200
Adds fdisk -l result in Log File at restore time


r3389@localhost (orig r2347): bruno | 2009-08-27 13:51:00 +0200

  • Solve tmp dir creation which sometimes was trying to create /%xx dirs. Should fix #293 for good


r3390@localhost (orig r2348): bruno | 2009-08-27 13:54:25 +0200
Improve logging (minor)


r3394@localhost (orig r2350): bruno | 2009-08-28 02:24:19 +0200
Change inerface of evaluate_mountlist and spread_flaws_across_three_lines in order to solve bugs linked to strings management in these functions. May fix a restoration crash seen by some customers


r3397@localhost (orig r2353): bruno | 2009-08-28 19:03:45 +0200

  • Addition of a nomd option to avoid starting mdadm
  • mpath is now already started if there was a mpath entry in mountlist


r3399@localhost (orig r2355): bruno | 2009-08-29 00:56:50 +0200
Remove function spread_flaws_across_three_lines and expand it at the single place where it was useful, and fix memory allocation issues in it.


r3402@localhost (orig r2358): bruno | 2009-09-01 19:02:35 +0200
P2V doc updated (Lester Wade lester.wade_at_hp.com)


r3404@localhost (orig r2360): bruno | 2009-09-01 19:26:53 +0200
Website update to refer to new P2V document


r3405@localhost (orig r2361): bruno | 2009-09-03 13:54:25 +0200

  • Fix a case where the NFS dir in restore mode was mounted rw (linked to bug #291 could create a huge problem)


r3407@localhost (orig r2363): bruno | 2009-09-03 14:46:46 +0200
More verbose at installation of additional tools


r3409@localhost (orig r2365): bruno | 2009-09-03 18:08:32 +0200

  • New update from Lester Wade (lester.wade_at_hp.com) for P2V doc


r3410@localhost (orig r2366): bruno | 2009-09-05 01:28:18 +0200
place the code of mondo_makefilelist before its call



r3411@localhost (orig r2367): bruno | 2009-09-06 01:51:26 +0200

  • Advertising for project-builder on the website added


r3412@localhost (orig r2368): bruno | 2009-09-07 15:36:23 +0200
Fix compilation issue


r3413@localhost (orig r2369): bruno | 2009-09-07 18:03:40 +0200
Another compilation issue fixed.


r3415@localhost (orig r2371): bruno | 2009-09-08 13:40:25 +0200

  • Fix a problem a error detection in evaluate_mountlist which casued nuke mode to abort. Error string should also be better now.


r3417@localhost (orig r2373): bruno | 2009-09-08 13:55:31 +0200
Avoid asking the Prefix name in NFS mode twice


r3418@localhost (orig r2374): bruno | 2009-09-08 20:04:07 +0200

  • Try to fix garbled screen progression in text mode based on 2.2.10 modifications which are working


r3424@localhost (orig r2380): bruno | 2009-09-09 20:30:47 +0200

  • Change NFS support into a NetFS support to allow for multiple protocol in addition to NFS (NEEDS TESTING)
  • Better logging to detect a potential nuke issue


r3425@localhost (orig r2381): bruno | 2009-09-10 02:05:55 +0200
Fix a missing param for sshfs call


r3428@localhost (orig r2384): bruno | 2009-09-10 13:02:56 +0200

  • Remove separate function look_for_duplicate_mountpoints used only once and whose interface created problems with caller


r3430@localhost (orig r2386): bruno | 2009-09-10 16:06:52 +0200
Be compatible on backup type by making old nfs recognized as netfs and proto forced


r3431@localhost (orig r2387): bruno | 2009-09-10 18:40:47 +0200
Fix a problem in netfs analysis in mondoarchive


r3432@localhost (orig r2388): bruno | 2009-09-10 20:25:13 +0200
Fix mondoarchive CLI analysis for NETFS type of requests


r3434@localhost (orig r2390): bruno | 2009-09-11 03:05:20 +0200

  • Adds ext3 initrd support for 2.6.30


r3437@localhost (orig r2393): bruno | 2009-09-11 11:56:52 +0200

  • Tries to add support for bzip2 and lzma initramfs (preliminary, not tested) for 2.6.30


r3438@localhost (orig r2394): bruno | 2009-09-12 02:53:02 +0200
Fix interface of evaluate_mountlist (remove 2nd param useless) and fix nuke mode which wasn't working.


r3441@localhost (orig r2397): bruno | 2009-09-14 18:54:34 +0200
Fix a format issue in text mode on percentage


r3452@localhost (orig r2398): bruno | 2009-09-15 16:00:13 +0200

  • Fix a bug where flaws_str could be NULL and wasn't tested correctly.


r3453@localhost (orig r2399): bruno | 2009-09-15 19:28:39 +0200

  • Use protocol name when displaying restore progress instead of netfs
  • Ask for network protocol name at restore time


r3455@localhost (orig r2401): bruno | 2009-09-15 19:34:19 +0200
Wrong structure member name was used


r3456@localhost (orig r2402): bruno | 2009-09-16 13:04:17 +0200
Use dir for shell related commands and dir1 for C related actions in open_and_list_dir to avoid missing some files with { in names e.g.


r3457@localhost (orig r2403): bruno | 2009-09-16 16:32:03 +0200

  • At restore time read the netfs protocol in the conf file


r3462@localhost (orig r2408): bruno | 2009-09-18 15:17:08 +0200
Remove useless script


r3463@localhost (orig r2409): bruno | 2009-09-18 15:25:35 +0200

  • Split deplist.txt into multiple conf files under deplist.d in the conf dir. This will allow to have a minimal.conf file for initrd content to analyze to improve support of new embedded feature in the future (sshfs, live install). The other conf files contain the additional commands to put in the all.tar.gz. For the moment, mindi is still working the same. THis infra will allow that support in a near future. deplist.txt is now reserved for the admin additional commands.


r3465@localhost (orig r2410): bruno | 2009-09-18 19:10:54 +0200

  • Better list of mandatory tools
  • Adds fuse and sshfs support in initrd


r3466@localhost (orig r2411): bruno | 2009-09-18 20:32:47 +0200
sshfs also needs ssh at restore time in initrd


r3478@localhost (orig r2418): bruno | 2009-09-23 23:22:39 +0200
Modify getfattr call to have all extended attributes, including non user ones. (patch from Kevin Ritzenthaler Kevin.Ritzenthaler_at_hp.com) and fix #357


r3479@localhost (orig r2419): bruno | 2009-09-23 23:50:34 +0200
star only supports ACL when used with exustar mode. Fix #356.


r3482@localhost (orig r2422): bruno | 2009-09-24 16:53:24 +0200

  • Adds support for bnx2x (BL 460 G6) and auth_rpcgss (Debian 2.6.31)


r3485@localhost (orig r2423): bruno | 2009-09-25 16:38:40 +0200
Fix an issue in is_this_device_mounted (string freed before last usage)


r3486@localhost (orig r2424): bruno | 2009-09-25 18:44:01 +0200

  • analyze-my-lvm now removes excluded devices from list coming from mondoarchive
  • new mr_make_devlist_from_pathlist which handle the new bkpinfo->exclude_devs field containing the excluded devices and remove corresponding code from libmondo-cli.c
  • Move DSF code into libmondo-devices.c for coherency, and only the previous function is made externally available
  • Remove dev_to_exclude in libmondo-archive.c which wasn't working correctly and replace it with bkpinfo->exclude_devs


r3487@localhost (orig r2425): bruno | 2009-09-25 18:58:23 +0200

  • Improving ssh support at restore time by providing a shadow file


r3489@localhost (orig r2426): bruno | 2009-09-25 19:42:09 +0200

  • Attempt to stay backward compatible without protocol for -n option


r3490@localhost (orig r2427): bruno | 2009-09-28 02:08:06 +0200
Avoids null param for excludes_devs for mindi call


r3492@localhost (orig r2429): bruno | 2009-09-28 11:46:16 +0200

  • Simplify GetInitrdFilesystemToUse which doesn't need to detect everything, but just know if it's initramfs (new mode) or a compressed FS ext2/3 (older mode) as initrd is anyway re-made by mindi. Should fix #353


r3494@localhost (orig r2431): bruno | 2009-09-28 13:16:18 +0200

  • Use only the AWK veriable everywhere and not the awk command


r3495@localhost (orig r2432): bruno | 2009-09-28 14:16:31 +0200
Warning emited in case of duplicate mountpoints or devices in fstab found


r3496@localhost (orig r2433): bruno | 2009-09-28 15:55:17 +0200
ssh in the restore env needs some dlopened libs (libnss_compat|files)


r3497@localhost (orig r2434): bruno | 2009-09-28 16:33:14 +0200
Compiler warning fixed


r3498@localhost (orig r2435): bruno | 2009-09-28 17:55:26 +0200
Improve user management for NetFS cases


r3499@localhost (orig r2436): bruno | 2009-09-29 01:48:32 +0200

  • Improve deplist.d/* files
  • adds libnss for ssh support in boot disk
  • Solve a memory management issue in DSF module (strtok => mr_strtok)
  • DSF now also supports partitions in addition to full disks
  • Adds debug in open_and_list_dir


r3500@localhost (orig r2437): bruno | 2009-09-29 10:41:56 +0200

  • Fix udev support in init for Mandriva 2009.1 (udevadm settle is blocking)


r3501@localhost (orig r2438): bruno | 2009-09-29 14:41:36 +0200

  • Improvements on sshfs/ssh management in restore mode
  • Include now all minimal requirements for sshfs


r3502@localhost (orig r2439): bruno | 2009-09-29 18:46:08 +0200

  • Avoids error message if some ssh conf files do not exist


r3503@localhost (orig r2440): bruno | 2009-09-29 18:57:13 +0200

  • Avoids comment analysis in the new code handling deplist.d


r3504@localhost (orig r2441): bruno | 2009-09-29 19:34:34 +0200

  • fuse device is needed at restore time for sshfs


r3505@localhost (orig r2442): bruno | 2009-09-29 20:02:36 +0200

  • Improves udev timeout handling


r3506@localhost (orig r2443): bruno | 2009-09-29 20:43:38 +0200

  • priority given to env var for tmpdir
  • fuse FS excluded from tmpdir computation


r3518@localhost (orig r2447): bruno | 2009-10-04 01:58:08 +0200

  • Iprove USB log in case of error by adding the conf file


r3519@localhost (orig r2448): bruno | 2009-10-05 11:06:13 +0200


r3520@localhost (orig r2449): bruno | 2009-10-06 01:10:35 +0200

  • Adds support for grub2 conf file grub.cfg in addition to menu.lst


r3521@localhost (orig r2450): bruno | 2009-10-06 01:24:02 +0200

  • Fix a mr_asprintf usage without & causing a seg fault.


r3523@localhost (orig r2452): bruno | 2009-10-06 12:47:56 +0200
CIFS mounts shouldn't be part of the mountlist analysis (should help solving #288)


r3524@localhost (orig r2453): bruno | 2009-10-07 10:17:03 +0200

  • Fix a bug in handling of -E option with real devices (bad report in function mr_make_devlist_from_pathlist of the test between -E and -I)


r3525@localhost (orig r2454): bruno | 2009-10-07 10:19:02 +0200

  • Fix an error in the test for grub conf files (or used instead of and)


r3526@localhost (orig r2455): bruno | 2009-10-07 16:14:59 +0200
afio is under /bin on Debian


r3527@localhost (orig r2456): bruno | 2009-10-07 17:31:26 +0200

  • Adds support for libcrc32c (needed by bnx2x)


r3532@localhost (orig r2457): bruno | 2009-10-09 13:33:44 +0200

  • Apply path from Matthew Cline (matt_at_nightrealms.com) in order to fix #359


r3533@localhost (orig r2458): bruno | 2009-10-09 13:41:02 +0200
Adds a conf file example for mindi and fix #360


r3535@localhost (orig r2459): bruno | 2009-10-09 15:13:01 +0200
MOde of conf file


r3546@localhost (orig r2461): bruno | 2009-10-14 01:12:24 +0200

  • umount freshly created VFAT partition on USB key as Ubunu has an automounter mounting it as soon as created (Steffen Neumann sneumann_at_ipb-halle.de)


r3566@localhost (orig r2463): bruno | 2009-10-26 01:34:16 +0100

  • Reset an error counter before blanking a DVD to avoid always returning an error (Vincent Raman vincent.raman_at_macqel.eu)


r3567@localhost (orig r2464): bruno | 2009-10-26 13:57:14 +0100
bzip2 is under /bin on Debian


r3568@localhost (orig r2465): bruno | 2009-10-28 01:46:30 +0100
some distro hold lvm commands under /usr/sbin


r3595@localhost (orig r2469): bruno | 2009-11-10 12:22:10 +0100
/dev/shm is now part of the default exclude list


r3596@localhost (orig r2470): bruno | 2009-11-10 12:32:40 +0100
Remove useless pb_log and MONDO_TRACEFILE


r3597@localhost (orig r2471): bruno | 2009-11-10 12:57:58 +0100
Improve analysis of kernel modules by printing whether it's a live or extra module which has not been found (Matthew Cline) as reported in #362


r3598@localhost (orig r2472): bruno | 2009-11-10 13:21:46 +0100

  • Default to DVD size when in iso or netfs mode


r3599@localhost (orig r2473): bruno | 2009-11-10 14:13:10 +0100

  • Fix #363 where exclude_paths was extended up to memory limit dumping core


r3600@localhost (orig r2474): bruno | 2009-11-10 14:31:14 +0100

  • Update deplist for Debian support


r3602@localhost (orig r2476): bruno | 2009-11-11 02:44:42 +0100

  • small improvement for loging in USB case


r3603@localhost (orig r2477): bruno | 2009-11-11 13:29:27 +0100

  • Adds a nolvm boot option at restore time


r3604@localhost (orig r2478): bruno | 2009-11-11 19:54:51 +0100

  • Fix #367 - the for loop doesn't make any test now, as it was computed before entering the loop, leading to an error, and was also made inside the loop anyway.


r3605@localhost (orig r2479): bruno | 2009-11-12 00:32:45 +0100

  • Add support for diskdumplib driver useful for RHEL 3 and IBM xseries 336


r3606@localhost (orig r2480): bruno | 2009-11-12 01:09:40 +0100

  • If using nolvm, mondorestore should also not nalyze and handle i-want-my-lvm


r3608@localhost (orig r2482): bruno | 2009-11-14 12:54:11 +0100
Fix bunzip2 on debian as well


r3610@localhost (orig r2484): bruno | 2009-11-15 00:44:19 +0100

  • Adds support for variable serial port console, with defalut to /dev/ttyS0, and a boot param to change it with serial=/dev/ttySx


r3615@localhost (orig r2485): bruno | 2009-11-15 01:34:33 +0100

r3614@localhost: bruno | 2009-11-15 01:34:12 +0100
Adds a space in exclude paths


r3623@localhost (orig r2487): bruno | 2009-11-18 20:41:40 +0100

r3620@localhost: bruno | 2009-11-18 10:31:36 +0100

  • Only link /dev/tty to serial port when there is indeed a serial port. If not breaks mondorestore on normal console


r3631@localhost (orig r2490): bruno | 2009-11-24 01:48:29 +0100
Put news below in the main page to make it more readable


r3648@localhost (orig r2492): bruno | 2009-11-25 23:50:13 +0100

r3647@localhost: bruno | 2009-11-25 23:49:11 +0100

  • Add warning for -f and SW Raid as in 2.2.10


r3650@localhost (orig r2493): bruno | 2009-11-26 00:19:52 +0100

r3649@localhost: bruno | 2009-11-26 00:18:27 +0100

  • Addition of the german translation made by Magnus Rasche (Magnus.rasche_at_gmx.de) and Website inclusion


r3652@localhost (orig r2495): bruno | 2009-11-27 15:55:55 +0100
cosmetic display fix
r3659@localhost (orig r2498): bruno | 2009-12-05 17:53:03 +0100
nfsopt restore boot time option added to support custom mount options for network restore


r3684@localhost (orig r2501): bruno | 2009-12-17 00:35:08 +0100
Fix #375 mondo will segfault if the partition in sensibly_set_tmpdir_and_scratchdir() is read-only (cylau)


r3685@localhost (orig r2502): bruno | 2009-12-17 01:02:47 +0100

  • Fix an issue in the function listing kernel modules when not found


r3686@localhost (orig r2503): bruno | 2009-12-17 01:15:01 +0100
Adds scsi_dump_register to mindi SCSI_MODS for RHEL3 + IBM servers


r3701@localhost (orig r2504): bruno | 2009-12-23 02:24:33 +0100

  • Addition of the Lab for Mondorescue


r3702@localhost (orig r2505): bruno | 2009-12-23 02:41:17 +0100
Web site update for Lab MondoRescue delivery


r3706@localhost (orig r2506): bruno | 2010-01-04 11:31:53 +0100

  • Fix a bug when isodir is / only when splitting it in iso_path and iso_mnt


r3707@localhost (orig r2507): bruno | 2010-01-04 13:22:49 +0100

  • Fix #377: Segfault in pause_and_ask_for_cdr() (ggeens)


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