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

Last change on this file since 688 was 688, checked in by bcornec, 13 years ago

Huge memory management patch.
Still not finished but a lot as been done.
What remains is around some functions returning strings, and some structure members.
(Could not finish due to laptop failure !)

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