source: MondoRescue/branches/3.1/mondo/src/common/newt-specific.c@ 3190

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