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

Last change on this file since 1315 was 1315, checked in by bruno, 12 years ago

Log files are now consistent: mondoarchive.log for mondoarchive (containing also mindi.log) and mondorestore.log for mondorestore (copied from /tmp (ram) to /var/log (disk) at the end of the restore)
One include has been created for each bianry containing only that declaration ofr the moment, but which will be extended to include all local definitions (ps_* e.g.)
Doc updated accordingly
LOGFILE in restore process is now passed in the environment and not duplicated anymore
LogIt? is not redifined either
LOGFILE should be put in environment by mondoarchive for mindi's usage but that's a step left for later.

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