source: MondoRescue/trunk/mondo/mondo/common/newt-specific.c@ 75

Last change on this file since 75 was 75, checked in by andree, 19 years ago

Various changes to get archiving to NFS work in interactive mode. It
wasn't really like were were bugs, it appeared more like it was simply
not finished.

Side note: I believe that bkpinfo->isodir and bkpinfo->prefix were the
wrong way round in libmondo-archive.c and I've swapped them.

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