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

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

ps (busybox) and ps (system) do not give PID in the same column. Adapted with a global variable.

  • Property svn:keywords set to Id
File size: 47.7 KB
Line 
1/* newt-specific.c
2 $Id: newt-specific.c 928 2006-11-13 09:17:07Z 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 928 2006-11-13 09:17:07Z 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
351asprintf(&tmp,"kill `ps %s | grep \" %s \" | awk '{print %s;}' | grep -vx \"\\?\"`", ps_options, str , ps_proc_id);
352run_program_and_log_output(tmp, TRUE);
353paranoid_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 system
438 ("gzip -9c /var/log/mondo-archive.log > /tmp/MA.log.gz 2> /dev/null");
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 strip_spaces(err_log_lines[i]);
560 if (!strncmp(err_log_lines[i], "root:", 5)) {
561 strcpy(tmp, err_log_lines[i] + 6);
562 strcpy(err_log_lines[i], tmp);
563 }
564 if (feof(fin)) {
565 break;
566 }
567 }
568 }
569 paranoid_pclose(fin);
570 }
571 refresh_log_screen();
572 paranoid_free(command);
573 paranoid_free(tmp);
574 }
575
576
577/**
578 * Log a message to the screen.
579 * @param fmt A printf-style format string to write. The following parameters are its arguments.
580 * @note The message is also written to the logfile.
581 */
582 void
583 log_to_screen(const char *fmt, ...) {
584
585 /*@ int ************************************************************** */
586 int i = 0;
587 int j = 0;
588 va_list args;
589
590 /*@ buffers ********************************************************** */
591 char *output;
592
593 malloc_string(output);
594
595 va_start(args, fmt);
596 vsprintf(output, fmt, args);
597 log_msg(0, output);
598 output[80] = '\0';
599 va_end(args);
600 i = (int) strlen(output);
601 if (i > 0 && output[i - 1] < 32) {
602 output[i - 1] = '\0';
603 }
604
605 if (err_log_lines) {
606 for (i = 1; i < g_noof_log_lines; i++) {
607 strcpy(err_log_lines[i - 1],
608 " ");
609 strcpy(err_log_lines[i - 1], err_log_lines[i]);
610 }
611 }
612 while (strlen(output) > 0 && output[strlen(output) - 1] < 32) {
613 output[strlen(output) - 1] = '\0';
614 }
615 for (j = 0; j < (int) strlen(output); j++) {
616 if (output[j] < 32) {
617 output[j] = ' ';
618 }
619 }
620 if (err_log_lines)
621 strcpy(err_log_lines[g_noof_log_lines - 1], output);
622 if (g_text_mode) {
623 printf("%s\n", output);
624 } else {
625 refresh_log_screen();
626 }
627 paranoid_free(output);
628 }
629
630
631
632
633/**
634 * Write a string to the root window at (@p x, @p y) and also to the logfile.
635 * @param y The row to write the string to.
636 * @param x The column to write the string to.
637 * @param output The string to write.
638 */
639 void
640 mvaddstr_and_log_it(int y, int x, char *output) {
641 assert_string_is_neither_NULL_nor_zerolength(output);
642 log_msg(0, output);
643 if (g_text_mode) {
644 printf("%s\n", output);
645 } else {
646 newtDrawRootText(x, y, output);
647 newtRefresh();
648 }
649 }
650
651
652
653
654/**
655 * Open an evalcall form with title @p ttl.
656 * @param ttl The title to use for the evalcall form.
657 */
658 void
659 open_evalcall_form(char *ttl) {
660
661 /*@ buffers ********************************************************* */
662 char *title;
663 char *tmp;
664
665 /*@ initialize ****************************************************** */
666 g_isoform_old_progress = -1;
667 g_mysterious_dot_counter = 0;
668 malloc_string(title);
669 malloc_string(tmp);
670
671 assert(ttl != NULL);
672 strcpy(title, ttl);
673 strcpy(g_isoform_header_str, title);
674// center_string (title, 80);
675 if (g_text_mode) {
676 log_msg(0, title);
677 } else {
678 strcpy(tmp, title);
679 center_string(tmp, 80);
680 newtPushHelpLine(tmp);
681 }
682 center_string(g_isoform_header_str, 36);
683 g_isoform_starttime = get_time();
684 if (g_text_mode) {
685 log_msg(0, g_isoform_header_str);
686 } else {
687 g_isoform_header = newtLabel(1, 1, g_isoform_header_str);
688 g_isoform_scale = newtScale(3, 3, 34, 100);
689 // newtOpenWindow (20, 6, 40, 7, title); // "Please Wait");
690 newtCenteredWindow(40, 7, title);
691 g_isoform_main = newtForm(NULL, NULL, 0);
692 g_isoform_timeline = newtLabel(1, 5, "This is the timeline");
693 g_isoform_pcline = newtLabel(1, 6, "This is the pcline");
694 newtFormAddComponents(g_isoform_main, g_isoform_timeline,
695 g_isoform_pcline, g_isoform_header,
696 g_isoform_scale, NULL);
697 newtRefresh();
698 }
699 update_evalcall_form(0);
700 paranoid_free(tmp);
701 paranoid_free(title);
702 }
703
704
705
706/**
707 * Open a progress form with title @p title.
708 * @param title The title to use for the progress form (will be put in the title bar on Newt).
709 * @param b1 The first line of the blurb; generally static.
710 * @param b2 The second line of the blurb; generally static.
711 * @param b3 The third line of the blurb; generally dynamic (it is passed
712 * to update_evalcall_form() every time).
713 * @param max_val The maximum amount of progress (number of filesets, etc.)
714 */
715 void
716 open_progress_form(char *title, char *b1, char *b2, char *b3,
717 long max_val) {
718
719 /*@ buffers ********************************************************* */
720 char *b1c;
721 char *blurb1;
722 char *blurb2;
723 char *blurb3;
724
725 /*@ initialize ****************************************************** */
726 g_mysterious_dot_counter = 0;
727
728 malloc_string(b1c);
729 malloc_string(blurb1);
730 malloc_string(blurb2);
731 malloc_string(blurb3);
732
733 assert(title != NULL);
734 assert(b1 != NULL);
735 assert(b2 != NULL);
736 assert(b3 != NULL);
737
738 strcpy(blurb1, b1);
739 strcpy(blurb2, b2);
740 strcpy(blurb3, b3);
741 strcpy(b1c, b1);
742 center_string(b1c, 80);
743 if (max_val <= 0) {
744 max_val = 1;
745 }
746
747 g_start_time = get_time();
748 g_maximum_progress = max_val;
749 g_current_progress = 0;
750 strcpy(g_blurb_str_1, blurb1);
751 strcpy(g_blurb_str_2, blurb3);
752 strcpy(g_blurb_str_3, blurb2);
753 if (g_text_mode) {
754 log_msg(0, blurb1);
755 log_msg(0, blurb2);
756 log_msg(0, blurb3);
757 } else {
758 g_blurb1 = newtLabel(2, 1, blurb1);
759 g_blurb2 = newtLabel(2, 2, blurb3);
760 g_blurb3 = newtLabel(2, 4, blurb2);
761 // newtOpenWindow (10, 4, 60, 11, title);
762 newtCenteredWindow(60, 11, title);
763 g_scale = newtScale(3, 6, 54, g_maximum_progress);
764 g_progressForm = newtForm(NULL, NULL, 0);
765 g_percentline = newtLabel(10, 9, "This is the percentline");
766 g_timeline = newtLabel(10, 8, "This is the timeline");
767 newtFormAddComponents(g_progressForm, g_percentline,
768 g_timeline, g_scale, g_blurb1, g_blurb3,
769 g_blurb2, NULL);
770 newtPushHelpLine(b1c);
771 newtRefresh();
772 }
773 update_progress_form_full(blurb1, blurb2, blurb3);
774 paranoid_free(b1c);
775 paranoid_free(blurb1);
776 paranoid_free(blurb2);
777 paranoid_free(blurb3);
778 }
779
780/**
781 * Give a message to the user in the form of a dialog box (under Newt).
782 * @param prompt The message.
783 */
784 void
785 popup_and_OK(char *prompt) {
786 char ch;
787
788 assert_string_is_neither_NULL_nor_zerolength(prompt);
789
790 log_msg(0, prompt);
791 if (g_text_mode) {
792 printf
793 ("---promptpopup---1--- %s\r\n---promptpopup---Q--- [OK] ---\r\n--> ",
794 prompt);
795 while (((ch = getchar()) != '\n') && (ch != EOF));
796 } else {
797 (void) popup_with_buttons(prompt, " OK ", "");
798 }
799 }
800
801/**
802 * Ask the user to enter a value.
803 * @param title The title of the dialog box.
804 * @param b The blurb (e.g. what you want the user to enter).
805 * @param output The string to put the user's answer in.
806 * @param maxsize The size in bytes allocated to @p output.
807 * @return TRUE if the user pressed OK, FALSE if they pressed Cancel.
808 */
809 bool popup_and_get_string(char *title, char *b, char *output,
810 int maxsize) {
811
812 /*@ newt ************************************************************ */
813 newtComponent myForm;
814 newtComponent b_1;
815 newtComponent b_2;
816 newtComponent b_res;
817 newtComponent text;
818 newtComponent type_here;
819
820 /*@ pointers ********************************************************* */
821 char *entry_value;
822
823 /*@ buffers ********************************************************** */
824 char *blurb;
825 char *original_contents;
826
827 blurb = malloc(MAX_NEWT_COMMENT_LEN);
828 original_contents = malloc(MAX_NEWT_COMMENT_LEN);
829 assert_string_is_neither_NULL_nor_zerolength(title);
830 assert(b != NULL);
831 assert(output != NULL);
832
833 if (g_text_mode) {
834 printf
835 ("---promptstring---1--- %s\r\n---promptstring---2--- %s\r\n---promptstring---Q---\r\n--> ",
836 title, b);
837 (void) fgets(output, maxsize, stdin);
838 if (output[strlen(output) - 1] == '\n')
839 output[strlen(output) - 1] = '\0';
840 paranoid_free(blurb);
841 paranoid_free(original_contents);
842 return (TRUE);
843 }
844 strcpy(blurb, b);
845 text = newtTextboxReflowed(2, 1, blurb, 48, 5, 5, 0);
846 strcpy(original_contents, output);
847 output[0] = '\0';
848 type_here =
849 newtEntry(2, newtTextboxGetNumLines(text) + 2,
850 original_contents, 50,
851#ifdef __cplusplus
852 0, NEWT_FLAG_RETURNEXIT
853#else
854 (void *) &entry_value, NEWT_FLAG_RETURNEXIT
855#endif
856 );
857 b_1 = newtButton(6, newtTextboxGetNumLines(text) + 4, " OK ");
858 b_2 = newtButton(18, newtTextboxGetNumLines(text) + 4, "Cancel");
859 // newtOpenWindow (8, 5, 54, newtTextboxGetNumLines (text) + 9, title);
860 newtCenteredWindow(54, newtTextboxGetNumLines(text) + 9, title);
861 myForm = newtForm(NULL, NULL, 0);
862 newtFormAddComponents(myForm, text, type_here, b_1, b_2, NULL);
863 center_string(blurb, 80);
864 newtPushHelpLine(blurb);
865 b_res = newtRunForm(myForm);
866 strcpy(output, entry_value);
867 newtPopHelpLine();
868 newtFormDestroy(myForm);
869 newtPopWindow();
870 if (b_res == b_2) {
871 strcpy(output, original_contents);
872 paranoid_free(blurb);
873 paranoid_free(original_contents);
874 return (FALSE);
875 } else {
876 paranoid_free(blurb);
877 paranoid_free(original_contents);
878 return (TRUE);
879 }
880 }
881
882
883/**
884 * Pop up a dialog box with user-defined buttons.
885 * @param p The text to put in the dialog box.
886 * @param button1 The label on the first button.
887 * @param button2 The label on the second button, or "" if you only want one button.
888 * @return TRUE if @p button1 was pushed, FALSE otherwise.
889 */
890 bool popup_with_buttons(char *p, char *button1, char *button2) {
891
892 /*@ buffers *********************************************************** */
893 char *prompt, *tmp;
894
895 /*@ newt ************************************************************** */
896 newtComponent myForm;
897 newtComponent b_1;
898 newtComponent b_2;
899 newtComponent b_res;
900 newtComponent text;
901
902 prompt = malloc(MAX_NEWT_COMMENT_LEN);
903 tmp = malloc(MAX_NEWT_COMMENT_LEN);
904 assert_string_is_neither_NULL_nor_zerolength(p);
905 assert(button1 != NULL);
906 assert(button2 != NULL);
907 if (g_text_mode) {
908 if (strlen(button2) == 0) {
909 printf("%s (%s) --> ", p, button1);
910 } else {
911 printf("%s (%s or %s) --> ", p, button1, button2);
912 }
913 for (tmp[0] = '\0';
914 strcmp(tmp, button1) && (strlen(button2) == 0
915 || strcmp(tmp, button2));) {
916 printf("--> ");
917 (void) fgets(tmp, MAX_NEWT_COMMENT_LEN, stdin);
918 }
919 if (!strcmp(tmp, button1)) {
920 paranoid_free(tmp);
921 paranoid_free(prompt);
922 return (TRUE);
923 } else {
924 paranoid_free(tmp);
925 paranoid_free(prompt);
926 return (FALSE);
927 }
928 }
929
930 strncpy(prompt, p, MAX_NEWT_COMMENT_LEN - 1);
931 prompt[MAX_NEWT_COMMENT_LEN - 1] = '\0';
932 text = newtTextboxReflowed(1, 1, prompt, 40, 5, 5, 0);
933 b_1 =
934 newtButton(20 -
935 ((button2[0] !=
936 '\0') ? strlen(button1) +
937 2 : strlen(button1) / 2),
938 newtTextboxGetNumLines(text) + 3, button1);
939 if (button2[0] != '\0') {
940 b_2 =
941 newtButton(24, newtTextboxGetNumLines(text) + 3, button2);
942 } else {
943 b_2 = NULL;
944 }
945 // newtOpenWindow (25, 5, 46, newtTextboxGetNumLines (text) + 7, "Alert");
946 newtCenteredWindow(46, newtTextboxGetNumLines(text) + 7, "Alert");
947 myForm = newtForm(NULL, NULL, 0);
948 newtFormAddComponents(myForm, text, b_1, b_2, NULL);
949 center_string(prompt, 80);
950 newtPushHelpLine(prompt);
951 b_res = newtRunForm(myForm);
952 newtPopHelpLine();
953 newtFormDestroy(myForm);
954 newtPopWindow();
955 if (b_res == b_1) {
956 paranoid_free(tmp);
957 paranoid_free(prompt);
958 return (TRUE);
959 } else {
960 paranoid_free(tmp);
961 paranoid_free(prompt);
962 return (FALSE);
963 }
964 }
965
966
967
968
969/**
970 * Synchronize the log messages stored in @p err_log_lines with those shown
971 * on the screen.
972 */
973 void
974 refresh_log_screen() {
975
976 /*@ int *********************************************************** */
977 int i = 0;
978
979
980 if (g_text_mode || !err_log_lines) {
981 return;
982 }
983 for (i = g_noof_log_lines - 1; i >= 0; i--) {
984 newtDrawRootText(0, i + g_noof_rows - 1 - g_noof_log_lines,
985 " ");
986 }
987 newtRefresh();
988 for (i = g_noof_log_lines - 1; i >= 0; i--) {
989 err_log_lines[i][79] = '\0';
990 newtDrawRootText(0, i + g_noof_rows - 1 - g_noof_log_lines,
991 err_log_lines[i]);
992 }
993 newtRefresh();
994 }
995
996
997/**
998 * Set up the Newt graphical environment. If @p g_text_mode is TRUE, then
999 * only allocate some memory.
1000 */
1001 void
1002 setup_newt_stuff() {
1003
1004 /*@ int *********************************************************** */
1005 int i = 0;
1006 int cols;
1007
1008 if (!g_text_mode) {
1009 newtInit();
1010 newtCls();
1011 newtPushHelpLine
1012 ("Welcome to Mondo Rescue, by Dev Team and the Internet. All rights reversed.");
1013 /* newtDrawRootText(28,0,"Welcome to Mondo Rescue"); */
1014 newtDrawRootText(18, 0, WELCOME_STRING);
1015 newtRefresh();
1016 newtGetScreenSize(&cols, &g_noof_rows);
1017 g_noof_log_lines = (g_noof_rows / 5) + 1;
1018 }
1019
1020 err_log_lines =
1021 (char **) malloc(sizeof(char *) * g_noof_log_lines);
1022 if (!err_log_lines) {
1023 fatal_error("Out of memory");
1024 }
1025
1026 for (i = 0; i < g_noof_log_lines; i++) {
1027 err_log_lines[i] = (char *) malloc(MAX_NEWT_COMMENT_LEN);
1028 if (!err_log_lines[i]) {
1029 fatal_error("Out of memory");
1030 }
1031 }
1032
1033 for (i = 0; i < g_noof_log_lines; i++) {
1034 err_log_lines[i][0] = '\0';
1035 }
1036 }
1037
1038
1039/**
1040 * Update the evalcall form to show (<tt>num</tt>/<tt>denom</tt>)*100 %.
1041 * @param num The numerator of the ratio.
1042 * @param denom The denomenator of the ratio.
1043 */
1044 void
1045 update_evalcall_form_ratio(int num, int denom) {
1046
1047 /*@ long ************************************************************ */
1048 long current_time = 0;
1049 long time_taken = 0;
1050 long time_total_est = 0;
1051 long time_remaining = 0;
1052
1053 /*@ buffers ********************************************************** */
1054 char *timeline_str;
1055 char *pcline_str;
1056 char *taskprogress;
1057
1058 /*@ int ************************************************************** */
1059 int percentage = 0;
1060 int i = 0;
1061 int j = 0;
1062
1063 malloc_string(timeline_str);
1064 malloc_string(pcline_str);
1065 malloc_string(taskprogress);
1066 timeline_str[0] = '\0';
1067// log_it("update_eval_call_form called");
1068 if (num * 100 < denom) {
1069 percentage = 1;
1070 } else {
1071 percentage = (num * 100 + denom / 2) / denom;
1072 }
1073
1074 current_time = get_time();
1075 time_taken = current_time - g_isoform_starttime;
1076 if (num) {
1077 time_total_est = time_taken * denom / num;
1078 time_remaining = time_total_est - time_taken;
1079 } else {
1080 time_remaining = 0;
1081 }
1082 if (!g_text_mode) {
1083 newtLabelSetText(g_isoform_header, g_isoform_header_str);
1084 }
1085 g_mysterious_dot_counter = (g_mysterious_dot_counter + 1) % 27;
1086 if ((percentage < 3 && g_isoform_old_progress < 3)
1087 || percentage > g_isoform_old_progress) {
1088 g_isoform_old_progress = percentage;
1089 sprintf(timeline_str,
1090 "%2ld:%02ld taken %2ld:%02ld remaining",
1091 time_taken / 60, time_taken % 60, time_remaining / 60,
1092 time_remaining % 60);
1093 if (percentage < 3) {
1094 sprintf(pcline_str, " Working");
1095 for (j = 0; j < g_mysterious_dot_counter; j++) {
1096 strcat(pcline_str, ".");
1097 }
1098 for (; j < 27; j++) {
1099 strcat(pcline_str, " ");
1100 }
1101 sprintf(pcline_str + strlen(pcline_str), " %c",
1102 special_dot_char(g_mysterious_dot_counter));
1103 } else {
1104 sprintf(pcline_str, " %3d%% done %3d%% to go",
1105 percentage, 100 - percentage);
1106 }
1107 if (g_text_mode) {
1108 sprintf(taskprogress, "TASK: [");
1109 for (i = 0; i < percentage; i += 5) {
1110 strcat(taskprogress, "*");
1111 }
1112 for (; i < 100; i += 5) {
1113 strcat(taskprogress, ".");
1114 }
1115 if (percentage >= 3) {
1116 sprintf(taskprogress + strlen(taskprogress),
1117 "] %3d%% done; %2ld:%02ld to go", percentage,
1118 time_remaining / 60, time_remaining % 60);
1119 printf("---evalcall---1--- %s\r\n",
1120 g_isoform_header_str);
1121 printf("---evalcall---2--- %s\r\n", taskprogress);
1122 printf("---evalcall---E---\r\n");
1123 }
1124 } else {
1125 newtScaleSet(g_isoform_scale,
1126 (unsigned long long) percentage);
1127 newtLabelSetText(g_isoform_pcline, pcline_str);
1128 if (percentage >= 3) {
1129 newtLabelSetText(g_isoform_timeline, timeline_str);
1130 }
1131 }
1132 }
1133 if (!g_text_mode) {
1134// log_it("refreshing");
1135 newtRefresh();
1136 }
1137 paranoid_free(timeline_str);
1138 paranoid_free(pcline_str);
1139 paranoid_free(taskprogress);
1140 }
1141
1142
1143
1144/**
1145 * Update the evalcall form to show @p curr %.
1146 * @param curr The current amount of progress (percentage) in the evalcall form.
1147 */
1148 void
1149 update_evalcall_form(int curr) {
1150 update_evalcall_form_ratio(curr, 100);
1151 }
1152
1153
1154
1155/**
1156 * Update the progress form to show @p blurb3 and the current value of
1157 * @p g_maximum_progress.
1158 * @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.
1159 */
1160 void
1161 update_progress_form(char *blurb3) {
1162 /* log_it("update_progress_form --- called"); */
1163 if (g_current_progress == -999) {
1164 /* 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."); */
1165 return;
1166 }
1167 strcpy(g_blurb_str_2, blurb3);
1168 update_progress_form_full(g_blurb_str_1, g_blurb_str_2,
1169 g_blurb_str_3);
1170 }
1171
1172
1173/**
1174 * Update the progress form's complete blurb and show @p g_current_progress.
1175 * @param blurb1 The first line of the blurb. Use @p g_blurb_str_1 to keep it unchanged.
1176 * @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.
1177 * @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.
1178 */
1179 void
1180 update_progress_form_full(char *blurb1, char *blurb2, char *blurb3) {
1181 /*@ long ***************************************************** */
1182 long current_time = 0;
1183 long time_taken = 0;
1184 long time_remaining = 0;
1185 long time_total_est = 0;
1186
1187 /*@ int ******************************************************* */
1188 int percentage = 0;
1189 int i = 0;
1190
1191 /*@ buffers *************************************************** */
1192 char *percentline_str;
1193 char *timeline_str;
1194 char *taskprogress;
1195 char *tmp;
1196
1197// log_msg(1, "'%s' '%s' '%s'", blurb1, blurb2, blurb3);
1198 percentline_str = malloc(MAX_NEWT_COMMENT_LEN);
1199 timeline_str = malloc(MAX_NEWT_COMMENT_LEN);
1200 taskprogress = malloc(MAX_NEWT_COMMENT_LEN);
1201 malloc_string(tmp);
1202 if (!g_text_mode) {
1203 assert(blurb1 != NULL);
1204 assert(blurb2 != NULL);
1205 assert(blurb3 != NULL);
1206 assert(g_timeline != NULL);
1207 }
1208
1209 percentline_str[0] = '\0';
1210
1211 current_time = get_time();
1212 time_taken = current_time - g_start_time;
1213 if (g_maximum_progress == 0) {
1214 percentage = 0;
1215 } else {
1216 if (g_current_progress > g_maximum_progress) {
1217 sprintf(tmp,
1218 "update_progress_form_full(%s,%s,%s) --- g_current_progress=%ld; g_maximum_progress=%ld",
1219 blurb1, blurb2, blurb3, g_current_progress,
1220 g_maximum_progress);
1221 log_msg(0, tmp);
1222 g_current_progress = g_maximum_progress;
1223 }
1224 percentage =
1225 (int) ((g_current_progress * 100L) / g_maximum_progress);
1226 }
1227 if (percentage < 1) {
1228 percentage = 1;
1229 }
1230 if (percentage > 100) {
1231 percentage = 100;
1232 }
1233 if (g_current_progress) {
1234 time_total_est =
1235 time_taken * (long) g_maximum_progress /
1236 (long) (g_current_progress);
1237 time_remaining = time_total_est - time_taken;
1238 } else {
1239 time_remaining = 0;
1240 }
1241 g_mysterious_dot_counter = (g_mysterious_dot_counter + 1) % 27;
1242 sprintf(timeline_str,
1243 "%2ld:%02ld taken %2ld:%02ld remaining ",
1244 time_taken / 60, time_taken % 60, time_remaining / 60,
1245 time_remaining % 60);
1246 sprintf(percentline_str, " %3d%% done %3d%% to go",
1247 percentage, 100 - percentage);
1248
1249 if (g_text_mode) {
1250 printf("---progress-form---1--- %s\r\n", blurb1);
1251 printf("---progress-form---2--- %s\r\n", blurb2);
1252 printf("---progress-form---3--- %s\r\n", blurb3);
1253 printf("---progress-form---E---\n");
1254 sprintf(taskprogress, "TASK: [");
1255 for (i = 0; i < percentage; i += 5) {
1256 strcat(taskprogress, "*");
1257 }
1258 for (; i < 100; i += 5) {
1259 strcat(taskprogress, ".");
1260 }
1261 if (percentage > 100) {
1262 log_msg(2, "percentage = %d", percentage);
1263 }
1264 sprintf(taskprogress + strlen(taskprogress),
1265 "] %3d%c", percentage, '%');
1266 sprintf(taskprogress + strlen(taskprogress),
1267 " done; %2ld:%02ld to go",
1268 time_remaining / 60, time_remaining % 60);
1269 printf("---progress-form---4--- %s\r\n", taskprogress);
1270 } else {
1271 center_string(blurb1, 54);
1272 center_string(blurb2, 54);
1273 center_string(blurb3, 54);
1274 newtLabelSetText(g_blurb1, blurb1);
1275 newtLabelSetText(g_blurb2, blurb3);
1276 newtLabelSetText(g_blurb3, blurb2);
1277 newtScaleSet(g_scale, (unsigned long long) g_current_progress);
1278 if (percentage >= 2) {
1279 newtLabelSetText(g_timeline, timeline_str);
1280 }
1281 newtLabelSetText(g_percentline, percentline_str);
1282 newtRefresh();
1283 }
1284 paranoid_free(percentline_str);
1285 paranoid_free(timeline_str);
1286 paranoid_free(taskprogress);
1287 paranoid_free(tmp);
1288 }
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303/**
1304 * Ask the user which backup media type they would like to use.
1305 * The choices are @p none (exit to shell), @c cdr, @c cdrw, @c dvd,
1306 * @c tape, @c cdstream, @c udev (only when @p g_text_mode is TRUE), @c nfs,
1307 * and @c iso.
1308 * @param restoring TRUE if we're restoring, FALSE if we're backing up.
1309 * @return The backup type chosen, or @c none if the user chose "Exit to shell".
1310 */
1311 t_bkptype which_backup_media_type(bool restoring) {
1312
1313 /*@ char ************************************************************ */
1314 t_bkptype output;
1315
1316
1317 /*@ newt ************************************************************ */
1318 char *title_sz;
1319 char *minimsg_sz;
1320 static t_bkptype possible_bkptypes[] =
1321 { none, cdr, cdrw, dvd, tape, cdstream, udev, nfs, iso };
1322 static char *possible_responses[] =
1323 { "none", "cdr", "cdrw", "dvd", "tape", "cdstream", "udev",
1324"nfs", "iso", NULL };
1325 char *outstr;
1326 t_bkptype backup_type;
1327 int i;
1328
1329 newtComponent b1;
1330 newtComponent b2;
1331 newtComponent b3;
1332 newtComponent b4;
1333 newtComponent b5;
1334 newtComponent b6;
1335 newtComponent b7;
1336 newtComponent b8;
1337 newtComponent b_res;
1338 newtComponent myForm;
1339
1340 title_sz = malloc(MAX_NEWT_COMMENT_LEN);
1341 minimsg_sz = malloc(MAX_NEWT_COMMENT_LEN);
1342 outstr = malloc(MAX_NEWT_COMMENT_LEN);
1343 if (g_text_mode) {
1344 for (backup_type = none; backup_type == none;) {
1345 printf("Backup type (");
1346 for (i = 0; possible_responses[i]; i++) {
1347 printf("%c%s", (i == 0) ? '\0' : ' ',
1348 possible_responses[i]);
1349 }
1350 printf(")\n--> ");
1351 (void) fgets(outstr, MAX_NEWT_COMMENT_LEN, stdin);
1352 strip_spaces(outstr);
1353 for (i = 0; possible_responses[i]; i++) {
1354 if (!strcmp(possible_responses[i], outstr)) {
1355 backup_type = possible_bkptypes[i];
1356 }
1357 }
1358 }
1359 paranoid_free(title_sz);
1360 paranoid_free(minimsg_sz);
1361 paranoid_free(outstr);
1362 return (backup_type);
1363 }
1364 newtDrawRootText(18, 0, WELCOME_STRING);
1365 if (restoring) {
1366 strcpy(title_sz,
1367 "Please choose the backup media from which you want to read data.");
1368 strcpy(minimsg_sz, "Read from:");
1369 } else {
1370 strcpy(title_sz,
1371 "Please choose the backup media to which you want to archive data.");
1372 strcpy(minimsg_sz, "Backup to:");
1373 }
1374 newtPushHelpLine(title_sz);
1375 // newtOpenWindow (23, 3, 34, 17, minimsg_sz);
1376 newtCenteredWindow(34, 17, minimsg_sz);
1377 b1 = newtButton(1, 1, "CD-R disks ");
1378 b2 = newtButton(17, 1, "CD-RW disks");
1379 b3 = newtButton(1, 9, "Tape drive ");
1380 b4 = newtButton(17, 5, "CD streamer");
1381 b5 = newtButton(1, 5, " DVD disks ");
1382 b6 = newtButton(17, 9, " NFS mount ");
1383 b7 = newtButton(1, 13, " Hard disk ");
1384 b8 = newtButton(17, 13, " Exit ");
1385 myForm = newtForm(NULL, NULL, 0);
1386 newtFormAddComponents(myForm, b1, b5, b3, b7, b2, b4, b6, b8,
1387 NULL);
1388 b_res = newtRunForm(myForm);
1389 newtFormDestroy(myForm);
1390 newtPopWindow();
1391 if (b_res == b1) {
1392 output = cdr;
1393 } else if (b_res == b2) {
1394 output = cdrw;
1395 } else if (b_res == b3) {
1396 output = tape;
1397 } else if (b_res == b4) {
1398 output = cdstream;
1399 } else if (b_res == b5) {
1400 output = dvd;
1401 } else if (b_res == b6) {
1402 output = nfs;
1403 } else if (b_res == b7) {
1404 output = iso;
1405 } else {
1406 output = none;
1407 }
1408 newtPopHelpLine();
1409 paranoid_free(title_sz);
1410 paranoid_free(minimsg_sz);
1411 paranoid_free(outstr);
1412 return (output);
1413 }
1414
1415
1416
1417
1418/**
1419 * Ask the user how much compression they would like to use.
1420 * The choices are "None" (0), "Minimum" (1), "Average" (4), and "Maximum" (9).
1421 * @return The compression level (0-9) chosen, or -1 for "Exit".
1422 */
1423 int
1424 which_compression_level() {
1425
1426 /*@ char ************************************************************ */
1427 int output = none;
1428
1429
1430 /*@ newt ************************************************************ */
1431
1432 newtComponent b1;
1433 newtComponent b2;
1434 newtComponent b3;
1435 newtComponent b4;
1436 newtComponent b5;
1437 newtComponent b_res;
1438 newtComponent myForm;
1439
1440 newtDrawRootText(18, 0, WELCOME_STRING);
1441 newtPushHelpLine
1442 (" Please specify the level of compression that you want.");
1443 // newtOpenWindow (23, 3, 34, 13, "How much compression?");
1444 newtCenteredWindow(34, 13, "How much compression?");
1445 b1 = newtButton(4, 1, "Maximum");
1446 b2 = newtButton(18, 1, "Average");
1447 b3 = newtButton(4, 5, "Minumum");
1448 b4 = newtButton(18, 5, " None ");
1449 b5 = newtButton(4, 9, " Exit ");
1450 myForm = newtForm(NULL, NULL, 0);
1451 newtFormAddComponents(myForm, b1, b3, b2, b4, b5, NULL);
1452 b_res = newtRunForm(myForm);
1453 newtFormDestroy(myForm);
1454 newtPopWindow();
1455 if (b_res == b1) {
1456 output = 9;
1457 } else if (b_res == b2) {
1458 output = 4;
1459 } else if (b_res == b3) {
1460 output = 1;
1461 } else if (b_res == b4) {
1462 output = 0;
1463 } else if (b_res == b5) {
1464 output = -1;
1465 }
1466 newtPopHelpLine();
1467 return (output);
1468 }
1469
1470
1471
1472
1473
1474/**
1475 * Load @p source_file (a list of files) into @p filelist. There can be no more than
1476 * @p ARBITRARY_MAXIMUM entries.
1477 * @param filelist The filelist structure to load @p source_file into.
1478 * @param source_file The file containing a list of filenames to load into @p filelist.
1479 */
1480 int load_filelist_into_array(struct s_filelist *filelist,
1481 char *source_file) {
1482 int i;
1483 bool done;
1484 char *tmp;
1485 FILE *fin;
1486 struct s_filelist_entry dummy_fle;
1487
1488 malloc_string(tmp);
1489 assert(filelist != NULL);
1490 assert_string_is_neither_NULL_nor_zerolength(source_file);
1491
1492 iamhere("entering");
1493 if (!(fin = fopen(source_file, "r"))) {
1494 log_OS_error(source_file);
1495 log_msg(2, "Can't open %s; therefore, cannot popup list",
1496 source_file);
1497 paranoid_free(tmp);
1498 return (1);
1499 }
1500 log_msg(2, "Loading %s", source_file);
1501 for (filelist->entries = 0; filelist->entries <= ARBITRARY_MAXIMUM;
1502 filelist->entries++) {
1503 god_i_hate_gotos:
1504 if (feof(fin)) {
1505 break;
1506 }
1507 (void) fgets(tmp, MAX_NEWT_COMMENT_LEN, fin);
1508 i = (int) strlen(tmp);
1509 if (i < 2) {
1510 goto god_i_hate_gotos;
1511 }
1512 if (tmp[i - 1] < 32) {
1513 tmp[--i] = '\0';
1514 }
1515 if (i < 2) {
1516 goto god_i_hate_gotos;
1517 }
1518 if (!does_file_exist(tmp)) {
1519 goto god_i_hate_gotos;
1520 }
1521 filelist->el[filelist->entries].severity =
1522 severity_of_difference(tmp, NULL);
1523 strcpy(filelist->el[filelist->entries].filename, tmp);
1524 if (feof(fin)) {
1525 break;
1526 }
1527 }
1528 paranoid_fclose(fin);
1529 if (filelist->entries >= ARBITRARY_MAXIMUM) {
1530 log_to_screen("Arbitrary limits suck, man!");
1531 paranoid_free(tmp);
1532 return (1);
1533 }
1534 for (done = FALSE; !done;) {
1535 done = TRUE;
1536 for (i = 0; i < filelist->entries - 1; i++) {
1537// if (strcmp(filelist->el[i].filename, filelist->el[i+1].filename) > 0)
1538 if (filelist->el[i].severity < filelist->el[i + 1].severity
1539 || (filelist->el[i].severity ==
1540 filelist->el[i + 1].severity
1541 && strcmp(filelist->el[i].filename,
1542 filelist->el[i + 1].filename) > 0)) {
1543 memcpy((void *) &dummy_fle,
1544 (void *) &(filelist->el[i]),
1545 sizeof(struct s_filelist_entry));
1546 memcpy((void *) &(filelist->el[i]),
1547 (void *) &(filelist->el[i + 1]),
1548 sizeof(struct s_filelist_entry));
1549 memcpy((void *) &(filelist->el[i + 1]),
1550 (void *) &dummy_fle,
1551 sizeof(struct s_filelist_entry));
1552 log_msg(2, "Swapping %s and %s",
1553 filelist->el[i].filename,
1554 filelist->el[i + 1].filename);
1555 done = FALSE;
1556 }
1557 }
1558 }
1559 paranoid_free(tmp);
1560 iamhere("leaving");
1561 return (0);
1562 }
1563
1564
1565
1566/**
1567 * Generate a pretty string based on @p flentry.
1568 * @param flentry The filelist entry to stringify.
1569 * @return The string form of @p flentry.
1570 * @note The returned value points to static storage that will be overwritten with each call.
1571 */
1572 char *filelist_entry_to_string(struct s_filelist_entry *flentry) {
1573 static char comment[100];
1574 char *tmp;
1575
1576 iamhere("entering");
1577 malloc_string(tmp);
1578 assert(flentry != NULL);
1579 if (flentry->severity == 0) {
1580 strcpy(tmp, "0 ");
1581 } else if (flentry->severity == 1) {
1582 strcpy(tmp, "low ");
1583 } else if (flentry->severity == 2) {
1584 strcpy(tmp, "med ");
1585 } else {
1586 strcpy(tmp, "high");
1587 }
1588 strcat(tmp, " ");
1589 strncat(tmp, flentry->filename, 100);
1590 tmp[98] = '\0';
1591 strcpy(comment, tmp);
1592 paranoid_free(tmp);
1593 iamhere("leaving");
1594 return (comment);
1595 }
1596
1597
1598
1599
1600
1601/**
1602 * Pop up a list containing the filenames in @p source_file and the severity if they have changed since the
1603 * last backup. There can be no more than @p ARBITRARY_MAXIMUM files in @p source_file.
1604 * @param source_file The file containing a list of changed files.
1605 */
1606 void popup_changelist_from_file(char *source_file) {
1607 char *reason;
1608 newtComponent myForm;
1609 newtComponent bClose;
1610 newtComponent bSelect;
1611 newtComponent b_res;
1612 newtComponent fileListbox;
1613 newtComponent headerMsg;
1614
1615 /*@ ???? ************************************************************ */
1616 void *curr_choice;
1617 void *keylist[ARBITRARY_MAXIMUM];
1618
1619 /*@ int ************************************************************* */
1620 int currline = 0;
1621 int finished = FALSE;
1622
1623 /*@ long ************************************************************ */
1624 long i = 0;
1625 long lng = 0;
1626
1627 /*@ buffers ********************************************************* */
1628 char *tmp;
1629 char *differ_sz;
1630
1631 struct s_filelist *filelist;
1632 malloc_string(reason);
1633 tmp = malloc(5000);
1634 malloc_string(differ_sz);
1635 assert_string_is_neither_NULL_nor_zerolength(source_file);
1636 if (g_text_mode) {
1637 log_msg(2, "Text mode. Therefore, no popup list.");
1638 goto free_to_go;
1639 }
1640 log_msg(2, "Examining file %s", source_file);
1641
1642 lng = count_lines_in_file(source_file);
1643 if (lng < 1) {
1644 log_msg(2, "No lines in file. Therefore, no popup list.");
1645 paranoid_free(reason);
1646 goto free_to_go;
1647 } else if (lng >= ARBITRARY_MAXIMUM) {
1648 log_msg(2, "Too many files differ for me to list.");
1649 goto free_to_go;
1650 }
1651
1652 filelist = (struct s_filelist *) malloc(sizeof(struct s_filelist));
1653 fileListbox =
1654 newtListbox(2, 2, 12, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1655 newtListboxClear(fileListbox);
1656
1657 if (load_filelist_into_array(filelist, source_file)) {
1658 log_msg(2, "Can't open %s; therefore, cannot popup list",
1659 source_file);
1660 paranoid_free(reason);
1661 return;
1662 }
1663 log_msg(2, "%d files loaded into filelist array",
1664 filelist->entries);
1665 for (i = 0; i < filelist->entries; i++) {
1666 keylist[i] = (void *) i;
1667 newtListboxAppendEntry(fileListbox,
1668 filelist_entry_to_string(&
1669 (filelist->
1670 el[i])),
1671 keylist[i]);
1672 }
1673 sprintf(differ_sz,
1674 " %ld files differ. Hit 'Select' to pick a file. Hit 'Close' to quit the list.",
1675 i);
1676 newtPushHelpLine(differ_sz);
1677 bClose = newtCompactButton(10, 15, " Close ");
1678 bSelect = newtCompactButton(30, 15, " Select ");
1679 sprintf(tmp, "%-10s %-20s", "Priority", "Filename");
1680 headerMsg = newtLabel(2, 1, tmp);
1681 newtOpenWindow(5, 4, 70, 16, "Non-matching files");
1682 myForm = newtForm(NULL, NULL, 0);
1683 newtFormAddComponents(myForm, headerMsg, fileListbox, bClose,
1684 bSelect, NULL);
1685 while (!finished) {
1686 b_res = newtRunForm(myForm);
1687 if (b_res == bClose) {
1688 finished = TRUE;
1689 } else {
1690 curr_choice = newtListboxGetCurrent(fileListbox);
1691 for (i = 0;
1692 i < filelist->entries && keylist[i] != curr_choice;
1693 i++);
1694 if (i == filelist->entries && filelist->entries > 0) {
1695 log_to_screen("I don't know what that button does!");
1696 } else {
1697 currline = i;
1698 if (filelist->entries > 0) {
1699 severity_of_difference(filelist->el[currline].
1700 filename, reason);
1701 sprintf(tmp, "%s --- %s",
1702 filelist->el[currline].filename, reason);
1703 popup_and_OK(tmp);
1704 }
1705 }
1706 }
1707 }
1708 newtFormDestroy(myForm);
1709 newtPopWindow();
1710 newtPopHelpLine();
1711 free_to_go:
1712 paranoid_free(reason);
1713 paranoid_free(tmp);
1714 paranoid_free(differ_sz);
1715 return;
1716 }
1717
1718/* @} - end of guiGroup */
1719
1720
1721#if __cplusplus
1722} /* extern "C" */
1723#endif
1724
1725
1726void wait_until_software_raids_are_prepped(char *mdstat_file,
1727 int wait_for_percentage);
Note: See TracBrowser for help on using the repository browser.