source: branches/2.2.5/mondo/src/common/newt-specific.c @ 1708

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