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

Last change on this file since 900 was 900, checked in by Bruno Cornec, 13 years ago

Huge patch to introduce low level functions that will bw used everywhere (mr_free, mr_asprintf, ...)
Nearly linking now due to that.

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