source: branches/stable/mondo/src/common/newt-specific.c @ 928

Last change on this file since 928 was 928, checked in by Bruno Cornec, 14 years ago

ps (busybox) and ps (system) do not give PID in the same column. Adapted with a global variable.

  • Property svn:keywords set to Id
File size: 47.7 KB
Line 
1/* newt-specific.c
2   $Id: newt-specific.c 928 2006-11-13 09:17:07Z 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 928 2006-11-13 09:17:07Z 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
351asprintf(&tmp,"kill `ps %s | grep \" %s \" | awk '{print %s;}' | grep -vx \"\\?\"`", ps_options, str , ps_proc_id);
352run_program_and_log_output(tmp, TRUE);
353paranoid_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        system
438            ("gzip -9c /var/log/mondo-archive.log > /tmp/MA.log.gz 2> /dev/null");
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                    strip_spaces(err_log_lines[i]);
560                    if (!strncmp(err_log_lines[i], "root:", 5)) {
561                        strcpy(tmp, err_log_lines[i] + 6);
562                        strcpy(err_log_lines[i], tmp);
563                    }
564                    if (feof(fin)) {
565                        break;
566                    }
567                }
568            }
569            paranoid_pclose(fin);
570        }
571        refresh_log_screen();
572        paranoid_free(command);
573        paranoid_free(tmp);
574    }
575
576
577/**
578 * Log a message to the screen.
579 * @param fmt A printf-style format string to write. The following parameters are its arguments.
580 * @note The message is also written to the logfile.
581 */
582    void
583     log_to_screen(const char *fmt, ...) {
584
585        /*@ int ************************************************************** */
586        int i = 0;
587        int j = 0;
588        va_list args;
589
590        /*@ buffers ********************************************************** */
591        char *output;
592
593        malloc_string(output);
594
595        va_start(args, fmt);
596        vsprintf(output, fmt, args);
597        log_msg(0, output);
598        output[80] = '\0';
599        va_end(args);
600        i = (int) strlen(output);
601        if (i > 0 && output[i - 1] < 32) {
602            output[i - 1] = '\0';
603        }
604
605        if (err_log_lines) {
606            for (i = 1; i < g_noof_log_lines; i++) {
607                strcpy(err_log_lines[i - 1],
608                       "                                                                                ");
609                strcpy(err_log_lines[i - 1], err_log_lines[i]);
610            }
611        }
612        while (strlen(output) > 0 && output[strlen(output) - 1] < 32) {
613            output[strlen(output) - 1] = '\0';
614        }
615        for (j = 0; j < (int) strlen(output); j++) {
616            if (output[j] < 32) {
617                output[j] = ' ';
618            }
619        }
620        if (err_log_lines)
621            strcpy(err_log_lines[g_noof_log_lines - 1], output);
622        if (g_text_mode) {
623            printf("%s\n", output);
624        } else {
625            refresh_log_screen();
626        }
627        paranoid_free(output);
628    }
629
630
631
632
633/**
634 * Write a string to the root window at (@p x, @p y) and also to the logfile.
635 * @param y The row to write the string to.
636 * @param x The column to write the string to.
637 * @param output The string to write.
638 */
639    void
640     mvaddstr_and_log_it(int y, int x, char *output) {
641        assert_string_is_neither_NULL_nor_zerolength(output);
642        log_msg(0, output);
643        if (g_text_mode) {
644            printf("%s\n", output);
645        } else {
646            newtDrawRootText(x, y, output);
647            newtRefresh();
648        }
649    }
650
651
652
653
654/**
655 * Open an evalcall form with title @p ttl.
656 * @param ttl The title to use for the evalcall form.
657 */
658    void
659     open_evalcall_form(char *ttl) {
660
661        /*@ buffers ********************************************************* */
662        char *title;
663        char *tmp;
664
665        /*@ initialize ****************************************************** */
666        g_isoform_old_progress = -1;
667        g_mysterious_dot_counter = 0;
668        malloc_string(title);
669        malloc_string(tmp);
670
671        assert(ttl != NULL);
672        strcpy(title, ttl);
673        strcpy(g_isoform_header_str, title);
674//  center_string (title, 80);
675        if (g_text_mode) {
676            log_msg(0, title);
677        } else {
678            strcpy(tmp, title);
679            center_string(tmp, 80);
680            newtPushHelpLine(tmp);
681        }
682        center_string(g_isoform_header_str, 36);
683        g_isoform_starttime = get_time();
684        if (g_text_mode) {
685            log_msg(0, g_isoform_header_str);
686        } else {
687            g_isoform_header = newtLabel(1, 1, g_isoform_header_str);
688            g_isoform_scale = newtScale(3, 3, 34, 100);
689            //      newtOpenWindow (20, 6, 40, 7, title);      // "Please Wait");
690            newtCenteredWindow(40, 7, title);
691            g_isoform_main = newtForm(NULL, NULL, 0);
692            g_isoform_timeline = newtLabel(1, 5, "This is the timeline");
693            g_isoform_pcline = newtLabel(1, 6, "This is the pcline");
694            newtFormAddComponents(g_isoform_main, g_isoform_timeline,
695                                  g_isoform_pcline, g_isoform_header,
696                                  g_isoform_scale, NULL);
697            newtRefresh();
698        }
699        update_evalcall_form(0);
700        paranoid_free(tmp);
701        paranoid_free(title);
702    }
703
704
705
706/**
707 * Open a progress form with title @p title.
708 * @param title The title to use for the progress form (will be put in the title bar on Newt).
709 * @param b1 The first line of the blurb; generally static.
710 * @param b2 The second line of the blurb; generally static.
711 * @param b3 The third line of the blurb; generally dynamic (it is passed
712 * to update_evalcall_form() every time).
713 * @param max_val The maximum amount of progress (number of filesets, etc.)
714 */
715    void
716     open_progress_form(char *title, char *b1, char *b2, char *b3,
717                        long max_val) {
718
719        /*@ buffers ********************************************************* */
720        char *b1c;
721        char *blurb1;
722        char *blurb2;
723        char *blurb3;
724
725        /*@ initialize ****************************************************** */
726        g_mysterious_dot_counter = 0;
727
728        malloc_string(b1c);
729        malloc_string(blurb1);
730        malloc_string(blurb2);
731        malloc_string(blurb3);
732
733        assert(title != NULL);
734        assert(b1 != NULL);
735        assert(b2 != NULL);
736        assert(b3 != NULL);
737
738        strcpy(blurb1, b1);
739        strcpy(blurb2, b2);
740        strcpy(blurb3, b3);
741        strcpy(b1c, b1);
742        center_string(b1c, 80);
743        if (max_val <= 0) {
744            max_val = 1;
745        }
746
747        g_start_time = get_time();
748        g_maximum_progress = max_val;
749        g_current_progress = 0;
750        strcpy(g_blurb_str_1, blurb1);
751        strcpy(g_blurb_str_2, blurb3);
752        strcpy(g_blurb_str_3, blurb2);
753        if (g_text_mode) {
754            log_msg(0, blurb1);
755            log_msg(0, blurb2);
756            log_msg(0, blurb3);
757        } else {
758            g_blurb1 = newtLabel(2, 1, blurb1);
759            g_blurb2 = newtLabel(2, 2, blurb3);
760            g_blurb3 = newtLabel(2, 4, blurb2);
761            //      newtOpenWindow (10, 4, 60, 11, title);
762            newtCenteredWindow(60, 11, title);
763            g_scale = newtScale(3, 6, 54, g_maximum_progress);
764            g_progressForm = newtForm(NULL, NULL, 0);
765            g_percentline = newtLabel(10, 9, "This is the percentline");
766            g_timeline = newtLabel(10, 8, "This is the timeline");
767            newtFormAddComponents(g_progressForm, g_percentline,
768                                  g_timeline, g_scale, g_blurb1, g_blurb3,
769                                  g_blurb2, NULL);
770            newtPushHelpLine(b1c);
771            newtRefresh();
772        }
773        update_progress_form_full(blurb1, blurb2, blurb3);
774        paranoid_free(b1c);
775        paranoid_free(blurb1);
776        paranoid_free(blurb2);
777        paranoid_free(blurb3);
778    }
779
780/**
781 * Give a message to the user in the form of a dialog box (under Newt).
782 * @param prompt The message.
783 */
784    void
785     popup_and_OK(char *prompt) {
786        char ch;
787
788        assert_string_is_neither_NULL_nor_zerolength(prompt);
789
790        log_msg(0, prompt);
791        if (g_text_mode) {
792            printf
793                ("---promptpopup---1--- %s\r\n---promptpopup---Q--- [OK] ---\r\n--> ",
794                 prompt);
795            while (((ch = getchar()) != '\n') && (ch != EOF));
796        } else {
797            (void) popup_with_buttons(prompt, " OK ", "");
798        }
799    }
800
801/**
802 * Ask the user to enter a value.
803 * @param title The title of the dialog box.
804 * @param b The blurb (e.g. what you want the user to enter).
805 * @param output The string to put the user's answer in.
806 * @param maxsize The size in bytes allocated to @p output.
807 * @return TRUE if the user pressed OK, FALSE if they pressed Cancel.
808 */
809    bool popup_and_get_string(char *title, char *b, char *output,
810                              int maxsize) {
811
812        /*@ newt ************************************************************ */
813        newtComponent myForm;
814        newtComponent b_1;
815        newtComponent b_2;
816        newtComponent b_res;
817        newtComponent text;
818        newtComponent type_here;
819
820        /*@ pointers ********************************************************* */
821        char *entry_value;
822
823        /*@ buffers ********************************************************** */
824        char *blurb;
825        char *original_contents;
826
827        blurb = malloc(MAX_NEWT_COMMENT_LEN);
828        original_contents = malloc(MAX_NEWT_COMMENT_LEN);
829        assert_string_is_neither_NULL_nor_zerolength(title);
830        assert(b != NULL);
831        assert(output != NULL);
832
833        if (g_text_mode) {
834            printf
835                ("---promptstring---1--- %s\r\n---promptstring---2--- %s\r\n---promptstring---Q---\r\n-->  ",
836                 title, b);
837            (void) fgets(output, maxsize, stdin);
838            if (output[strlen(output) - 1] == '\n')
839                output[strlen(output) - 1] = '\0';
840            paranoid_free(blurb);
841            paranoid_free(original_contents);
842            return (TRUE);
843        }
844        strcpy(blurb, b);
845        text = newtTextboxReflowed(2, 1, blurb, 48, 5, 5, 0);
846        strcpy(original_contents, output);
847        output[0] = '\0';
848        type_here =
849            newtEntry(2, newtTextboxGetNumLines(text) + 2,
850                      original_contents, 50,
851#ifdef __cplusplus
852                      0, NEWT_FLAG_RETURNEXIT
853#else
854                      (void *) &entry_value, NEWT_FLAG_RETURNEXIT
855#endif
856            );
857        b_1 = newtButton(6, newtTextboxGetNumLines(text) + 4, "  OK  ");
858        b_2 = newtButton(18, newtTextboxGetNumLines(text) + 4, "Cancel");
859        //  newtOpenWindow (8, 5, 54, newtTextboxGetNumLines (text) + 9, title);
860        newtCenteredWindow(54, newtTextboxGetNumLines(text) + 9, title);
861        myForm = newtForm(NULL, NULL, 0);
862        newtFormAddComponents(myForm, text, type_here, b_1, b_2, NULL);
863        center_string(blurb, 80);
864        newtPushHelpLine(blurb);
865        b_res = newtRunForm(myForm);
866        strcpy(output, entry_value);
867        newtPopHelpLine();
868        newtFormDestroy(myForm);
869        newtPopWindow();
870        if (b_res == b_2) {
871            strcpy(output, original_contents);
872            paranoid_free(blurb);
873            paranoid_free(original_contents);
874            return (FALSE);
875        } else {
876            paranoid_free(blurb);
877            paranoid_free(original_contents);
878            return (TRUE);
879        }
880    }
881
882
883/**
884 * Pop up a dialog box with user-defined buttons.
885 * @param p The text to put in the dialog box.
886 * @param button1 The label on the first button.
887 * @param button2 The label on the second button, or "" if you only want one button.
888 * @return TRUE if @p button1 was pushed, FALSE otherwise.
889 */
890    bool popup_with_buttons(char *p, char *button1, char *button2) {
891
892        /*@ buffers *********************************************************** */
893        char *prompt, *tmp;
894
895        /*@ newt ************************************************************** */
896        newtComponent myForm;
897        newtComponent b_1;
898        newtComponent b_2;
899        newtComponent b_res;
900        newtComponent text;
901
902        prompt = malloc(MAX_NEWT_COMMENT_LEN);
903        tmp = malloc(MAX_NEWT_COMMENT_LEN);
904        assert_string_is_neither_NULL_nor_zerolength(p);
905        assert(button1 != NULL);
906        assert(button2 != NULL);
907        if (g_text_mode) {
908            if (strlen(button2) == 0) {
909                printf("%s (%s) --> ", p, button1);
910            } else {
911                printf("%s (%s or %s) --> ", p, button1, button2);
912            }
913            for (tmp[0] = '\0';
914                 strcmp(tmp, button1) && (strlen(button2) == 0
915                                          || strcmp(tmp, button2));) {
916                printf("--> ");
917                (void) fgets(tmp, MAX_NEWT_COMMENT_LEN, stdin);
918            }
919            if (!strcmp(tmp, button1)) {
920                paranoid_free(tmp);
921                paranoid_free(prompt);
922                return (TRUE);
923            } else {
924                paranoid_free(tmp);
925                paranoid_free(prompt);
926                return (FALSE);
927            }
928        }
929
930        strncpy(prompt, p, MAX_NEWT_COMMENT_LEN - 1);
931        prompt[MAX_NEWT_COMMENT_LEN - 1] = '\0';
932        text = newtTextboxReflowed(1, 1, prompt, 40, 5, 5, 0);
933        b_1 =
934            newtButton(20 -
935                       ((button2[0] !=
936                         '\0') ? strlen(button1) +
937                        2 : strlen(button1) / 2),
938                       newtTextboxGetNumLines(text) + 3, button1);
939        if (button2[0] != '\0') {
940            b_2 =
941                newtButton(24, newtTextboxGetNumLines(text) + 3, button2);
942        } else {
943            b_2 = NULL;
944        }
945        //  newtOpenWindow (25, 5, 46, newtTextboxGetNumLines (text) + 7, "Alert");
946        newtCenteredWindow(46, newtTextboxGetNumLines(text) + 7, "Alert");
947        myForm = newtForm(NULL, NULL, 0);
948        newtFormAddComponents(myForm, text, b_1, b_2, NULL);
949        center_string(prompt, 80);
950        newtPushHelpLine(prompt);
951        b_res = newtRunForm(myForm);
952        newtPopHelpLine();
953        newtFormDestroy(myForm);
954        newtPopWindow();
955        if (b_res == b_1) {
956            paranoid_free(tmp);
957            paranoid_free(prompt);
958            return (TRUE);
959        } else {
960            paranoid_free(tmp);
961            paranoid_free(prompt);
962            return (FALSE);
963        }
964    }
965
966
967
968
969/**
970 * Synchronize the log messages stored in @p err_log_lines with those shown
971 * on the screen.
972 */
973    void
974     refresh_log_screen() {
975
976        /*@ int *********************************************************** */
977        int i = 0;
978
979
980        if (g_text_mode || !err_log_lines) {
981            return;
982        }
983        for (i = g_noof_log_lines - 1; i >= 0; i--) {
984            newtDrawRootText(0, i + g_noof_rows - 1 - g_noof_log_lines,
985                             "                                                                                ");
986        }
987        newtRefresh();
988        for (i = g_noof_log_lines - 1; i >= 0; i--) {
989            err_log_lines[i][79] = '\0';
990            newtDrawRootText(0, i + g_noof_rows - 1 - g_noof_log_lines,
991                             err_log_lines[i]);
992        }
993        newtRefresh();
994    }
995
996
997/**
998 * Set up the Newt graphical environment. If @p g_text_mode is TRUE, then
999 * only allocate some memory.
1000 */
1001    void
1002     setup_newt_stuff() {
1003
1004        /*@ int *********************************************************** */
1005        int i = 0;
1006        int cols;
1007
1008        if (!g_text_mode) {
1009            newtInit();
1010            newtCls();
1011            newtPushHelpLine
1012                ("Welcome to Mondo Rescue, by Dev Team and the Internet. All rights reversed.");
1013            /*  newtDrawRootText(28,0,"Welcome to Mondo Rescue"); */
1014            newtDrawRootText(18, 0, WELCOME_STRING);
1015            newtRefresh();
1016            newtGetScreenSize(&cols, &g_noof_rows);
1017            g_noof_log_lines = (g_noof_rows / 5) + 1;
1018        }
1019
1020        err_log_lines =
1021            (char **) malloc(sizeof(char *) * g_noof_log_lines);
1022        if (!err_log_lines) {
1023            fatal_error("Out of memory");
1024        }
1025
1026        for (i = 0; i < g_noof_log_lines; i++) {
1027            err_log_lines[i] = (char *) malloc(MAX_NEWT_COMMENT_LEN);
1028            if (!err_log_lines[i]) {
1029                fatal_error("Out of memory");
1030            }
1031        }
1032
1033        for (i = 0; i < g_noof_log_lines; i++) {
1034            err_log_lines[i][0] = '\0';
1035        }
1036    }
1037
1038
1039/**
1040 * Update the evalcall form to show (<tt>num</tt>/<tt>denom</tt>)*100 %.
1041 * @param num The numerator of the ratio.
1042 * @param denom The denomenator of the ratio.
1043 */
1044    void
1045     update_evalcall_form_ratio(int num, int denom) {
1046
1047        /*@ long ************************************************************ */
1048        long current_time = 0;
1049        long time_taken = 0;
1050        long time_total_est = 0;
1051        long time_remaining = 0;
1052
1053        /*@ buffers ********************************************************** */
1054        char *timeline_str;
1055        char *pcline_str;
1056        char *taskprogress;
1057
1058        /*@ int ************************************************************** */
1059        int percentage = 0;
1060        int i = 0;
1061        int j = 0;
1062
1063        malloc_string(timeline_str);
1064        malloc_string(pcline_str);
1065        malloc_string(taskprogress);
1066        timeline_str[0] = '\0';
1067//  log_it("update_eval_call_form called");
1068        if (num * 100 < denom) {
1069            percentage = 1;
1070        } else {
1071            percentage = (num * 100 + denom / 2) / denom;
1072        }
1073
1074        current_time = get_time();
1075        time_taken = current_time - g_isoform_starttime;
1076        if (num) {
1077            time_total_est = time_taken * denom / num;
1078            time_remaining = time_total_est - time_taken;
1079        } else {
1080            time_remaining = 0;
1081        }
1082        if (!g_text_mode) {
1083            newtLabelSetText(g_isoform_header, g_isoform_header_str);
1084        }
1085        g_mysterious_dot_counter = (g_mysterious_dot_counter + 1) % 27;
1086        if ((percentage < 3 && g_isoform_old_progress < 3)
1087            || percentage > g_isoform_old_progress) {
1088            g_isoform_old_progress = percentage;
1089            sprintf(timeline_str,
1090                    "%2ld:%02ld taken            %2ld:%02ld remaining",
1091                    time_taken / 60, time_taken % 60, time_remaining / 60,
1092                    time_remaining % 60);
1093            if (percentage < 3) {
1094                sprintf(pcline_str, " Working");
1095                for (j = 0; j < g_mysterious_dot_counter; j++) {
1096                    strcat(pcline_str, ".");
1097                }
1098                for (; j < 27; j++) {
1099                    strcat(pcline_str, " ");
1100                }
1101                sprintf(pcline_str + strlen(pcline_str), " %c",
1102                        special_dot_char(g_mysterious_dot_counter));
1103            } else {
1104                sprintf(pcline_str, " %3d%% done              %3d%% to go",
1105                        percentage, 100 - percentage);
1106            }
1107            if (g_text_mode) {
1108                sprintf(taskprogress, "TASK:  [");
1109                for (i = 0; i < percentage; i += 5) {
1110                    strcat(taskprogress, "*");
1111                }
1112                for (; i < 100; i += 5) {
1113                    strcat(taskprogress, ".");
1114                }
1115                if (percentage >= 3) {
1116                    sprintf(taskprogress + strlen(taskprogress),
1117                            "] %3d%% done; %2ld:%02ld to go", percentage,
1118                            time_remaining / 60, time_remaining % 60);
1119                    printf("---evalcall---1--- %s\r\n",
1120                           g_isoform_header_str);
1121                    printf("---evalcall---2--- %s\r\n", taskprogress);
1122                    printf("---evalcall---E---\r\n");
1123                }
1124            } else {
1125                newtScaleSet(g_isoform_scale,
1126                             (unsigned long long) percentage);
1127                newtLabelSetText(g_isoform_pcline, pcline_str);
1128                if (percentage >= 3) {
1129                    newtLabelSetText(g_isoform_timeline, timeline_str);
1130                }
1131            }
1132        }
1133        if (!g_text_mode) {
1134//      log_it("refreshing");
1135            newtRefresh();
1136        }
1137        paranoid_free(timeline_str);
1138        paranoid_free(pcline_str);
1139        paranoid_free(taskprogress);
1140    }
1141
1142
1143
1144/**
1145 * Update the evalcall form to show @p curr %.
1146 * @param curr The current amount of progress (percentage) in the evalcall form.
1147 */
1148    void
1149     update_evalcall_form(int curr) {
1150        update_evalcall_form_ratio(curr, 100);
1151    }
1152
1153
1154
1155/**
1156 * Update the progress form to show @p blurb3 and the current value of
1157 * @p g_maximum_progress.
1158 * @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.
1159 */
1160    void
1161     update_progress_form(char *blurb3) {
1162        /*  log_it("update_progress_form --- called"); */
1163        if (g_current_progress == -999) {
1164            /* 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."); */
1165            return;
1166        }
1167        strcpy(g_blurb_str_2, blurb3);
1168        update_progress_form_full(g_blurb_str_1, g_blurb_str_2,
1169                                  g_blurb_str_3);
1170    }
1171
1172
1173/**
1174 * Update the progress form's complete blurb and show @p g_current_progress.
1175 * @param blurb1 The first line of the blurb. Use @p g_blurb_str_1 to keep it unchanged.
1176 * @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.
1177 * @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.
1178 */
1179    void
1180     update_progress_form_full(char *blurb1, char *blurb2, char *blurb3) {
1181        /*@ long ***************************************************** */
1182        long current_time = 0;
1183        long time_taken = 0;
1184        long time_remaining = 0;
1185        long time_total_est = 0;
1186
1187        /*@ int ******************************************************* */
1188        int percentage = 0;
1189        int i = 0;
1190
1191        /*@ buffers *************************************************** */
1192        char *percentline_str;
1193        char *timeline_str;
1194        char *taskprogress;
1195        char *tmp;
1196
1197//  log_msg(1, "'%s' '%s' '%s'", blurb1, blurb2, blurb3);
1198        percentline_str = malloc(MAX_NEWT_COMMENT_LEN);
1199        timeline_str = malloc(MAX_NEWT_COMMENT_LEN);
1200        taskprogress = malloc(MAX_NEWT_COMMENT_LEN);
1201        malloc_string(tmp);
1202        if (!g_text_mode) {
1203            assert(blurb1 != NULL);
1204            assert(blurb2 != NULL);
1205            assert(blurb3 != NULL);
1206            assert(g_timeline != NULL);
1207        }
1208
1209        percentline_str[0] = '\0';
1210
1211        current_time = get_time();
1212        time_taken = current_time - g_start_time;
1213        if (g_maximum_progress == 0) {
1214            percentage = 0;
1215        } else {
1216            if (g_current_progress > g_maximum_progress) {
1217                sprintf(tmp,
1218                        "update_progress_form_full(%s,%s,%s) --- g_current_progress=%ld; g_maximum_progress=%ld",
1219                        blurb1, blurb2, blurb3, g_current_progress,
1220                        g_maximum_progress);
1221                log_msg(0, tmp);
1222                g_current_progress = g_maximum_progress;
1223            }
1224            percentage =
1225                (int) ((g_current_progress * 100L) / g_maximum_progress);
1226        }
1227        if (percentage < 1) {
1228            percentage = 1;
1229        }
1230        if (percentage > 100) {
1231            percentage = 100;
1232        }
1233        if (g_current_progress) {
1234            time_total_est =
1235                time_taken * (long) g_maximum_progress /
1236                (long) (g_current_progress);
1237            time_remaining = time_total_est - time_taken;
1238        } else {
1239            time_remaining = 0;
1240        }
1241        g_mysterious_dot_counter = (g_mysterious_dot_counter + 1) % 27;
1242        sprintf(timeline_str,
1243                "%2ld:%02ld taken               %2ld:%02ld remaining  ",
1244                time_taken / 60, time_taken % 60, time_remaining / 60,
1245                time_remaining % 60);
1246        sprintf(percentline_str, " %3d%% done                 %3d%% to go",
1247                percentage, 100 - percentage);
1248
1249        if (g_text_mode) {
1250            printf("---progress-form---1--- %s\r\n", blurb1);
1251            printf("---progress-form---2--- %s\r\n", blurb2);
1252            printf("---progress-form---3--- %s\r\n", blurb3);
1253            printf("---progress-form---E---\n");
1254            sprintf(taskprogress, "TASK:  [");
1255            for (i = 0; i < percentage; i += 5) {
1256                strcat(taskprogress, "*");
1257            }
1258            for (; i < 100; i += 5) {
1259                strcat(taskprogress, ".");
1260            }
1261            if (percentage > 100) {
1262                log_msg(2, "percentage = %d", percentage);
1263            }
1264            sprintf(taskprogress + strlen(taskprogress),
1265                    "] %3d%c", percentage, '%');
1266            sprintf(taskprogress + strlen(taskprogress),
1267                    " done; %2ld:%02ld to go",
1268                    time_remaining / 60, time_remaining % 60);
1269            printf("---progress-form---4--- %s\r\n", taskprogress);
1270        } else {
1271            center_string(blurb1, 54);
1272            center_string(blurb2, 54);
1273            center_string(blurb3, 54);
1274            newtLabelSetText(g_blurb1, blurb1);
1275            newtLabelSetText(g_blurb2, blurb3);
1276            newtLabelSetText(g_blurb3, blurb2);
1277            newtScaleSet(g_scale, (unsigned long long) g_current_progress);
1278            if (percentage >= 2) {
1279                newtLabelSetText(g_timeline, timeline_str);
1280            }
1281            newtLabelSetText(g_percentline, percentline_str);
1282            newtRefresh();
1283        }
1284        paranoid_free(percentline_str);
1285        paranoid_free(timeline_str);
1286        paranoid_free(taskprogress);
1287        paranoid_free(tmp);
1288    }
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303/**
1304 * Ask the user which backup media type they would like to use.
1305 * The choices are @p none (exit to shell), @c cdr, @c cdrw, @c dvd,
1306 * @c tape, @c cdstream, @c udev (only when @p g_text_mode is TRUE), @c nfs,
1307 * and @c iso.
1308 * @param restoring TRUE if we're restoring, FALSE if we're backing up.
1309 * @return The backup type chosen, or @c none if the user chose "Exit to shell".
1310 */
1311    t_bkptype which_backup_media_type(bool restoring) {
1312
1313        /*@ char ************************************************************ */
1314        t_bkptype output;
1315
1316
1317        /*@ newt ************************************************************ */
1318        char *title_sz;
1319        char *minimsg_sz;
1320        static t_bkptype possible_bkptypes[] =
1321            { none, cdr, cdrw, dvd, tape, cdstream, udev, nfs, iso };
1322        static char *possible_responses[] =
1323            { "none", "cdr", "cdrw", "dvd", "tape", "cdstream", "udev",
1324"nfs", "iso", NULL };
1325        char *outstr;
1326        t_bkptype backup_type;
1327        int i;
1328
1329        newtComponent b1;
1330        newtComponent b2;
1331        newtComponent b3;
1332        newtComponent b4;
1333        newtComponent b5;
1334        newtComponent b6;
1335        newtComponent b7;
1336        newtComponent b8;
1337        newtComponent b_res;
1338        newtComponent myForm;
1339
1340        title_sz = malloc(MAX_NEWT_COMMENT_LEN);
1341        minimsg_sz = malloc(MAX_NEWT_COMMENT_LEN);
1342        outstr = malloc(MAX_NEWT_COMMENT_LEN);
1343        if (g_text_mode) {
1344            for (backup_type = none; backup_type == none;) {
1345                printf("Backup type (");
1346                for (i = 0; possible_responses[i]; i++) {
1347                    printf("%c%s", (i == 0) ? '\0' : ' ',
1348                           possible_responses[i]);
1349                }
1350                printf(")\n--> ");
1351                (void) fgets(outstr, MAX_NEWT_COMMENT_LEN, stdin);
1352                strip_spaces(outstr);
1353                for (i = 0; possible_responses[i]; i++) {
1354                    if (!strcmp(possible_responses[i], outstr)) {
1355                        backup_type = possible_bkptypes[i];
1356                    }
1357                }
1358            }
1359            paranoid_free(title_sz);
1360            paranoid_free(minimsg_sz);
1361            paranoid_free(outstr);
1362            return (backup_type);
1363        }
1364        newtDrawRootText(18, 0, WELCOME_STRING);
1365        if (restoring) {
1366            strcpy(title_sz,
1367                   "Please choose the backup media from which you want to read data.");
1368            strcpy(minimsg_sz, "Read from:");
1369        } else {
1370            strcpy(title_sz,
1371                   "Please choose the backup media to which you want to archive data.");
1372            strcpy(minimsg_sz, "Backup to:");
1373        }
1374        newtPushHelpLine(title_sz);
1375        //  newtOpenWindow (23, 3, 34, 17, minimsg_sz);
1376        newtCenteredWindow(34, 17, minimsg_sz);
1377        b1 = newtButton(1, 1, "CD-R disks ");
1378        b2 = newtButton(17, 1, "CD-RW disks");
1379        b3 = newtButton(1, 9, "Tape drive ");
1380        b4 = newtButton(17, 5, "CD streamer");
1381        b5 = newtButton(1, 5, " DVD disks ");
1382        b6 = newtButton(17, 9, " NFS mount ");
1383        b7 = newtButton(1, 13, " Hard disk ");
1384        b8 = newtButton(17, 13, "    Exit   ");
1385        myForm = newtForm(NULL, NULL, 0);
1386        newtFormAddComponents(myForm, b1, b5, b3, b7, b2, b4, b6, b8,
1387                              NULL);
1388        b_res = newtRunForm(myForm);
1389        newtFormDestroy(myForm);
1390        newtPopWindow();
1391        if (b_res == b1) {
1392            output = cdr;
1393        } else if (b_res == b2) {
1394            output = cdrw;
1395        } else if (b_res == b3) {
1396            output = tape;
1397        } else if (b_res == b4) {
1398            output = cdstream;
1399        } else if (b_res == b5) {
1400            output = dvd;
1401        } else if (b_res == b6) {
1402            output = nfs;
1403        } else if (b_res == b7) {
1404            output = iso;
1405        } else {
1406            output = none;
1407        }
1408        newtPopHelpLine();
1409        paranoid_free(title_sz);
1410        paranoid_free(minimsg_sz);
1411        paranoid_free(outstr);
1412        return (output);
1413    }
1414
1415
1416
1417
1418/**
1419 * Ask the user how much compression they would like to use.
1420 * The choices are "None" (0), "Minimum" (1), "Average" (4), and "Maximum" (9).
1421 * @return The compression level (0-9) chosen, or -1 for "Exit".
1422 */
1423    int
1424     which_compression_level() {
1425
1426        /*@ char ************************************************************ */
1427        int output = none;
1428
1429
1430        /*@ newt ************************************************************ */
1431
1432        newtComponent b1;
1433        newtComponent b2;
1434        newtComponent b3;
1435        newtComponent b4;
1436        newtComponent b5;
1437        newtComponent b_res;
1438        newtComponent myForm;
1439
1440        newtDrawRootText(18, 0, WELCOME_STRING);
1441        newtPushHelpLine
1442            ("   Please specify the level of compression that you want.");
1443        //  newtOpenWindow (23, 3, 34, 13, "How much compression?");
1444        newtCenteredWindow(34, 13, "How much compression?");
1445        b1 = newtButton(4, 1, "Maximum");
1446        b2 = newtButton(18, 1, "Average");
1447        b3 = newtButton(4, 5, "Minumum");
1448        b4 = newtButton(18, 5, " None  ");
1449        b5 = newtButton(4, 9, "         Exit        ");
1450        myForm = newtForm(NULL, NULL, 0);
1451        newtFormAddComponents(myForm, b1, b3, b2, b4, b5, NULL);
1452        b_res = newtRunForm(myForm);
1453        newtFormDestroy(myForm);
1454        newtPopWindow();
1455        if (b_res == b1) {
1456            output = 9;
1457        } else if (b_res == b2) {
1458            output = 4;
1459        } else if (b_res == b3) {
1460            output = 1;
1461        } else if (b_res == b4) {
1462            output = 0;
1463        } else if (b_res == b5) {
1464            output = -1;
1465        }
1466        newtPopHelpLine();
1467        return (output);
1468    }
1469
1470
1471
1472
1473
1474/**
1475 * Load @p source_file (a list of files) into @p filelist. There can be no more than
1476 * @p ARBITRARY_MAXIMUM entries.
1477 * @param filelist The filelist structure to load @p source_file into.
1478 * @param source_file The file containing a list of filenames to load into @p filelist.
1479 */
1480    int load_filelist_into_array(struct s_filelist *filelist,
1481                                 char *source_file) {
1482        int i;
1483        bool done;
1484        char *tmp;
1485        FILE *fin;
1486        struct s_filelist_entry dummy_fle;
1487
1488        malloc_string(tmp);
1489        assert(filelist != NULL);
1490        assert_string_is_neither_NULL_nor_zerolength(source_file);
1491
1492        iamhere("entering");
1493        if (!(fin = fopen(source_file, "r"))) {
1494            log_OS_error(source_file);
1495            log_msg(2, "Can't open %s; therefore, cannot popup list",
1496                    source_file);
1497            paranoid_free(tmp);
1498            return (1);
1499        }
1500        log_msg(2, "Loading %s", source_file);
1501        for (filelist->entries = 0; filelist->entries <= ARBITRARY_MAXIMUM;
1502             filelist->entries++) {
1503          god_i_hate_gotos:
1504            if (feof(fin)) {
1505                break;
1506            }
1507            (void) fgets(tmp, MAX_NEWT_COMMENT_LEN, fin);
1508            i = (int) strlen(tmp);
1509            if (i < 2) {
1510                goto god_i_hate_gotos;
1511            }
1512            if (tmp[i - 1] < 32) {
1513                tmp[--i] = '\0';
1514            }
1515            if (i < 2) {
1516                goto god_i_hate_gotos;
1517            }
1518            if (!does_file_exist(tmp)) {
1519                goto god_i_hate_gotos;
1520            }
1521            filelist->el[filelist->entries].severity =
1522                severity_of_difference(tmp, NULL);
1523            strcpy(filelist->el[filelist->entries].filename, tmp);
1524            if (feof(fin)) {
1525                break;
1526            }
1527        }
1528        paranoid_fclose(fin);
1529        if (filelist->entries >= ARBITRARY_MAXIMUM) {
1530            log_to_screen("Arbitrary limits suck, man!");
1531            paranoid_free(tmp);
1532            return (1);
1533        }
1534        for (done = FALSE; !done;) {
1535            done = TRUE;
1536            for (i = 0; i < filelist->entries - 1; i++) {
1537//          if (strcmp(filelist->el[i].filename, filelist->el[i+1].filename) > 0)
1538                if (filelist->el[i].severity < filelist->el[i + 1].severity
1539                    || (filelist->el[i].severity ==
1540                        filelist->el[i + 1].severity
1541                        && strcmp(filelist->el[i].filename,
1542                                  filelist->el[i + 1].filename) > 0)) {
1543                    memcpy((void *) &dummy_fle,
1544                           (void *) &(filelist->el[i]),
1545                           sizeof(struct s_filelist_entry));
1546                    memcpy((void *) &(filelist->el[i]),
1547                           (void *) &(filelist->el[i + 1]),
1548                           sizeof(struct s_filelist_entry));
1549                    memcpy((void *) &(filelist->el[i + 1]),
1550                           (void *) &dummy_fle,
1551                           sizeof(struct s_filelist_entry));
1552                    log_msg(2, "Swapping %s and %s",
1553                            filelist->el[i].filename,
1554                            filelist->el[i + 1].filename);
1555                    done = FALSE;
1556                }
1557            }
1558        }
1559        paranoid_free(tmp);
1560        iamhere("leaving");
1561        return (0);
1562    }
1563
1564
1565
1566/**
1567 * Generate a pretty string based on @p flentry.
1568 * @param flentry The filelist entry to stringify.
1569 * @return The string form of @p flentry.
1570 * @note The returned value points to static storage that will be overwritten with each call.
1571 */
1572    char *filelist_entry_to_string(struct s_filelist_entry *flentry) {
1573        static char comment[100];
1574        char *tmp;
1575
1576        iamhere("entering");
1577        malloc_string(tmp);
1578        assert(flentry != NULL);
1579        if (flentry->severity == 0) {
1580            strcpy(tmp, "0   ");
1581        } else if (flentry->severity == 1) {
1582            strcpy(tmp, "low ");
1583        } else if (flentry->severity == 2) {
1584            strcpy(tmp, "med ");
1585        } else {
1586            strcpy(tmp, "high");
1587        }
1588        strcat(tmp, "  ");
1589        strncat(tmp, flentry->filename, 100);
1590        tmp[98] = '\0';
1591        strcpy(comment, tmp);
1592        paranoid_free(tmp);
1593        iamhere("leaving");
1594        return (comment);
1595    }
1596
1597
1598
1599
1600
1601/**
1602 * Pop up a list containing the filenames in @p source_file and the severity if they have changed since the
1603 * last backup. There can be no more than @p ARBITRARY_MAXIMUM files in @p source_file.
1604 * @param source_file The file containing a list of changed files.
1605 */
1606    void popup_changelist_from_file(char *source_file) {
1607        char *reason;
1608        newtComponent myForm;
1609        newtComponent bClose;
1610        newtComponent bSelect;
1611        newtComponent b_res;
1612        newtComponent fileListbox;
1613        newtComponent headerMsg;
1614
1615        /*@ ???? ************************************************************ */
1616        void *curr_choice;
1617        void *keylist[ARBITRARY_MAXIMUM];
1618
1619        /*@ int ************************************************************* */
1620        int currline = 0;
1621        int finished = FALSE;
1622
1623        /*@ long ************************************************************ */
1624        long i = 0;
1625        long lng = 0;
1626
1627        /*@ buffers ********************************************************* */
1628        char *tmp;
1629        char *differ_sz;
1630
1631        struct s_filelist *filelist;
1632        malloc_string(reason);
1633        tmp = malloc(5000);
1634        malloc_string(differ_sz);
1635        assert_string_is_neither_NULL_nor_zerolength(source_file);
1636        if (g_text_mode) {
1637            log_msg(2, "Text mode. Therefore, no popup list.");
1638            goto free_to_go;
1639        }
1640        log_msg(2, "Examining file %s", source_file);
1641
1642        lng = count_lines_in_file(source_file);
1643        if (lng < 1) {
1644            log_msg(2, "No lines in file. Therefore, no popup list.");
1645            paranoid_free(reason);
1646            goto free_to_go;
1647        } else if (lng >= ARBITRARY_MAXIMUM) {
1648            log_msg(2, "Too many files differ for me to list.");
1649            goto free_to_go;
1650        }
1651
1652        filelist = (struct s_filelist *) malloc(sizeof(struct s_filelist));
1653        fileListbox =
1654            newtListbox(2, 2, 12, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
1655        newtListboxClear(fileListbox);
1656
1657        if (load_filelist_into_array(filelist, source_file)) {
1658            log_msg(2, "Can't open %s; therefore, cannot popup list",
1659                    source_file);
1660            paranoid_free(reason);
1661            return;
1662        }
1663        log_msg(2, "%d files loaded into filelist array",
1664                filelist->entries);
1665        for (i = 0; i < filelist->entries; i++) {
1666            keylist[i] = (void *) i;
1667            newtListboxAppendEntry(fileListbox,
1668                                   filelist_entry_to_string(&
1669                                                            (filelist->
1670                                                             el[i])),
1671                                   keylist[i]);
1672        }
1673        sprintf(differ_sz,
1674                "  %ld files differ. Hit 'Select' to pick a file. Hit 'Close' to quit the list.",
1675                i);
1676        newtPushHelpLine(differ_sz);
1677        bClose = newtCompactButton(10, 15, " Close  ");
1678        bSelect = newtCompactButton(30, 15, " Select ");
1679        sprintf(tmp, "%-10s               %-20s", "Priority", "Filename");
1680        headerMsg = newtLabel(2, 1, tmp);
1681        newtOpenWindow(5, 4, 70, 16, "Non-matching files");
1682        myForm = newtForm(NULL, NULL, 0);
1683        newtFormAddComponents(myForm, headerMsg, fileListbox, bClose,
1684                              bSelect, NULL);
1685        while (!finished) {
1686            b_res = newtRunForm(myForm);
1687            if (b_res == bClose) {
1688                finished = TRUE;
1689            } else {
1690                curr_choice = newtListboxGetCurrent(fileListbox);
1691                for (i = 0;
1692                     i < filelist->entries && keylist[i] != curr_choice;
1693                     i++);
1694                if (i == filelist->entries && filelist->entries > 0) {
1695                    log_to_screen("I don't know what that button does!");
1696                } else {
1697                    currline = i;
1698                    if (filelist->entries > 0) {
1699                        severity_of_difference(filelist->el[currline].
1700                                               filename, reason);
1701                        sprintf(tmp, "%s --- %s",
1702                                filelist->el[currline].filename, reason);
1703                        popup_and_OK(tmp);
1704                    }
1705                }
1706            }
1707        }
1708        newtFormDestroy(myForm);
1709        newtPopWindow();
1710        newtPopHelpLine();
1711      free_to_go:
1712        paranoid_free(reason);
1713        paranoid_free(tmp);
1714        paranoid_free(differ_sz);
1715        return;
1716    }
1717
1718/* @} - end of guiGroup */
1719
1720
1721#if __cplusplus
1722}                               /* extern "C" */
1723#endif
1724
1725
1726void wait_until_software_raids_are_prepped(char *mdstat_file,
1727                                           int wait_for_percentage);
Note: See TracBrowser for help on using the repository browser.