source: MondoRescue/branches/stable/mondo/src/common/newt-specific.c@ 1770

Last change on this file since 1770 was 1770, checked in by Bruno Cornec, 16 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

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