source: MondoRescue/branches/2.2.2/mondo/src/common/newt-specific.c@ 1315

Last change on this file since 1315 was 1315, checked in by Bruno Cornec, 17 years ago

Log files are now consistent: mondoarchive.log for mondoarchive (containing also mindi.log) and mondorestore.log for mondorestore (copied from /tmp (ram) to /var/log (disk) at the end of the restore)
One include has been created for each bianry containing only that declaration ofr the moment, but which will be extended to include all local definitions (ps_* e.g.)
Doc updated accordingly
LOGFILE in restore process is now passed in the environment and not duplicated anymore
LogIt is not redifined either
LOGFILE should be put in environment by mondoarchive for mindi's usage but that's a step left for later.

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