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

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

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

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

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