source: MondoRescue/branches/2.06/mondo/mondo/common/newt-specific.c

Last change on this file was 296, checked in by andree, 18 years ago

Replaced partimagehack with ntfsclone from ntfsprogs package. Replaced
all occurrences of strings 'partimagehack' and 'partimage' with 'ntfsprog'.

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