source: MondoRescue/branches/3.0/mondo/src/common/newt-specific.c@ 3192

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