source: branches/2.04_berlios/mondo/mondo/common/newt-specific.c @ 99

Last change on this file since 99 was 99, checked in by bcornec, 14 years ago

Apply patch from Andree Leidenfrost <aleidenf_AT_bigpond.net.au>
(-r72:75 of trunk) for :
+ correcting NFS handling in interactive mode
+ growisofs and sudo pb

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