source: MondoRescue/branches/2.2.10/mondo/src/common/newt-specific.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: 42.8 KB
Line 
1/* newt-specific.c
2 $Id: newt-specific.c 2508 2010-01-04 18:21:55Z bruno $
3
4 subroutines which do display-type things
5 and use the newt library to do them
6*/
7
8
9/**
10 * @file
11 * Functions for doing display-type things with the Newt library.
12 */
13
14#define MAX_NEWT_COMMENT_LEN 200
15
16#if __cplusplus
17extern "C" {
18#endif
19
20#include "my-stuff.h"
21#include "mr_mem.h"
22#include "mr_str.h"
23#include "mondostructures.h"
24#include "newt-specific.h"
25#include "libmondo-string-EXT.h"
26#include "libmondo-files-EXT.h"
27#include "libmondo-devices-EXT.h"
28#include "libmondo-tools-EXT.h"
29#include "libmondo-fork-EXT.h"
30#include "libmondo-gui-EXT.h"
31#include "lib-common-externs.h"
32
33extern char *MONDO_LOGFILE;
34
35extern struct s_bkpinfo *bkpinfo;
36extern void mr_free_bkpinfo();
37
38/*@unused@*/
39//static char cvsid[] = "$Id: newt-specific.c 2508 2010-01-04 18:21:55Z bruno $";
40
41 extern pid_t g_mastermind_pid;
42 /*
43 extern char *g_tmpfs_mountpt;
44 */
45 extern char *g_boot_mountpt;
46 extern char *ps_options;
47 extern char *ps_proc_id;
48
49 extern void set_signals(int);
50
51/**
52 * @addtogroup globalGroup
53 * @{
54 */
55/**
56 * Whether we are currently in a nested call of fatal_error().
57 */
58 bool g_exiting = FALSE;
59
60/**
61 * Padding below the Newt components, to overcome bugs in Newt.
62 */
63 char g_haharrrrr[500];
64
65
66 newtComponent g_timeline = NULL, ///< The line of the progress form that shows the time elapsed/remaining
67 g_percentline = NULL, ///< The line of the progress form that shows the percent completed/remaining
68 g_scale = NULL, ///< The progress bar component in the progress form
69 g_progressForm = NULL, ///< The progress form component itself
70 g_blurb1 = NULL, ///< The component for line 1 of the blurb in the progress form
71 g_blurb2 = NULL, ///< The component for line 2 of the blurb in the progress form
72 g_blurb3 = NULL, ///< The component for line 3 (updated continuously) of the blurb in the progress form
73 g_label = NULL; ///< ????? @bug ?????
74
75/**
76 * Padding above the Newt components, to overcome bugs in Newt.
77 */
78 char g_jim_lad_yarr[500];
79 char **err_log_lines = NULL, ///< The list of log lines to show on the screen.
80 g_blurb_str_1[MAX_NEWT_COMMENT_LEN] = "", ///< The string for line 1 of the blurb in the progress form
81 g_blurb_str_2[MAX_NEWT_COMMENT_LEN] = "", ///< The string for line 2 of the blurb in the progress form
82 g_blurb_str_3[MAX_NEWT_COMMENT_LEN] = ""; ///< The string for line 3 (updated continuously) of the blurb in the progress form
83 newtComponent g_isoform_main = NULL, ///< The evalcall form component itself
84 g_isoform_header = NULL, ///< The component for the evalcall form title
85 g_isoform_scale = NULL, ///< The progress bar component in the evalcall form
86 g_isoform_timeline = NULL, ///< The line of the evalcall form that shows the time elapsed/remaining
87 g_isoform_pcline = NULL; ///< The line of the evalcall form that shows the percent completed/remaining
88 long g_isoform_starttime; ///< The time (in seconds since the epoch) that the evalcall form was opened.
89 int g_isoform_old_progress = -1; ///< The most recent progress update of the evalcall form (percent).
90 char g_isoform_header_str[MAX_STR_LEN] = " "; ///< The string for the evalcall form title.
91 int g_mysterious_dot_counter; ///< The counter for the twirling baton (/ | \\ - ...) on percentage less than 3
92 int g_noof_log_lines = 6; ///< The number of lines to show in the log at the bottom of the screen.
93 int g_noof_rows = 25; ///< The number of rows on the screen.
94
95 int g_currentY = 3; ///< The row to write background progress messages to. Incremented each time a message is written.
96 extern int g_current_media_number;
97 pid_t g_main_pid = 0; ///< The PID of the main Mondo process.
98 long g_maximum_progress = 999L; ///< The maximum amount of progress (100%) for the currently opened progress form.
99 long g_current_progress = -999; ///< The current amount of progress (filelist #, etc.) for the currently opened progress form.
100 long g_start_time = 0L; ///< The time (in seconds since the epoch) that the progress form was opened.
101 bool g_text_mode = TRUE; ///< If FALSE, use a newt interface; if TRUE, use an ugly (but more compatible) dumb terminal interface.
102 char *g_selfmounted_isodir; ///< Holds the NETFS mountpoint if mounted via mondoarchive.
103
104/* @} - end of globalGroup */
105
106 void popup_and_OK(char *);
107
108
109/**
110 * @addtogroup guiGroup
111 * @{
112 */
113/**
114 * Ask the user a yes/no question.
115 * @param prompt The question to ask the user.
116 * @return TRUE for yes; FALSE for no.
117 */
118 bool ask_me_yes_or_no(char *prompt) {
119
120 /*@ buffers ********************************************************** */
121 int i;
122 char *tmp;
123
124 assert_string_is_neither_NULL_nor_zerolength(prompt);
125
126 if (g_text_mode) {
127 while (1) {
128 sync();
129 printf("---promptdialogYN---1--- %s\n---promptdialogYN---Q--- [yes] [no] ---\n--> ", prompt);
130 mr_getline(tmp, stdin);
131 if (tmp[strlen(tmp) - 1] == '\n')
132 tmp[strlen(tmp) - 1] = '\0';
133
134 i = (int) strlen(tmp);
135 if (i > 0 && tmp[i - 1] < 32) {
136 tmp[i - 1] = '\0';
137 }
138 if (strstr("yesYES", tmp)) {
139 mr_free(tmp);
140 return (TRUE);
141 } else if (strstr("NOno", tmp)) {
142 mr_free(tmp);
143 return (FALSE);
144 } else {
145 sync();
146 printf("Please enter either YES or NO (or yes or no, or y or n, or...)\n");
147 }
148 }
149 } else {
150 return (popup_with_buttons(prompt, "Yes", "No"));
151 }
152 }
153
154
155/**
156 * Give the user the opportunity to continue the current operation (OK)
157 * or cancel it (Cancel).
158 * @param prompt The string to be displayed.
159 * @return TRUE for OK, FALSE for Cancel.
160 */
161 bool ask_me_OK_or_cancel(char *prompt) {
162
163 /*@ buffer *********************************************************** */
164 char *tmp = NULL;
165 int i;
166
167 assert_string_is_neither_NULL_nor_zerolength(prompt);
168
169 if (g_text_mode) {
170 sync();
171 printf("---promptdialogOKC---1--- %s\n---promptdialogOKC---Q--- [OK] [Cancel] ---\n--> ", prompt);
172 mr_getline(tmp, stdin);
173 if (tmp[strlen(tmp) - 1] == '\n')
174 tmp[strlen(tmp) - 1] = '\0';
175
176 i = (int) strlen(tmp);
177 if (i > 0 && tmp[i - 1] < 32) {
178 tmp[i - 1] = '\0';
179 }
180 if (strstr("okOKOkYESyes", tmp)) {
181 mr_free(tmp);
182 return (TRUE);
183 } else {
184 mr_free(tmp);
185 return (FALSE);
186 }
187 } else {
188 return (popup_with_buttons(prompt, " Okay ", "Cancel"));
189 }
190 }
191
192
193
194/**
195 * Close the currently opened evalcall form.
196 */
197 void
198 close_evalcall_form(void) {
199 if (g_text_mode) {
200 return;
201 }
202 if (g_isoform_main == NULL) {
203 return;
204 }
205 update_evalcall_form(100);
206 usleep(500000);
207 if (g_text_mode) {
208 log_msg(2, "Closing evalcall form");
209 return;
210 }
211 newtPopHelpLine();
212 newtFormDestroy(g_isoform_main);
213 newtPopWindow();
214
215 /* Reset globals */
216 g_isoform_main = NULL;
217 g_isoform_old_progress = -1;
218 g_isoform_header = NULL;
219 g_isoform_scale = NULL;
220 g_isoform_timeline = NULL;
221 g_isoform_pcline = NULL;
222}
223
224/**
225 * Close the currently opened progress form.
226 */
227 void
228 close_progress_form() {
229 if (g_text_mode) {
230 return;
231 }
232 if (g_current_progress == -999) {
233 log_msg(2, "Trying to close the progress form when it ain't open!");
234 return;
235 }
236 g_current_progress = g_maximum_progress;
237 update_progress_form("Complete");
238 sleep(1);
239 if (g_text_mode) {
240 log_msg(2, "Closing progress form");
241 return;
242 }
243 newtPopHelpLine();
244 newtFormDestroy(g_progressForm);
245 newtPopWindow();
246
247 /* Reset globals */
248 g_progressForm = NULL;
249 g_current_progress = -999;
250 g_timeline = NULL;
251 g_percentline = NULL;
252 g_scale = NULL;
253
254 }
255
256/**
257 * Kill any process containing the string @p str surrounded by spaces in its commandline.
258 */
259void kill_anything_like_this(char *str) {
260
261char *tmp = NULL;
262char *tmp1 = NULL;
263
264 mr_asprintf(tmp,"ps %s | grep \" %s \" | awk '{print %s;}' | grep -v \"grep\"", ps_options, str , ps_proc_id);
265 run_program_and_log_output(tmp, TRUE);
266 if (strlen(tmp) > 0) {
267 mr_asprintf(tmp1,"kill `%s`", tmp);
268 run_program_and_log_output(tmp1, TRUE);
269 mr_free(tmp1);
270 }
271 mr_free(tmp);
272}
273
274
275/**
276 * Exit Mondo with a fatal error.
277 * @param error_string The error message to present to the user before exiting.
278 * @note This function never returns.
279 */
280void fatal_error(char *error_string) {
281
282 /*@ buffers ***************************************************** */
283 char *command = NULL;
284 static bool already_exiting = FALSE;
285
286 /*@ end vars **************************************************** */
287
288 set_signals(FALSE); // link to external func
289 g_exiting = TRUE;
290 log_msg(1, "Fatal error received - '%s'", error_string);
291 printf("Fatal error... %s\n", error_string);
292 if (getpid() == g_mastermind_pid) {
293 log_msg(2, "mastermind %d is exiting", (int) getpid());
294 kill(g_main_pid, SIGTERM);
295 finish(1);
296 }
297
298 if (getpid() != g_main_pid) {
299 if (g_mastermind_pid != 0 && getpid() != g_mastermind_pid) {
300 log_msg(2, "non-m/m %d is exiting", (int) getpid());
301 kill(g_main_pid, SIGTERM);
302 finish(1);
303 }
304 }
305
306 log_msg(3, "OK, I think I'm the main PID.");
307 if (already_exiting) {
308 log_msg(3, "...I'm already exiting. Give me time, Julian!");
309 finish(1);
310 }
311
312 already_exiting = TRUE;
313 log_msg(2, "I'm going to do some cleaning up now.");
314 paranoid_system("killall mindi 2> /dev/null");
315 kill_anything_like_this("/mondo/do-not");
316 kill_anything_like_this("tmp.mondo");
317 kill_anything_like_this("ntfsclone");
318 sync();
319
320 chdir("/");
321 if (g_selfmounted_isodir) {
322 mr_asprintf(command, "umount %s", g_selfmounted_isodir);
323 run_program_and_log_output(command, 5);
324 mr_free(command);
325 mr_asprintf(command, "rmdir %s", g_selfmounted_isodir);
326 run_program_and_log_output(command, 5);
327 mr_free(command);
328 }
329
330 if (!g_text_mode) {
331 log_msg(0, "-------FATAL ERROR---------");
332 log_msg(0, error_string);
333 }
334
335 printf("---FATALERROR--- %s\n", error_string);
336 printf("If you require technical support, please contact the mailing list.\n");
337 printf("See http://www.mondorescue.org for details.\n");
338 printf("The list's members can help you, if you attach that file to your e-mail.\n");
339 printf("Log file: %s\n", MONDO_LOGFILE);
340 printf("Mondo has aborted.\n");
341 if (!g_main_pid) {
342 log_msg(3, "FYI - g_main_pid is blank");
343 }
344 finish(254);
345 }
346
347/* Free memory allocated for newt */
348void free_newt_stuff() {
349
350int i;
351
352for (i = 0; i < g_noof_log_lines; i++) {
353 mr_free(err_log_lines[i]);
354}
355mr_free(err_log_lines);
356}
357
358
359
360/**
361 * Exit Mondo normally.
362 * @param signal The exit code (0 indicates a successful backup; 1 for Mondo means the
363 * user aborted; 254 means a fatal error occured).
364 * @note This function never returns.
365 */
366void finish(int signal) {
367
368 char *command = NULL;
369
370 chdir("/");
371 run_program_and_log_output("umount " MNT_CDROM, FALSE);
372 if (g_selfmounted_isodir) {
373 mr_asprintf(command, "umount %s", g_selfmounted_isodir);
374 run_program_and_log_output(command, 1);
375 mr_free(command);
376
377 mr_asprintf(command, "rmdir %s", g_selfmounted_isodir);
378 run_program_and_log_output(command, 1);
379 mr_free(command);
380 }
381 if (bkpinfo->tmpdir) {
382 log_msg(8,"tempdir is %s",bkpinfo->tmpdir);
383 if (strstr(bkpinfo->tmpdir ,"mondo.tmp.") != NULL) {
384 log_msg(8,"erasing tempdir");
385 mr_asprintf(command, "rm -Rf %s", bkpinfo->tmpdir);
386 system(command);
387 mr_free(command);
388 }
389 }
390 if (bkpinfo->scratchdir) {
391 log_msg(8,"scratchdir is %s", bkpinfo->scratchdir);
392 if (strstr(bkpinfo->scratchdir ,"mondo.scratch.") != NULL) {
393 log_msg(8,"erasing scratchdir");
394 mr_asprintf(command, "rm -Rf %s", bkpinfo->scratchdir);
395 system(command);
396 mr_free(command);
397 }
398 }
399 /* Free all allocated strings in bkpinfo */
400 mr_free_bkpinfo();
401 free_libmondo_global_strings();
402 free_newt_stuff();
403 if (!g_text_mode) {
404 log_msg(1, "Calling newtFinished()");
405 newtFinished();
406 }
407 printf("Execution run ended; result=%d\n", signal);
408 printf("Type 'less %s' to see the output log\n", MONDO_LOGFILE);
409 exit(signal);
410 }
411
412
413/**
414 * Log the last @p g_noof_log_lines lines of @p filename that match @p
415 * grep_for_me to the screen.
416 * @param filename The file to give the end of.
417 * @param grep_for_me If not "", then only give lines in @p filename that match this regular expression.
418 */
419void log_file_end_to_screen(char *filename, char *grep_for_me) {
420
421 /*@ buffers ********************************************************** */
422 char *command = NULL;
423 char *tmp = NULL;
424
425 /*@ pointers ********************************************************* */
426 FILE *fin;
427
428 /*@ int ************************************************************** */
429 int i = 0;
430
431 assert_string_is_neither_NULL_nor_zerolength(filename);
432 assert(grep_for_me != NULL);
433
434 if (!does_file_exist(filename)) {
435 return;
436 }
437 if (grep_for_me[0] != '\0') {
438 mr_asprintf(command, "grep '%s' %s | tail -n%d", grep_for_me, filename, g_noof_log_lines);
439 } else {
440 mr_asprintf(command, "tail -n%d %s", g_noof_log_lines, filename);
441 }
442 fin = popen(command, "r");
443 if (!fin) {
444 log_OS_error(command);
445 } else {
446 for (i = 0; i < g_noof_log_lines; i++) {
447 for (err_log_lines[i][0] = '\0';
448 strlen(err_log_lines[i]) < 2 && !feof(fin);) {
449 (void) fgets(err_log_lines[i], MAX_NEWT_COMMENT_LEN, fin);
450 /* Commented to make valgrind happy and avoid crash
451 strip_spaces(err_log_lines[i]);
452 */
453 if (!strncmp(err_log_lines[i], "root:", 5)) {
454 mr_asprintf(tmp, "%s", err_log_lines[i] + 6);
455 strcpy(err_log_lines[i], tmp);
456 mr_free(tmp);
457 }
458 if (feof(fin)) {
459 break;
460 }
461 }
462 }
463 paranoid_pclose(fin);
464 }
465 mr_free(command);
466 refresh_log_screen();
467 }
468
469
470/**
471 * Log a message to the screen.
472 * @param fmt A printf-style format string to write. The following parameters are its arguments.
473 * @note The message is also written to the logfile.
474 */
475void log_to_screen(const char *fmt, ...) {
476
477 /*@ int ************************************************************** */
478 int i = 0;
479 int j = 0;
480 va_list args;
481
482 /*@ buffers ********************************************************** */
483 char *output;
484
485 malloc_string(output);
486
487 va_start(args, fmt);
488 vsprintf(output, fmt, args);
489 log_msg(0, output);
490 output[80] = '\0';
491 va_end(args);
492 i = (int) strlen(output);
493 if (i > 0 && output[i - 1] < 32) {
494 output[i - 1] = '\0';
495 }
496
497 if (err_log_lines) {
498 for (i = 1; i < g_noof_log_lines; i++) {
499 strcpy(err_log_lines[i - 1],
500 " ");
501 strcpy(err_log_lines[i - 1], err_log_lines[i]);
502 }
503 }
504 while (strlen(output) > 0 && output[strlen(output) - 1] < 32) {
505 output[strlen(output) - 1] = '\0';
506 }
507 for (j = 0; j < (int) strlen(output); j++) {
508 if (output[j] < 32) {
509 output[j] = ' ';
510 }
511 }
512 if (err_log_lines)
513 strcpy(err_log_lines[g_noof_log_lines - 1], output);
514 if (g_text_mode) {
515 printf("%s\n", output);
516 } else {
517 refresh_log_screen();
518 }
519 paranoid_free(output);
520 }
521
522
523
524
525/**
526 * Write a string to the root window at (@p x, @p y) and also to the logfile.
527 * @param y The row to write the string to.
528 * @param x The column to write the string to.
529 * @param output The string to write.
530 */
531void mvaddstr_and_log_it(int y, int x, char *output) {
532
533 assert_string_is_neither_NULL_nor_zerolength(output);
534 log_msg(0, output);
535 if (g_text_mode) {
536 printf("%s\n", output);
537 } else {
538 newtDrawRootText(x, y, output);
539 newtRefresh();
540 }
541 }
542
543
544
545
546/**
547 * Open an evalcall form with title @p ttl.
548 * @param ttl The title to use for the evalcall form.
549 */
550void open_evalcall_form(char *ttl) {
551
552 /*@ buffers ********************************************************* */
553 char *title = NULL;
554 char *tmp = NULL;
555
556 /*@ initialize ****************************************************** */
557 g_isoform_old_progress = -1;
558 g_mysterious_dot_counter = 0;
559
560 assert(ttl != NULL);
561 malloc_string(tmp);
562 mr_asprintf(title, "%s", ttl);
563 strcpy(g_isoform_header_str, title);
564 if (g_text_mode) {
565 log_msg(0, title);
566 } else {
567 strcpy(tmp, title);
568 center_string(tmp, 80);
569 newtPushHelpLine(tmp);
570 }
571 center_string(g_isoform_header_str, 36);
572 g_isoform_starttime = get_time();
573 if (g_text_mode) {
574 log_msg(0, g_isoform_header_str);
575 } else {
576 g_isoform_header = newtLabel(1, 1, g_isoform_header_str);
577 g_isoform_scale = newtScale(3, 3, 34, 100);
578 newtCenteredWindow(40, 7, title);
579 g_isoform_main = newtForm(NULL, NULL, 0);
580 g_isoform_timeline = newtLabel(1, 5, "This is the timeline");
581 g_isoform_pcline = newtLabel(1, 6, "This is the pcline");
582 newtFormAddComponents(g_isoform_main, g_isoform_timeline,
583 g_isoform_pcline, g_isoform_header,
584 g_isoform_scale, NULL);
585 newtRefresh();
586 }
587 update_evalcall_form(0);
588 mr_free(title);
589 paranoid_free(tmp);
590 }
591
592
593
594/**
595 * Open a progress form with title @p title.
596 * @param title The title to use for the progress form (will be put in the title bar on Newt).
597 * @param b1 The first line of the blurb; generally static.
598 * @param b2 The second line of the blurb; generally static.
599 * @param b3 The third line of the blurb; generally dynamic (it is passed
600 * to update_evalcall_form() every time).
601 * @param max_val The maximum amount of progress (number of filesets, etc.)
602 */
603void open_progress_form(char *title, char *b1, char *b2, char *b3, long max_val) {
604
605 /*@ buffers ********************************************************* */
606 char *b1c;
607 char *blurb1 = NULL;
608 char *blurb2 = NULL;
609 char *blurb3 = NULL;
610
611 /*@ initialize ****************************************************** */
612 g_mysterious_dot_counter = 0;
613
614 malloc_string(b1c);
615
616 assert(title != NULL);
617 assert(b1 != NULL);
618 assert(b2 != NULL);
619 assert(b3 != NULL);
620
621 mr_asprintf(blurb1, "%s", b1);
622 mr_asprintf(blurb2, "%s", b2);
623 mr_asprintf(blurb3, "%s", b3);
624
625 strcpy(b1c, b1);
626 center_string(b1c, 80);
627 if (max_val <= 0) {
628 max_val = 1;
629 }
630
631 g_start_time = get_time();
632 g_maximum_progress = max_val;
633 g_current_progress = 0;
634 strcpy(g_blurb_str_1, blurb1);
635 strcpy(g_blurb_str_2, blurb3);
636 strcpy(g_blurb_str_3, blurb2);
637 if (g_text_mode) {
638 log_msg(0, blurb1);
639 log_msg(0, blurb2);
640 log_msg(0, blurb3);
641 } else {
642 g_blurb1 = newtLabel(2, 1, blurb1);
643 g_blurb2 = newtLabel(2, 2, blurb3);
644 g_blurb3 = newtLabel(2, 4, blurb2);
645 newtCenteredWindow(60, 11, title);
646 g_scale = newtScale(3, 6, 54, (long long)g_maximum_progress);
647 g_progressForm = newtForm(NULL, NULL, 0);
648 g_percentline = newtLabel(10, 9, "This is the percentline");
649 g_timeline = newtLabel(10, 8, "This is the timeline");
650 newtFormAddComponents(g_progressForm, g_percentline, g_timeline, g_scale, g_blurb1, g_blurb3, g_blurb2, NULL);
651 newtPushHelpLine(b1c);
652 newtRefresh();
653 }
654 update_progress_form_full(blurb1, blurb2, blurb3);
655 paranoid_free(b1c);
656 mr_free(blurb1);
657 mr_free(blurb2);
658 mr_free(blurb3);
659 }
660
661/**
662 * Give a message to the user in the form of a dialog box (under Newt).
663 * @param prompt The message.
664 */
665void popup_and_OK(char *prompt) {
666
667 char ch;
668
669 assert_string_is_neither_NULL_nor_zerolength(prompt);
670
671 log_msg(0, prompt);
672 if (g_text_mode) {
673 printf("---promptpopup---1--- %s\n---promptpopup---Q--- [OK] ---\n--> ", prompt);
674 while (((ch = getchar()) != '\n') && (ch != EOF));
675 } else {
676 (void) popup_with_buttons(prompt, " OK ", "");
677 }
678 }
679
680/**
681 * Ask the user to enter a value.
682 * @param title The title of the dialog box.
683 * @param b The blurb (e.g. what you want the user to enter).
684 * @param input The string given originaly as default
685 * @return output string if the user pressed OK, NULL if they pressed Cancel.
686 */
687char *popup_and_get_string(char *title, char *b, char *input) {
688
689 /*@ newt ************************************************************ */
690 newtComponent myForm;
691 newtComponent b_1;
692 newtComponent b_2;
693 newtComponent b_res;
694 newtComponent text;
695 newtComponent type_here;
696
697 /*@ pointers ********************************************************* */
698 char *entry_value;
699
700 /*@ buffers ********************************************************** */
701 char *blurb = NULL;
702 char *output = NULL;
703
704 assert_string_is_neither_NULL_nor_zerolength(title);
705 assert(b != NULL);
706
707 if (g_text_mode) {
708 printf("---promptstring---1--- %s\n---promptstring---2--- %s\n---promptstring---Q--- [%s]\n--> ", title, b, input);
709 mr_getline(output, stdin);
710 if (! strcmp(output,"\n")) {
711 /* take default if ENTER was typed */
712 mr_free(output);
713 mr_asprintf(output, "%s", input);
714 }
715 if (output[strlen(output) - 1] == '\n')
716 output[strlen(output) - 1] = '\0';
717 return (output);
718 }
719
720 mr_asprintf(blurb, "%s", b);
721 text = newtTextboxReflowed(2, 1, blurb, 48, 5, 5, 0);
722 type_here = newtEntry(2, newtTextboxGetNumLines(text) + 2, input, 50,
723#ifdef __cplusplus
724 0, NEWT_FLAG_RETURNEXIT
725#else
726 (void *) &entry_value, NEWT_FLAG_RETURNEXIT
727#endif
728 );
729 b_1 = newtButton(6, newtTextboxGetNumLines(text) + 4, " OK ");
730 b_2 = newtButton(18, newtTextboxGetNumLines(text) + 4, "Cancel");
731 newtCenteredWindow(54, newtTextboxGetNumLines(text) + 9, title);
732 myForm = newtForm(NULL, NULL, 0);
733 newtFormAddComponents(myForm, text, type_here, b_1, b_2, NULL);
734 center_string(blurb, 80);
735 newtPushHelpLine(blurb);
736 b_res = newtRunForm(myForm);
737
738 if (b_res == b_1) {
739 mr_asprintf(output, "%s", newtEntryGetValue(type_here));
740 }
741 newtPopHelpLine();
742 newtFormDestroy(myForm);
743 newtPopWindow();
744 mr_free(blurb);
745
746 return (output);
747 }
748
749
750/**
751 * Pop up a dialog box with user-defined buttons.
752 * @param p The text to put in the dialog box.
753 * @param button1 The label on the first button.
754 * @param button2 The label on the second button, or "" if you only want one button.
755 * @return TRUE if @p button1 was pushed, FALSE otherwise.
756 */
757bool popup_with_buttons(char *p, char *button1, char *button2) {
758
759 /*@ buffers *********************************************************** */
760 char *prompt = NULL;
761
762 /*@ newt ************************************************************** */
763 newtComponent myForm;
764 newtComponent b_1;
765 newtComponent b_2;
766 newtComponent b_res;
767 newtComponent text;
768
769 assert_string_is_neither_NULL_nor_zerolength(p);
770 assert(button1 != NULL);
771 assert(button2 != NULL);
772 if (g_text_mode) {
773 if (strlen(button2) == 0) {
774 printf("%s (%s) --> ", p, button1);
775 } else {
776 printf("%s (%s or %s) --> ", p, button1, button2);
777 }
778 mr_getline(prompt, stdin);
779 while (strcmp(prompt, button1) && (strlen(button2) == 0 || strcmp(prompt, button2))) {
780 printf("--> ");
781 mr_free(prompt);
782 mr_getline(prompt, stdin);
783 }
784 if (!strcmp(prompt, button1)) {
785 mr_free(prompt);
786 return (TRUE);
787 } else {
788 mr_free(prompt);
789 return (FALSE);
790 }
791 }
792
793 prompt = malloc(MAX_NEWT_COMMENT_LEN);
794 strncpy(prompt, p, MAX_NEWT_COMMENT_LEN - 1);
795 prompt[MAX_NEWT_COMMENT_LEN - 1] = '\0';
796 text = newtTextboxReflowed(1, 1, prompt, 40, 5, 5, 0);
797 b_1 = newtButton(20 - ((button2[0] != '\0') ? strlen(button1) + 2 : strlen(button1) / 2), newtTextboxGetNumLines(text) + 3, button1);
798 if (button2[0] != '\0') {
799 b_2 = newtButton(24, newtTextboxGetNumLines(text) + 3, button2);
800 } else {
801 b_2 = NULL;
802 }
803 newtCenteredWindow(46, newtTextboxGetNumLines(text) + 7, "Alert");
804 myForm = newtForm(NULL, NULL, 0);
805 newtFormAddComponents(myForm, text, b_1, b_2, NULL);
806 center_string(prompt, 80);
807 newtPushHelpLine(prompt);
808 b_res = newtRunForm(myForm);
809 newtPopHelpLine();
810 newtFormDestroy(myForm);
811 newtPopWindow();
812 if (b_res == b_1) {
813 paranoid_free(prompt);
814 return (TRUE);
815 } else {
816 paranoid_free(prompt);
817 return (FALSE);
818 }
819 }
820
821
822
823
824/**
825 * Synchronize the log messages stored in @p err_log_lines with those shown
826 * on the screen.
827 */
828void refresh_log_screen() {
829
830 /*@ int *********************************************************** */
831 int i = 0;
832
833
834 if (g_text_mode || !err_log_lines) {
835 return;
836 }
837 for (i = g_noof_log_lines - 1; i >= 0; i--) {
838 newtDrawRootText(0, i + g_noof_rows - 1 - g_noof_log_lines,
839 " ");
840 }
841 newtRefresh();
842 for (i = g_noof_log_lines - 1; i >= 0; i--) {
843 err_log_lines[i][79] = '\0';
844 newtDrawRootText(0, i + g_noof_rows - 1 - g_noof_log_lines,
845 err_log_lines[i]);
846 }
847 newtRefresh();
848 }
849
850
851/**
852 * Set up the Newt graphical environment. If @p g_text_mode is TRUE, then
853 * only allocate some memory.
854 */
855void setup_newt_stuff() {
856
857 /*@ int *********************************************************** */
858 int i = 0;
859 int cols;
860
861 if (!g_text_mode) {
862 newtInit();
863 newtCls();
864 newtPushHelpLine("Welcome to Mondo Rescue, by Dev Team and the Internet. All rights reversed.");
865 newtDrawRootText(18, 0, WELCOME_STRING);
866 newtRefresh();
867 newtGetScreenSize(&cols, &g_noof_rows);
868 g_noof_log_lines = (g_noof_rows / 5) + 1;
869 }
870
871 err_log_lines = (char **) mr_malloc(sizeof(char *) * g_noof_log_lines);
872
873 for (i = 0; i < g_noof_log_lines; i++) {
874 err_log_lines[i] = (char *) mr_malloc(MAX_NEWT_COMMENT_LEN);
875 }
876
877 for (i = 0; i < g_noof_log_lines; i++) {
878 err_log_lines[i][0] = '\0';
879 }
880 }
881
882
883/**
884 * Update the evalcall form to show (<tt>num</tt>/<tt>denom</tt>)*100 %.
885 * @param num The numerator of the ratio.
886 * @param denom The denomenator of the ratio.
887 */
888void update_evalcall_form_ratio(int num, int denom) {
889
890 /*@ long ************************************************************ */
891 long current_time = 0L;
892 long time_taken = 0L;
893 long time_total_est = 0L;
894 long time_remaining = 0L;
895
896 /*@ buffers ********************************************************** */
897 char *timeline_str = NULL;
898 char *pcline_str = NULL;
899 char *taskprogress = NULL;
900
901 /*@ int ************************************************************** */
902 int percentage = 0;
903 int i = 0;
904 int j = 0;
905
906 if (num * 100 < denom) {
907 percentage = 1;
908 } else {
909 percentage = (num * 100 + denom / 2) / denom;
910 }
911
912 current_time = get_time();
913 time_taken = current_time - g_isoform_starttime;
914 if (num) {
915 time_total_est = time_taken * denom / num;
916 time_remaining = time_total_est - time_taken;
917 } else {
918 time_remaining = 0L;
919 }
920 if (!g_text_mode) {
921 if (g_isoform_header) {
922 newtLabelSetText(g_isoform_header, g_isoform_header_str);
923 }
924 }
925 g_mysterious_dot_counter = (g_mysterious_dot_counter + 1) % 27;
926 if ((percentage < 3 && g_isoform_old_progress < 3)
927 || percentage > g_isoform_old_progress) {
928 g_isoform_old_progress = percentage;
929 mr_asprintf(timeline_str, "%2ld:%02ld taken %2ld:%02ld remaining", (long) time_taken / 60, (long) time_taken % 60, (long) time_remaining / 60, (long) time_remaining % 60);
930 if (percentage < 3) {
931 mr_asprintf(pcline_str, " Working");
932 for (j = 0; j < g_mysterious_dot_counter; j++) {
933 mr_strcat(pcline_str, ".");
934 }
935 for (; j < 27; j++) {
936 mr_strcat(pcline_str, " ");
937 }
938 mr_strcat(pcline_str, " %c", special_dot_char(g_mysterious_dot_counter));
939 } else {
940 mr_asprintf(pcline_str, " %3d%% done %3d%% to go", percentage, 100 - percentage);
941 }
942 if (g_text_mode) {
943 mr_asprintf(taskprogress, "TASK: [");
944 for (i = 0; i < percentage; i += 5) {
945 mr_strcat(taskprogress, "*");
946 }
947 for (; i < 100; i += 5) {
948 mr_strcat(taskprogress, ".");
949 }
950 if (percentage >= 3) {
951 mr_strcat(taskprogress, "] %3d%% done; %2ld:%02ld to go", percentage, time_remaining / 60, time_remaining % 60);
952 printf("---evalcall---1--- %s\n", g_isoform_header_str);
953 printf("---evalcall---2--- %s\n", taskprogress);
954 printf("---evalcall---E---\n");
955 }
956 mr_free(taskprogress);
957 } else {
958 newtScaleSet(g_isoform_scale, (unsigned long long) percentage);
959 if (g_isoform_pcline) {
960 newtLabelSetText(g_isoform_pcline, pcline_str);
961 }
962 if ((percentage >= 3) && (g_isoform_timeline)) {
963 newtLabelSetText(g_isoform_timeline, timeline_str);
964 }
965 }
966 mr_free(pcline_str);
967 mr_free(timeline_str);
968 }
969 if (!g_text_mode) {
970 newtRefresh();
971 }
972 }
973
974
975
976/**
977 * Update the evalcall form to show @p curr %.
978 * @param curr The current amount of progress (percentage) in the evalcall form.
979 */
980void update_evalcall_form(int curr) {
981
982 update_evalcall_form_ratio(curr, 100);
983}
984
985
986
987/**
988 * Update the progress form to show @p blurb3 and the current value of
989 * @p g_maximum_progress.
990 * @param blurb3 The new third line of the blurb; use @p g_blurb_str_2 (no, that's not a typo) to keep it the same.
991 */
992void update_progress_form(char *blurb3) {
993
994 if (g_current_progress == -999) {
995 return;
996 }
997 strcpy(g_blurb_str_2, blurb3);
998 update_progress_form_full(g_blurb_str_1, g_blurb_str_2, g_blurb_str_3);
999}
1000
1001
1002/**
1003 * Update the progress form's complete blurb and show @p g_current_progress.
1004 * @param blurb1 The first line of the blurb. Use @p g_blurb_str_1 to keep it unchanged.
1005 * @param blurb2 The second line of the blurb. Use @p g_blurb_str_3 (no, that's not a typo) to keep it the same.
1006 * @param blurb3 The third line of the blurb. Use @p g_blurb_str_2 (no, that's not a typo either) to keep it the same.
1007 */
1008void update_progress_form_full(char *blurb1, char *blurb2, char *blurb3) {
1009
1010 /*@ long ***************************************************** */
1011 long current_time = 0L;
1012 long time_taken = 0L;
1013 long time_remaining = 0L;
1014 long time_total_est = 0L;
1015
1016 /*@ int ******************************************************* */
1017 int percentage = 0;
1018 int i = 0;
1019
1020 /*@ buffers *************************************************** */
1021 char *percentline_str = NULL;
1022 char *timeline_str = NULL;
1023 char *taskprogress = NULL;
1024
1025 if (!g_text_mode) {
1026 assert(blurb1 != NULL);
1027 assert(blurb2 != NULL);
1028 assert(blurb3 != NULL);
1029 assert(g_timeline != NULL);
1030 }
1031
1032 current_time = get_time();
1033 time_taken = current_time - g_start_time;
1034 if (g_maximum_progress == 0) {
1035 percentage = 0;
1036 } else {
1037 if (g_current_progress > g_maximum_progress) {
1038 log_msg(0, "update_progress_form_full(%s,%s,%s) --- g_current_progress=%ld; g_maximum_progress=%ld", blurb1, blurb2, blurb3, g_current_progress, g_maximum_progress);
1039 g_current_progress = g_maximum_progress;
1040 }
1041 percentage = (int) ((g_current_progress * 100L) / g_maximum_progress);
1042 }
1043 if (percentage < 1) {
1044 percentage = 1;
1045 }
1046 if (percentage > 100) {
1047 percentage = 100;
1048 }
1049 if (g_current_progress) {
1050 time_total_est = time_taken * (long) g_maximum_progress / (long) g_current_progress;
1051 time_remaining = time_total_est - time_taken;
1052 } else {
1053 time_remaining = 0L;
1054 }
1055 g_mysterious_dot_counter = (g_mysterious_dot_counter + 1) % 27;
1056 if (g_text_mode) {
1057 printf("---progress-form---1--- %s\n", blurb1);
1058 printf("---progress-form---2--- %s\n", blurb2);
1059 printf("---progress-form---3--- %s\n", blurb3);
1060 printf("---progress-form---E---\n");
1061 mr_asprintf(taskprogress, "TASK: [");
1062 for (i = 0; i < percentage; i += 5) {
1063 mr_strcat(taskprogress, "*");
1064 }
1065 for (; i < 100; i += 5) {
1066 mr_strcat(taskprogress, ".");
1067 }
1068 if (percentage > 100) {
1069 log_msg(2, "percentage = %d", percentage);
1070 }
1071 mr_strcat(taskprogress, "] %3d%% done; %2ld:%02ld to go", percentage, (long) time_remaining / 60, (long) time_remaining % 60);
1072 printf("---progress-form---4--- %s\n", taskprogress);
1073 paranoid_free(taskprogress);
1074 } else {
1075 mr_asprintf(timeline_str, "%2ld:%02ld taken %2ld:%02ld remaining ", (long) time_taken / 60, (long) time_taken % 60, (long) time_remaining / 60, (long) time_remaining % 60);
1076 mr_asprintf(percentline_str, " %3d%% done %3d%% to go", percentage, 100 - percentage);
1077
1078 center_string(blurb1, 54);
1079 center_string(blurb2, 54);
1080 center_string(blurb3, 54);
1081 if (g_blurb1) {
1082 newtLabelSetText(g_blurb1, blurb1);
1083 }
1084 if (g_blurb2) {
1085 newtLabelSetText(g_blurb2, blurb3);
1086 }
1087 if (g_blurb3) {
1088 newtLabelSetText(g_blurb3, blurb2);
1089 }
1090 newtScaleSet(g_scale, (unsigned long long) g_current_progress);
1091 if ((percentage >= 2) && (g_timeline)) {
1092 newtLabelSetText(g_timeline, timeline_str);
1093 }
1094 mr_free(timeline_str);
1095
1096 if (g_percentline) {
1097 newtLabelSetText(g_percentline, percentline_str);
1098 }
1099 mr_free(percentline_str);
1100
1101 newtRefresh();
1102 }
1103 }
1104
1105
1106/**
1107 * Ask the user which backup media type they would like to use.
1108 * The choices are @p none (exit to shell), @c cdr, @c cdrw, @c dvd,
1109 * @c tape, @c cdstream, @c udev (only when @p g_text_mode is TRUE), @c netfs,
1110 * and @c iso.
1111 * @param restoring TRUE if we're restoring, FALSE if we're backing up.
1112 * @return The backup type chosen, or @c none if the user chose "Exit to shell".
1113 */
1114t_bkptype which_backup_media_type(bool restoring) {
1115
1116 /*@ char ************************************************************ */
1117 t_bkptype output;
1118
1119
1120 /*@ newt ************************************************************ */
1121 char *title_sz = NULL;
1122 char *minimsg_sz = NULL;
1123 static t_bkptype possible_bkptypes[] = { none, cdr, cdrw, dvd, tape, cdstream, udev, netfs, iso };
1124 static char *possible_responses[] = { "none", "cdr", "cdrw", "dvd", "tape", "cdstream", "udev", "netfs", "iso", NULL };
1125 char *outstr = NULL;
1126 t_bkptype backup_type;
1127 int i;
1128
1129 newtComponent b1;
1130 newtComponent b2;
1131 newtComponent b3;
1132 newtComponent b4;
1133 newtComponent b5;
1134 newtComponent b6;
1135 newtComponent b7;
1136 newtComponent b8;
1137 newtComponent b_res;
1138 newtComponent myForm;
1139
1140 if (g_text_mode) {
1141 for (backup_type = none; backup_type == none;) {
1142 printf("Backup type (");
1143 for (i = 0; possible_responses[i]; i++) {
1144 printf("%c%s", (i == 0) ? '\0' : ' ',
1145 possible_responses[i]);
1146 }
1147 printf(")\n--> ");
1148 mr_getline(outstr, stdin);
1149 mr_strip_spaces(outstr);
1150 for (i = 0; possible_responses[i]; i++) {
1151 if (!strcmp(possible_responses[i], outstr)) {
1152 backup_type = possible_bkptypes[i];
1153 }
1154 }
1155 mr_free(outstr);
1156 }
1157 return (backup_type);
1158 }
1159 newtDrawRootText(18, 0, WELCOME_STRING);
1160 if (restoring) {
1161 mr_asprintf(title_sz, "Please choose the backup media from which you want to read data.");
1162 mr_asprintf(minimsg_sz, "Read from:");
1163 } else {
1164 mr_asprintf(title_sz, "Please choose the backup media to which you want to archive data.");
1165 mr_asprintf(minimsg_sz, "Backup to:");
1166 }
1167 newtPushHelpLine(title_sz);
1168 newtCenteredWindow(34, 17, minimsg_sz);
1169 b1 = newtButton(1, 1, "CD-R disks ");
1170 b2 = newtButton(17, 1, "CD-RW disks");
1171 b3 = newtButton(1, 9, "Tape drive ");
1172 b4 = newtButton(17, 5, "USB Key/Disk");
1173 b5 = newtButton(1, 5, " DVD disks ");
1174 b6 = newtButton(17, 9, " Net mount ");
1175 b7 = newtButton(1, 13, " Hard disk ");
1176 b8 = newtButton(17, 13, " Exit ");
1177 myForm = newtForm(NULL, NULL, 0);
1178 newtFormAddComponents(myForm, b1, b5, b3, b7, b2, b4, b6, b8,
1179 NULL);
1180 b_res = newtRunForm(myForm);
1181 newtFormDestroy(myForm);
1182 newtPopWindow();
1183 if (b_res == b1) {
1184 output = cdr;
1185 } else if (b_res == b2) {
1186 output = cdrw;
1187 } else if (b_res == b3) {
1188 output = tape;
1189 } else if (b_res == b4) {
1190 output = usb;
1191 } else if (b_res == b5) {
1192 output = dvd;
1193 } else if (b_res == b6) {
1194 output = netfs;
1195 } else if (b_res == b7) {
1196 output = iso;
1197 } else {
1198 output = none;
1199 }
1200 newtPopHelpLine();
1201 mr_free(title_sz);
1202 mr_free(minimsg_sz);
1203 paranoid_free(outstr);
1204 return (output);
1205 }
1206
1207
1208
1209
1210/**
1211 * Ask the user how much compression they would like to use.
1212 * The choices are "None" (0), "Minimum" (1), "Average" (4), and "Maximum" (9).
1213 * @return The compression level (0-9) chosen, or -1 for "Exit".
1214 */
1215int which_compression_level() {
1216
1217 /*@ char ************************************************************ */
1218 int output = none;
1219
1220
1221 /*@ newt ************************************************************ */
1222
1223 newtComponent b1;
1224 newtComponent b2;
1225 newtComponent b3;
1226 newtComponent b4;
1227 newtComponent b5;
1228 newtComponent b_res;
1229 newtComponent myForm;
1230
1231 newtDrawRootText(18, 0, WELCOME_STRING);
1232 newtPushHelpLine(" Please specify the level of compression that you want.");
1233 newtCenteredWindow(34, 13, "How much compression?");
1234 b1 = newtButton(4, 1, "Maximum");
1235 b2 = newtButton(18, 1, "Average");
1236 b3 = newtButton(4, 5, "Minimum");
1237 b4 = newtButton(18, 5, " None ");
1238 b5 = newtButton(4, 9, " Exit ");
1239 myForm = newtForm(NULL, NULL, 0);
1240 newtFormAddComponents(myForm, b1, b3, b2, b4, b5, NULL);
1241 b_res = newtRunForm(myForm);
1242 newtFormDestroy(myForm);
1243 newtPopWindow();
1244 if (b_res == b1) {
1245 output = 9;
1246 } else if (b_res == b2) {
1247 output = 4;
1248 } else if (b_res == b3) {
1249 output = 1;
1250 } else if (b_res == b4) {
1251 output = 0;
1252 } else if (b_res == b5) {
1253 output = -1;
1254 }
1255 newtPopHelpLine();
1256 return (output);
1257 }
1258
1259
1260
1261
1262
1263/**
1264 * Load @p source_file (a list of files) into @p filelist. There can be no more than
1265 * @p ARBITRARY_MAXIMUM entries.
1266 * @param filelist The filelist structure to load @p source_file into.
1267 * @param source_file The file containing a list of filenames to load into @p filelist.
1268 */
1269int load_filelist_into_array(struct s_filelist *filelist, char *source_file) {
1270
1271 int i;
1272 int j = 0;
1273 bool done;
1274 char *tmp = NULL;
1275 char *tmp1 = NULL;
1276 FILE *fin, *fout;
1277 struct s_filelist_entry dummy_fle;
1278
1279 assert(filelist != NULL);
1280 assert_string_is_neither_NULL_nor_zerolength(source_file);
1281
1282 log_it("entering");
1283 if (!(fin = fopen(source_file, "r"))) {
1284 log_OS_error(source_file);
1285 log_msg(2, "Can't open %s; therefore, cannot popup list",
1286 source_file);
1287 return (1);
1288 }
1289
1290 mr_asprintf(tmp1,"%s/icantfindthesefiles.txt",bkpinfo->tmpdir);
1291 if (!(fout = fopen(tmp1, "a"))) {
1292 log_msg(2, "Can't write to %s", tmp1);
1293 mr_free(tmp1);
1294 return(1);
1295 }
1296
1297 log_msg(2, "Loading %s", source_file);
1298 for (filelist->entries = 0; filelist->entries <= ARBITRARY_MAXIMUM; ) {
1299 if (tmp != NULL) {
1300 mr_free(tmp);
1301 }
1302 if (feof(fin)) {
1303 break;
1304 }
1305 mr_getline(tmp, fin);
1306 i = (int) strlen(tmp);
1307 if (i < 2) {
1308 continue;
1309 }
1310 if (tmp[i - 1] < 32) {
1311 tmp[--i] = '\0';
1312 }
1313 if (i < 2) {
1314 continue;
1315 }
1316 if (!does_file_exist(tmp) && !feof(fin)) {
1317 j++;
1318 fprintf(fout, "%s\n", tmp);
1319 continue;
1320 }
1321 filelist->el[filelist->entries].severity = severity_of_difference(tmp, NULL);
1322 strcpy(filelist->el[filelist->entries].filename, tmp);
1323 if (feof(fin)) {
1324 break;
1325 }
1326 filelist->entries++;
1327 }
1328 mr_free(tmp);
1329 paranoid_fclose(fin);
1330 paranoid_fclose(fout);
1331 if (j > 0) {
1332 log_to_screen("%d files listed in %s/changed.files have been deleted since backup was made\nand are referenced in %s", j, bkpinfo->tmpdir,tmp1);
1333 }
1334 mr_free(tmp1);
1335 if (filelist->entries >= ARBITRARY_MAXIMUM) {
1336 log_to_screen("Arbitrary limits suck, man!");
1337 return (1);
1338 }
1339 for (done = FALSE; !done;) {
1340 done = TRUE;
1341 for (i = 0; i < filelist->entries - 1; i++) {
1342// if (strcmp(filelist->el[i].filename, filelist->el[i+1].filename) > 0)
1343 if (filelist->el[i].severity < filelist->el[i + 1].severity
1344 || (filelist->el[i].severity ==
1345 filelist->el[i + 1].severity
1346 && strcmp(filelist->el[i].filename,
1347 filelist->el[i + 1].filename) > 0)) {
1348 memcpy((void *) &dummy_fle,
1349 (void *) &(filelist->el[i]),
1350 sizeof(struct s_filelist_entry));
1351 memcpy((void *) &(filelist->el[i]),
1352 (void *) &(filelist->el[i + 1]),
1353 sizeof(struct s_filelist_entry));
1354 memcpy((void *) &(filelist->el[i + 1]),
1355 (void *) &dummy_fle,
1356 sizeof(struct s_filelist_entry));
1357 log_msg(2, "Swapping %s and %s",
1358 filelist->el[i].filename,
1359 filelist->el[i + 1].filename);
1360 done = FALSE;
1361 }
1362 }
1363 }
1364 log_it("leaving");
1365 return (0);
1366 }
1367
1368
1369/**
1370 * Generate a pretty string based on @p flentry.
1371 * @param flentry The filelist entry to stringify.
1372 * @return The string form of @p flentry.
1373 * @note The returned value points to static storage that will be overwritten with each call.
1374 */
1375char *filelist_entry_to_string(struct s_filelist_entry *flentry) {
1376 char *tmp = NULL;
1377
1378 log_msg(8, "entering");
1379 assert(flentry != NULL);
1380 if (flentry->severity == 0) {
1381 mr_asprintf(tmp, "0 ");
1382 } else if (flentry->severity == 1) {
1383 mr_asprintf(tmp, "low ");
1384 } else if (flentry->severity == 2) {
1385 mr_asprintf(tmp, "med ");
1386 } else {
1387 mr_asprintf(tmp, "high");
1388 }
1389 mr_strcat(tmp, " %s", flentry->filename);
1390
1391 log_msg(8, "leaving");
1392 return (tmp);
1393 }
1394
1395
1396/**
1397 * Pop up a list containing the filenames in @p source_file and the severity if they have changed since the
1398 * last backup. There can be no more than @p ARBITRARY_MAXIMUM files in @p source_file.
1399 * @param source_file The file containing a list of changed files.
1400 */
1401void popup_changelist_from_file(char *source_file) {
1402
1403 char *reason = NULL;
1404 newtComponent myForm;
1405 newtComponent bClose;
1406 newtComponent bSelect;
1407 newtComponent b_res;
1408 newtComponent fileListbox;
1409 newtComponent headerMsg;
1410
1411 /*@ ???? ************************************************************ */
1412 void *curr_choice;
1413 void *keylist[ARBITRARY_MAXIMUM];
1414
1415 /*@ int ************************************************************* */
1416 int currline = 0;
1417 int finished = FALSE;
1418
1419 /*@ long ************************************************************ */
1420 long i = 0;
1421 long lng = 0;
1422
1423 /*@ buffers ********************************************************* */
1424 char *tmp = NULL;
1425 char *differ_sz = NULL;
1426
1427 struct s_filelist *filelist;
1428 assert_string_is_neither_NULL_nor_zerolength(source_file);
1429 if (g_text_mode) {
1430 log_msg(2, "Text mode. Therefore, no popup list.");
1431 return;
1432 }
1433 log_msg(2, "Examining file %s", source_file);
1434
1435 lng = count_lines_in_file(source_file);
1436 if (lng < 1) {
1437 log_msg(2, "No lines in file. Therefore, no popup list.");
1438 return;
1439 } else if (lng >= ARBITRARY_MAXIMUM) {
1440 log_msg(2, "Too many files differ for me to list.");
1441 return;
1442 }
1443
1444 filelist = (struct s_filelist *) malloc(sizeof(struct s_filelist));
1445 fileListbox =
1446 newtListbox(2, 2, 12, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1447 newtListboxClear(fileListbox);
1448
1449 if (load_filelist_into_array(filelist, source_file)) {
1450 log_msg(2, "Can't open %s; therefore, cannot popup list", source_file);
1451 return;
1452 }
1453 log_msg(2, "%d files loaded into filelist array", filelist->entries);
1454 for (i = 0; i < filelist->entries; i++) {
1455 keylist[i] = (void *) i;
1456 tmp = filelist_entry_to_string(&(filelist->el[i]));
1457 newtListboxAppendEntry(fileListbox, tmp, keylist[i]);
1458 mr_free(tmp);
1459 }
1460 mr_asprintf(differ_sz, " %ld files differ. Hit 'Select' to pick a file. Hit 'Close' to quit the list.", i);
1461 newtPushHelpLine(differ_sz);
1462 mr_free(differ_sz);
1463
1464 bClose = newtCompactButton(10, 15, " Close ");
1465 bSelect = newtCompactButton(30, 15, " Select ");
1466 mr_asprintf(tmp, "%-10s %-20s", "Priority", "Filename");
1467 headerMsg = newtLabel(2, 1, tmp);
1468 mr_free(tmp);
1469
1470 newtOpenWindow(5, 4, 70, 16, "Non-matching files");
1471 myForm = newtForm(NULL, NULL, 0);
1472 newtFormAddComponents(myForm, headerMsg, fileListbox, bClose, bSelect, NULL);
1473
1474 while (!finished) {
1475 b_res = newtRunForm(myForm);
1476 if (b_res == bClose) {
1477 finished = TRUE;
1478 } else {
1479 curr_choice = newtListboxGetCurrent(fileListbox);
1480 for (i = 0;
1481 i < filelist->entries && keylist[i] != curr_choice;
1482 i++);
1483 if (i == filelist->entries && filelist->entries > 0) {
1484 log_to_screen("I don't know what that button does!");
1485 } else {
1486 currline = i;
1487 if (filelist->entries > 0) {
1488 severity_of_difference(filelist->el[currline]. filename, &reason);
1489 mr_asprintf(tmp, "%s --- %s", filelist->el[currline].filename, reason);
1490
1491 popup_and_OK(tmp);
1492 mr_free(tmp);
1493 mr_free(reason);
1494 }
1495 }
1496 }
1497 }
1498
1499 newtFormDestroy(myForm);
1500 newtPopWindow();
1501 newtPopHelpLine();
1502 return;
1503 }
1504
1505/* @} - end of guiGroup */
1506
1507
1508#if __cplusplus
1509} /* extern "C" */
1510#endif
1511
1512
1513void wait_until_software_raids_are_prepped(char *mdstat_file, int wait_for_percentage);
Note: See TracBrowser for help on using the repository browser.