source: MondoRescue/branches/stable/mondo/src/mondoarchive/mondo-cli.c@ 1164

Last change on this file since 1164 was 1164, checked in by Bruno Cornec, 17 years ago

Compiler warning solved (M. Loiseleur again !)
Code displaced to ease memeory management in case of exit in libmondo-archive.c

  • Property svn:keywords set to Id
File size: 28.2 KB
Line 
1/***************************************************************************
2$Id: mondo-cli.c 1164 2007-02-14 20:35:00Z bruno $
3*******************************************************************/
4
5/**
6 * @file
7 * Functions for handling command-line arguments passed to mondoarchive.
8 */
9
10/** @def BOOT_LOADER_CHARS The characters allowed for boot loader on this platform. */
11
12#include <pthread.h>
13#include "my-stuff.h"
14#include "../common/mondostructures.h"
15#include "mondo-cli-EXT.h"
16#include "../common/libmondo.h"
17#include "mr_mem.h"
18#include "mr_msg.h"
19
20//static char cvsid[] = "$Id: mondo-cli.c 1164 2007-02-14 20:35:00Z bruno $";
21
22extern int g_loglevel;
23extern bool g_text_mode;
24extern bool g_skip_floppies; ///< Whether to skip the creation of boot disks
25extern char g_startdir[MAX_STR_LEN]; ///< ????? @bug ?????
26extern char g_erase_tmpdir_and_scratchdir[MAX_STR_LEN];
27extern char g_tmpfs_mountpt[MAX_STR_LEN];
28extern bool g_sigpipe;
29
30/*@ file pointer **************************************************/
31extern FILE *g_tape_stream;
32
33/*@ long long *****************************************************/
34extern long long g_tape_posK;
35
36/*@ long **********************************************************/
37extern long g_noof_sets;
38
39/*@ bool******** **************************************************/
40bool g_debugging = FALSE; ///< ????? @bug ????? @ingroup globalGroup
41bool g_running_live = FALSE; ///< ????? @bug ????? @ingroup globalGroup
42extern bool g_cd_recovery;
43
44/**
45 * Whether we're restoring from ISOs. Obviously not, since this is the
46 * backup program.
47 * @note You @b MUST declare this variable somewhere in your program if
48 * you use libmondo. Otherwise the link will fail.
49 * @ingroup globalGroup
50 */
51bool g_ISO_restore_mode = FALSE;
52
53
54extern double g_kernel_version;
55extern int g_current_media_number;
56extern pid_t g_main_pid;
57extern char *resolve_softlinks_to_get_to_actual_device_file(char *);
58
59/* Do we use extended attributes and acl ?
60 * By default no, use --acl & --attr options to force their usage */
61char *g_getfacl = NULL;
62char *g_getfattr = NULL;
63
64/**
65 * @addtogroup cliGroup
66 * @{
67 */
68/**
69 * Populate @p bkpinfo from the command-line parameters stored in @p argc and @p argv.
70 * @param argc The argument count, including the program name; @p argc passed to main().
71 * @param argv The argument vector; @p argv passed to main().
72 * @param bkpinfo The backup information structure to populate.
73 * @return The number of problems with the command line (0 for success).
74 */
75int
76handle_incoming_parameters(int argc, char *argv[],
77 struct s_bkpinfo *bkpinfo)
78{
79 /*@ int *** */
80 int res = 0;
81 int retval = 0;
82 int i = 0, j;
83
84 /*@ buffers *************** */
85 char *tmp;
86 char flag_val[128][MAX_STR_LEN];
87 bool flag_set[128];
88
89 malloc_string(tmp);
90 sensibly_set_tmpdir_and_scratchdir(bkpinfo);
91 for (i = 0; i < 128; i++) {
92 flag_val[i][0] = '\0';
93 flag_set[i] = FALSE;
94 }
95 // strcpy (bkpinfo->tmpdir, "/root/images/mondo");
96 // strcpy (bkpinfo->scratchdir, "/home");
97 for (j = 1; j <= MAX_NOOF_MEDIA; j++) {
98 bkpinfo->media_size[j] = 650;
99 } /* default */
100 res =
101 retrieve_switches_from_command_line(argc, argv, flag_val,
102 flag_set);
103 retval += res;
104 if (!retval) {
105 res = process_switches(bkpinfo, flag_val, flag_set);
106 retval += res;
107 }
108/*
109 if (!retval)
110 {
111*/
112 mr_msg(3, "Switches:-");
113 for (i = 0; i < 128; i++) {
114 if (flag_set[i]) {
115 sprintf(tmp, "-%c %s", i, flag_val[i]);
116 mr_msg(3, tmp);
117 }
118 }
119// }
120 sprintf(tmp, "rm -Rf %s/tmp.mondo.*", bkpinfo->tmpdir);
121 paranoid_system(tmp);
122 sprintf(tmp, "rm -Rf %s/mondo.scratch.*", bkpinfo->scratchdir);
123 paranoid_system(tmp);
124 sprintf(bkpinfo->tmpdir + strlen(bkpinfo->tmpdir), "/tmp.mondo.%ld",
125 random() % 32767);
126 sprintf(bkpinfo->scratchdir + strlen(bkpinfo->scratchdir),
127 "/mondo.scratch.%ld", random() % 32767);
128 sprintf(tmp, "mkdir -p %s/tmpfs", bkpinfo->tmpdir);
129 paranoid_system(tmp);
130 sprintf(tmp, "mkdir -p %s", bkpinfo->scratchdir);
131 paranoid_system(tmp);
132 mr_free(tmp);
133 return (retval);
134}
135
136
137
138
139/**
140 * Store the sizespec(s) stored in @p value into @p bkpinfo.
141 * @param bkpinfo The backup information structure; the @c bkpinfo->media_size field will be populated.
142 * @param value The sizespec (e.g. "2g", "40m").
143 * @return 0, always.
144 * @bug Return code not needed.
145 */
146int process_the_s_switch(struct s_bkpinfo *bkpinfo, char *value)
147{
148 int j;
149 char tmp[MAX_STR_LEN], *p, comment[MAX_STR_LEN];
150
151 assert(bkpinfo != NULL);
152 assert(value != NULL);
153
154 bkpinfo->media_size[0] = -1; /* dummy value */
155 for (j = 1, p = value; j < MAX_NOOF_MEDIA && strchr(p, ',');
156 j++, p = strchr(p, ',') + 1) {
157 strncpy(tmp, p, MAX_STR_LEN);
158 *(strchr(tmp, ',')) = '\0';
159 bkpinfo->media_size[j] = friendly_sizestr_to_sizelong(tmp);
160 sprintf(comment, "media_size[%d] = %ld", j,
161 bkpinfo->media_size[j]);
162 mr_msg(3, comment);
163 }
164 for (; j <= MAX_NOOF_MEDIA; j++) {
165 bkpinfo->media_size[j] = friendly_sizestr_to_sizelong(p);
166 }
167// bkpinfo->media_size[0] = bkpinfo->media_size[MAX_NOOF_MEDIA];
168 for (j = 1; j <= MAX_NOOF_MEDIA; j++) {
169 if (bkpinfo->media_size[j] <= 0) {
170 mr_msg(1, "You gave media #%d an invalid size\n", j);
171 return (-1);
172 }
173 }
174 return (0);
175}
176
177
178
179/**
180 * Process mondoarchive's command-line switches.
181 * @param bkpinfo The backup information structure to populate.
182 * @param flag_val An array of the argument passed to each switch (the letter is the index).
183 * If a switch is not set or has no argument, the field in @p flag_val doesn't matter.
184 * @param flag_set An array of <tt>bool</tt>s indexed by switch letter: TRUE if it's set,
185 * FALSE if it's not.
186 * @return The number of problems with the switches, or 0 for success.
187 * @bug Maybe include a list of all switches (inc. intentionally undocumented ones not in the manual!) here?
188 */
189int
190process_switches(struct s_bkpinfo *bkpinfo,
191 char flag_val[128][MAX_STR_LEN], bool flag_set[128])
192{
193
194 /*@ ints *** */
195 int i = 0;
196 int retval = 0;
197 int percent = 0;
198
199 /*@ buffers ** */
200 char *tmp;
201 char *tmp1;
202 char *psz;
203 char *p;
204 char *q;
205
206 long itbs = 0L;
207
208 struct stat buf;
209
210 malloc_string(tmp);
211 malloc_string(psz);
212
213 assert(bkpinfo != NULL);
214 assert(flag_val != NULL);
215 assert(flag_set != NULL);
216
217 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
218
219/* compulsory */
220 i = flag_set['c'] + flag_set['i'] + flag_set['n'] +
221 flag_set['t'] + flag_set['u'] + flag_set['r'] +
222 flag_set['w'] + flag_set['C'] + flag_set['U'];
223 if (i == 0) {
224 retval++;
225 log_to_screen("You must specify the media type\n");
226 }
227 if (i > 1) {
228 retval++;
229 log_to_screen("Please specify only one media type\n");
230 }
231 if (flag_set['K']) {
232 g_loglevel = atoi(flag_val['K']);
233 if (g_loglevel < 3) {
234 g_loglevel = 3;
235 }
236 }
237 if (flag_set['L'] && flag_set['0']) {
238 retval++;
239 log_to_screen("You cannot have 'no compression' _and_ LZOP.\n");
240 }
241 bkpinfo->backup_data = flag_set['O'];
242 bkpinfo->verify_data = flag_set['V'];
243 if (flag_set['I'] && !bkpinfo->backup_data) {
244 log_to_screen("-I switch is ignored if just verifying");
245 }
246 if (flag_set['E'] && !bkpinfo->backup_data) {
247 log_to_screen("-E switch is ignored if just verifying");
248 }
249
250 if (!find_home_of_exe("afio")) {
251 if (find_home_of_exe("star")) {
252 flag_set['R'] = TRUE;
253 mr_msg(1, "Using star instead of afio");
254 } else {
255 fatal_error
256 ("Neither afio nor star is installed. Please install at least one.");
257 }
258 }
259
260 if (flag_set['R']) {
261 bkpinfo->use_star = TRUE;
262 if (flag_set['L']) {
263 fatal_error("You may not use star and lzop at the same time.");
264 }
265 if (!find_home_of_exe("star")) {
266 fatal_error
267 ("Please install 'star' RPM or tarball if you are going to use -R. Thanks.");
268 }
269 }
270 if (flag_set['W']) {
271 bkpinfo->nonbootable_backup = TRUE;
272 log_to_screen("Warning - you have opted for non-bootable backup");
273 if (flag_set['f'] || flag_set['l']) {
274 log_to_screen
275 ("You don't need to specify bootloader or bootdevice");
276 }
277 }
278 if (flag_set['t'] && flag_set['H']) {
279 fatal_error
280 ("Sorry, you may not nuke w/o warning from tape. Drop -H, please.");
281 }
282 if (flag_set['I']) {
283 if (!strcmp(bkpinfo->include_paths, "/")) {
284 mr_msg(2, "'/' is pleonastic.");
285 bkpinfo->include_paths[0] = '\0';
286 }
287 if (bkpinfo->include_paths[0]) {
288 strcat(bkpinfo->include_paths, " ");
289 }
290 mr_asprintf(&tmp1, flag_val['I']);
291 p = tmp1;
292 q = tmp1;
293
294 /* Cut the flag_val['I'] in parts containing all paths to test them */
295 while (p != NULL) {
296 q = strchr(p, ' ');
297 if (q != NULL) {
298 *q = '\0';
299 if (stat(p, &buf) != 0) {
300 mr_msg(1, "ERROR ! %s doesn't exist", p);
301 fatal_error("ERROR ! You specified a directory to include which doesn't exist");
302 }
303 p = q+1 ;
304 } else {
305 if (stat(p, &buf) != 0) {
306 mr_msg(1, "ERROR ! %s doesn't exist", p);
307 fatal_error("ERROR ! You specified a directory to include which doesn't exist");
308 }
309 p = NULL;
310 }
311 }
312 mr_free(tmp1);
313
314 strncpy(bkpinfo->include_paths + strlen(bkpinfo->include_paths),
315 flag_val['I'],
316 4*MAX_STR_LEN - strlen(bkpinfo->include_paths));
317 mr_msg(1, "include_paths is now '%s'", bkpinfo->include_paths);
318 if (bkpinfo->include_paths[0] == '-') {
319 retval++;
320 log_to_screen("Please supply a sensible value with '-I'\n");
321 }
322 }
323
324 if (g_kernel_version >= 2.6 && !flag_set['d']
325 && (flag_set['c'] || flag_set['w'])) {
326 fatal_error
327 ("If you are using the 2.6.x kernel, please specify the CD-R(W) device.");
328 }
329
330
331 if (flag_set['J']) {
332 if (flag_set['I']) {
333 retval++;
334 log_to_screen
335 ("Please do not use -J in combination with -I. If you want to make a list of files to backup, that's fine, use -J <filename> but please don't muddy the waters by combining -J with -I. Thanks. :-)");
336 }
337 bkpinfo->make_filelist = FALSE;
338 strcpy(bkpinfo->include_paths, flag_val['J']);
339 }
340 if (flag_set['c'] || flag_set['w'] || flag_set['C'] || flag_set['r']) {
341 if (!flag_set['r'] && g_kernel_version <= 2.5
342 && strstr(flag_val['d'], "/dev/")) {
343 fatal_error
344 ("Please don't give a /dev entry. Give a SCSI node for the parameter of the -d flag.");
345 }
346 if (flag_set['r'] && g_kernel_version <= 2.5
347 && !strstr(flag_val['d'], "/dev/")) {
348 fatal_error
349 ("Please give a /dev entry, not a SCSI node, as the parameter of the -d flag.");
350 }
351 if (g_kernel_version >= 2.6 && !strstr(flag_val['d'], "/dev/")) {
352 log_to_screen
353 ("Linus says 2.6 has a broken ide-scsi module. Proceed at your own risk...");
354 }
355
356 if (system("which cdrecord > /dev/null 2> /dev/null")
357 && system("which dvdrecord > /dev/null 2> /dev/null")) {
358 fatal_error
359 ("Please install dvdrecord/cdrecord and try again.");
360 }
361 if (flag_set['C']) {
362 bkpinfo->cdrw_speed = atoi(flag_val['C']);
363 if (bkpinfo->cdrw_speed < 1) {
364 fatal_error
365 ("You specified a silly speed for a CD-R[W] drive");
366 }
367 if (!flag_set['L']) {
368 log_to_screen
369 ("You must use -L with -C. Therefore I am setting it for you.");
370 flag_set['L'] = 1;
371 flag_val['L'][0] = '\0';
372 }
373 } else {
374 mr_msg(3, "flag_val['c'] = %s", flag_val['c']);
375 mr_msg(3, "flag_val['w'] = %s", flag_val['w']);
376// mr_msg(3, "flag_set['r'] = %i", flag_set['r'] );
377 if (flag_set['c']) {
378 bkpinfo->cdrw_speed = atoi(flag_val['c']);
379 } else if (flag_set['w']) {
380 bkpinfo->cdrw_speed = atoi(flag_val['w']);
381 } else if (flag_set['r']) {
382 bkpinfo->cdrw_speed = 1; /*atoi(flag_val['r']); */
383 }
384
385 if (bkpinfo->cdrw_speed < 1) {
386 fatal_error
387 ("You specified a silly speed for a CD-R[W] drive");
388 }
389 }
390 }
391 if (flag_set['t'] && !flag_set['d']) {
392 log_it("Hmm! No tape drive specified. Let's see what we can do.");
393 if (find_tape_device_and_size(flag_val['d'], tmp)) {
394 fatal_error
395 ("Tape device not specified. I couldn't find it either.");
396 }
397 flag_set['d'] = TRUE;
398 sprintf(tmp,
399 "You didn't specify a tape streamer device. I'm assuming %s",
400 flag_val['d']);
401 log_to_screen(tmp);
402 percent = 0;
403 }
404
405 if (flag_set['U']) // USB
406 {
407 if (! flag_set['d']) {
408 fatal_error
409 ("You need to specify a device file with -d for bootable USB device creation");
410 }
411 if (!flag_set['s']) {
412 fatal_error("You did not specify a size (-s) for your USB device. Aborting");
413 }
414 }
415
416 if (flag_set['r']) // DVD
417 {
418 if (flag_set['m']) {
419 fatal_error
420 ("Manual CD tray (-m) not yet supported in conjunction w/ DVD drives. Drop -m.");
421 }
422 if (!flag_set['d']) {
423 if (!find_dvd_device(flag_val['d'], FALSE)) {
424 flag_set['d'] = TRUE;
425 log_to_screen("I guess DVD drive is at %s", flag_val['d']);
426 }
427 }
428 if (!find_home_of_exe("growisofs")) {
429 fatal_error
430 ("Please install growisofs (probably part of dvd+rw-tools). If you want DVD support, you need it.");
431 }
432 if (!find_home_of_exe("dvd+rw-format")) {
433 fatal_error
434 ("Please install dvd+rw-format (probably part of dvd+rw-tools). If you want DVD support, you need it.");
435 }
436 if (strchr(flag_val['d'], ',')) {
437 fatal_error
438 ("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
439 }
440 if (!flag_set['s']) {
441 sprintf(flag_val['s'], "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4582 MB
442 strcat(flag_val['s'], "m");
443 log_to_screen
444 ("You did not specify a size (-s) for DVD. I'm guessing %s.",
445 flag_val['s']);
446 flag_set['s'] = 1;
447 }
448/*
449 if (flag_set['Z']) {
450 bkpinfo->blank_dvd_first = TRUE;
451 }
452*/
453 }
454
455 if (flag_set['t'] || flag_set['u']) { /* tape size */
456 if (strchr(flag_val['d'], ',')) {
457 fatal_error
458 ("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
459 }
460 if (flag_set['O']) {
461 if (flag_set['s']) {
462 if (flag_set['t']) {
463 fatal_error
464 ("For the moment, please don't specify a tape size. Mondo should handle end-of-tape gracefully anyway.");
465 }
466 if (process_the_s_switch(bkpinfo, flag_val['s'])) {
467 fatal_error("Bad -s switch");
468 }
469 } else if (flag_set['u'] || flag_set['t']) {
470 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
471 bkpinfo->media_size[i] = 0;
472 }
473 } else {
474 retval++;
475 log_to_screen("Tape size not specified.\n");
476 }
477 }
478 } else { /* CD|USB size */
479 if (flag_set['s']) {
480 if (process_the_s_switch(bkpinfo, flag_val['s'])) {
481 fatal_error("Bad -s switch");
482 }
483 }
484 if (flag_set['w']) {
485 bkpinfo->wipe_media_first = TRUE;
486 } /* CD-RW */
487 }
488 if (flag_set['n']) {
489 strncpy(bkpinfo->nfs_mount, flag_val['n'], MAX_STR_LEN);
490 if (!flag_set['d']) {
491 strncpy(bkpinfo->nfs_remote_dir, "/", MAX_STR_LEN);
492 }
493 sprintf(tmp, "mount | grep -E \"^%s .*\" | cut -d' ' -f3",
494 bkpinfo->nfs_mount);
495 strncpy(bkpinfo->isodir,
496 call_program_and_get_last_line_of_output(tmp),
497 MAX_STR_LEN / 4);
498 if (strlen(bkpinfo->isodir) < 3) {
499 retval++;
500 log_to_screen("NFS share is not mounted. Please mount it.\n");
501 }
502 mr_msg(3, "mount = %s", bkpinfo->nfs_mount);
503 mr_msg(3, "isodir= %s", bkpinfo->isodir);
504 }
505 if (flag_set['c']) {
506 bkpinfo->backup_media_type = cdr;
507 }
508 if (flag_set['C']) {
509 bkpinfo->backup_media_type = cdstream;
510 }
511 if (flag_set['i']) {
512 bkpinfo->backup_media_type = iso;
513 }
514 if (flag_set['n']) {
515 bkpinfo->backup_media_type = nfs;
516 }
517 if (flag_set['r']) {
518 bkpinfo->backup_media_type = dvd;
519 }
520 if (flag_set['t']) {
521 bkpinfo->backup_media_type = tape;
522 }
523 if (flag_set['u']) {
524 bkpinfo->backup_media_type = udev;
525 }
526 if (flag_set['w']) {
527 bkpinfo->backup_media_type = cdrw;
528 }
529 if (flag_set['U']) {
530 bkpinfo->backup_media_type = usb;
531 }
532 if (flag_set['z']) {
533 if (find_home_of_exe("getfattr")) {
534 mr_asprintf(&g_getfattr,"getfattr");
535 }
536 if (find_home_of_exe("getfacl")) {
537 mr_asprintf(&g_getfacl,"getfacl");
538 }
539 }
540
541 /* optional, popular */
542 if (flag_set['g']) {
543 g_text_mode = FALSE;
544 }
545
546 if (flag_set['E']) {
547 if (bkpinfo->exclude_paths[0]) {
548 strcat(bkpinfo->exclude_paths, " ");
549 }
550 mr_asprintf(&tmp1, flag_val['E']);
551 p = tmp1;
552 q = tmp1;
553
554 /* Cut the flag_val['E'] in parts containing all paths to test them */
555 while (p != NULL) {
556 q = strchr(p, ' ');
557 if (q != NULL) {
558 *q = '\0';
559 /* Fix bug 14 where ending / cause a problem later
560 * so handled here for the moment */
561 q--;
562 if (*q == '/') {
563 *q = '\0';
564 }
565 q++;
566 /* End of bug fix */
567 if (stat(p, &buf) != 0) {
568 mr_msg(1, "WARNING ! %s doesn't exist", p);
569 }
570 p = q+1 ;
571 } else {
572 if (stat(p, &buf) != 0) {
573 mr_msg(1, "WARNING ! %s doesn't exist", p);
574 }
575 p = NULL;
576 }
577 }
578 mr_free(tmp1);
579
580 strncpy(bkpinfo->exclude_paths + strlen(bkpinfo->exclude_paths),
581 flag_val['E'],
582 4*MAX_STR_LEN - strlen(bkpinfo->exclude_paths));
583 }
584 if (flag_set['e']) {
585 bkpinfo->please_dont_eject = TRUE;
586 }
587 if (flag_set['N']) // exclude NFS mounts & devices
588 {
589 strncpy(psz, list_of_NFS_mounts_only(), MAX_STR_LEN);
590 if (bkpinfo->exclude_paths[0]) {
591 strncat(bkpinfo->exclude_paths, " ", MAX_STR_LEN);
592 }
593 strncat(bkpinfo->exclude_paths, psz, MAX_STR_LEN);
594 mr_msg(3, "-N means we're now excluding %s",
595 bkpinfo->exclude_paths);
596 }
597 if (strlen(bkpinfo->exclude_paths) >= MAX_STR_LEN) {
598 fatal_error
599 ("Your '-E' parameter is too long. Please use '-J'. (See manual.)");
600 }
601 if (flag_set['b']) {
602 strcpy(psz, flag_val['b']);
603 mr_msg(1, "psz = '%s'", psz);
604 if (psz[strlen(psz) - 1] == 'k') {
605 psz[strlen(psz) - 1] = '\0';
606 itbs = atol(psz) * 1024L;
607 } else {
608 itbs = atol(psz);
609 }
610 mr_msg(1, "'%s' --> %ld", flag_val['b'], itbs);
611 mr_msg(1, "Internal tape block size is now %ld bytes", itbs);
612 if (itbs % 512 != 0 || itbs < 256 || itbs > 1024L * 1024) {
613 fatal_error
614 ("Are you nuts? Silly, your internal tape block size is. Abort, I shall.");
615 }
616 bkpinfo->internal_tape_block_size = itbs;
617 }
618 if (flag_set['D']) {
619 bkpinfo->differential = 1;
620// bkpinfo->differential = atoi (flag_val['D']);
621 if ((bkpinfo->differential < 1) || (bkpinfo->differential > 9)) {
622 fatal_error
623 ("The D option should be between 1 and 9 inclusive");
624 }
625 }
626 if (flag_set['x']) {
627 strncpy(bkpinfo->image_devs, flag_val['x'], MAX_STR_LEN / 4);
628 if (run_program_and_log_output("which ntfsclone", 2)) {
629 fatal_error("Please install ntfsprogs package/tarball.");
630 }
631 }
632 if (flag_set['m']) {
633 bkpinfo->manual_cd_tray = TRUE;
634 }
635 if (flag_set['k']) {
636 strncpy(bkpinfo->kernel_path, flag_val['k'], MAX_STR_LEN);
637 if (!strcmp(bkpinfo->kernel_path, "failsafe")) {
638 strcpy(bkpinfo->kernel_path, "FAILSAFE");
639 }
640 if (strcmp(bkpinfo->kernel_path, "FAILSAFE")
641 && !does_file_exist(bkpinfo->kernel_path)) {
642 retval++;
643 sprintf(tmp,
644 "You specified kernel '%s', which does not exist\n",
645 bkpinfo->kernel_path);
646 log_to_screen(tmp);
647 }
648 }
649 if (flag_set['p']) {
650 strncpy(bkpinfo->prefix, flag_val['p'], MAX_STR_LEN / 4);
651 }
652
653
654 if (flag_set['d']) { /* backup directory (if ISO/NFS/USB) */
655 if (flag_set['i']) {
656 strncpy(bkpinfo->isodir, flag_val['d'], MAX_STR_LEN / 4);
657 sprintf(tmp, "ls -l %s", bkpinfo->isodir);
658 if (run_program_and_log_output(tmp, FALSE)) {
659 fatal_error
660 ("output folder does not exist - please create it");
661 }
662 } else if (flag_set['n']) {
663 strncpy(bkpinfo->nfs_remote_dir, flag_val['d'], MAX_STR_LEN);
664 } else { /* backup device (if tape/CD-R/CD-RW) */
665 strncpy(bkpinfo->media_device, flag_val['d'], MAX_STR_LEN / 4);
666 }
667 }
668
669 if (flag_set['n']) {
670 sprintf(tmp, "echo hi > %s/%s/.dummy.txt", bkpinfo->isodir,
671 bkpinfo->nfs_remote_dir);
672 if (run_program_and_log_output(tmp, FALSE)) {
673 retval++;
674 sprintf(tmp,
675 "Are you sure directory '%s' exists in remote dir '%s'?\nIf so, do you have rights to write to it?\n",
676 bkpinfo->nfs_remote_dir, bkpinfo->nfs_mount);
677 log_to_screen(tmp);
678 }
679 }
680
681 if (!flag_set['d']
682 && (flag_set['c'] || flag_set['w'] || flag_set['C'] || flag_set['U'])) {
683 if (g_kernel_version >= 2.6) {
684 if (popup_and_get_string
685 ("Device", "Please specify the device",
686 bkpinfo->media_device, MAX_STR_LEN / 4)) {
687 retval++;
688 log_to_screen("User opted to cancel.");
689 }
690 } else if (find_cdrw_device(bkpinfo->media_device)) {
691 retval++;
692 log_to_screen
693 ("Tried and failed to find CD-R[W] drive automatically.\n");
694 } else {
695 flag_set['d'] = TRUE;
696 strncpy(flag_val['d'], bkpinfo->media_device, MAX_STR_LEN / 4);
697 }
698 }
699
700 if (!flag_set['d'] && !flag_set['n'] && !flag_set['C']) {
701 retval++;
702 log_to_screen("Please specify the backup device/directory.\n");
703 fatal_error
704 ("You didn't use -d to specify the backup device/directory.");
705 }
706/* optional, obscure */
707 for (i = '0'; i <= '9'; i++) {
708 if (flag_set[i]) {
709 bkpinfo->compression_level = i - '0';
710 } /* not '\0' but '0' */
711 }
712 if (flag_set['S']) {
713 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%ld", flag_val['S'],
714 random() % 32768);
715 }
716 if (flag_set['T']) {
717 sprintf(bkpinfo->tmpdir, "%s/tmp.mondo.%ld", flag_val['T'],
718 random() % 32768);
719 sprintf(tmp, "touch %s/.foo.dat", flag_val['T']);
720 if (run_program_and_log_output(tmp, 1)) {
721 retval++;
722 log_to_screen
723 ("Please specify a tempdir which I can write to. :)");
724 fatal_error("I cannot write to the tempdir you specified.");
725 }
726 sprintf(tmp, "ln -sf %s/.foo.dat %s/.bar.dat", flag_val['T'],
727 flag_val['T']);
728 if (run_program_and_log_output(tmp, 1)) {
729 retval++;
730 log_to_screen
731 ("Please don't specify a SAMBA or VFAT or NFS tmpdir.");
732 fatal_error("I cannot write to the tempdir you specified.");
733 }
734 }
735 if (flag_set['A']) {
736 strncpy(bkpinfo->call_after_iso, flag_val['A'], MAX_STR_LEN);
737 }
738 if (flag_set['B']) {
739 strncpy(bkpinfo->call_before_iso, flag_val['B'], MAX_STR_LEN);
740 }
741 if (flag_set['F']) {
742 g_skip_floppies = TRUE;
743 }
744 if (flag_set['H']) {
745 g_cd_recovery = TRUE;
746 }
747 if (flag_set['l']) {
748#ifdef __FreeBSD__
749# define BOOT_LOADER_CHARS "GLBMR"
750#else
751# ifdef __IA64__
752# define BOOT_LOADER_CHARS "GER"
753# else
754# define BOOT_LOADER_CHARS "GLR"
755# endif
756#endif
757 if (!strchr
758 (BOOT_LOADER_CHARS,
759 (bkpinfo->boot_loader = flag_val['l'][0]))) {
760 mr_msg(1, "%c? WTF is %c? I need G, L, E or R.",
761 bkpinfo->boot_loader, bkpinfo->boot_loader);
762 fatal_error
763 ("Please specify GRUB, LILO, ELILO or RAW with the -l switch");
764 }
765#undef BOOT_LOADER_CHARS
766 }
767 if (flag_set['f']) {
768 strncpy(bkpinfo->boot_device,
769 resolve_softlinks_to_get_to_actual_device_file(flag_val
770 ['f']),
771 MAX_STR_LEN / 4);
772 }
773 if (flag_set['P']) {
774 strncpy(bkpinfo->postnuke_tarball, flag_val['P'], MAX_STR_LEN);
775 }
776 if (flag_set['Q']) {
777 i = which_boot_loader(tmp);
778 mr_msg(3, "boot loader is %c, residing at %s", i, tmp);
779 printf("boot loader is %c, residing at %s\n", i, tmp);
780 finish(0);
781 }
782 if (flag_set['L']) {
783 bkpinfo->use_lzo = TRUE;
784 if (run_program_and_log_output("which lzop", FALSE)) {
785 retval++;
786 log_to_screen
787 ("Please install LZOP. You can't use '-L' until you do.\n");
788 }
789 }
790
791 if (flag_set['G']) {
792 bkpinfo->use_gzip = TRUE;
793 if (run_program_and_log_output("which gzip", FALSE)) {
794 retval++;
795 log_to_screen
796 ("Please install gzip. You can't use '-G' until you do.\n");
797 }
798 }
799
800 if (!flag_set['o']
801 &&
802 !run_program_and_log_output
803 ("grep -Ei suse /etc/issue.net | grep -E '9.0' | grep 64", TRUE)) {
804 bkpinfo->make_cd_use_lilo = TRUE;
805 log_to_screen
806 ("Forcing you to use LILO. SuSE 9.0 (64-bit) has a broken mkfs.vfat binary.");
807 }
808 if (flag_set['o']) {
809 bkpinfo->make_cd_use_lilo = TRUE;
810 }
811#ifndef __FreeBSD__
812 else {
813 if (!is_this_a_valid_disk_format("vfat")) {
814 bkpinfo->make_cd_use_lilo = TRUE;
815 log_to_screen
816 ("Your kernel appears not to support vfat filesystems. I am therefore");
817 log_to_screen
818 ("using LILO instead of SYSLINUX as the CD/floppy's boot loader.");
819 }
820 if (run_program_and_log_output("which mkfs.vfat", FALSE)) {
821 bkpinfo->make_cd_use_lilo = TRUE;
822#ifdef __IA32__
823 log_to_screen
824 ("Your filesystem is missing 'mkfs.vfat', so I cannot use SYSLINUX as");
825 log_to_screen
826 ("your boot loader. I shall therefore use LILO instead.");
827#endif
828#ifdef __IA64__
829 log_to_screen
830 ("Your filesystem is missing 'mkfs.vfat', so I cannot prepare the EFI");
831 log_to_screen("environment correctly. Please install it.");
832 fatal_error("Aborting");
833#endif
834 }
835#ifdef __IA64__
836 /* We force ELILO usage on IA64 */
837 bkpinfo->make_cd_use_lilo = TRUE;
838#endif
839 }
840#endif
841
842 if (bkpinfo->make_cd_use_lilo && !does_file_exist("/boot/boot.b")) {
843 paranoid_system("touch /boot/boot.b");
844 }
845
846 i = flag_set['O'] + flag_set['V'];
847 if (i == 0) {
848 retval++;
849 log_to_screen("Specify backup (-O), verify (-V) or both (-OV).\n");
850 }
851
852/* and finally... */
853
854 mr_free(tmp);
855 mr_free(psz);
856 return (retval);
857}
858
859
860
861/**
862 * Get the switches from @p argc and @p argv using getopt() and place them in
863 * @p flag_set and @p flag_val.
864 * @param argc The argument count (@p argc passed to main()).
865 * @param argv The argument vector (@p argv passed to main()).
866 * @param flag_val An array indexed by switch letter - if a switch is set and
867 * has an argument then set flag_val[switch] to that argument.
868 * @param flag_set An array indexed by switch letter - if a switch is set then
869 * set flag_set[switch] to TRUE, else set it to FALSE.
870 * @return The number of problems with the command line (0 for success).
871 */
872int
873retrieve_switches_from_command_line(int argc, char *argv[],
874 char flag_val[128][MAX_STR_LEN],
875 bool flag_set[128])
876{
877 /*@ ints ** */
878 int opt = 0;
879 char tmp[MAX_STR_LEN];
880 int i = 0;
881 int len;
882
883 /*@ bools *** */
884 bool bad_switches = FALSE;
885
886 assert(flag_val != NULL);
887 assert(flag_set != NULL);
888
889 for (i = 0; i < 128; i++) {
890 flag_val[i][0] = '\0';
891 flag_set[i] = FALSE;
892 }
893 while ((opt =
894 getopt(argc, argv,
895 "0123456789A:B:C:DE:FGHI:J:K:LNOP:QRS:T:UVWb:c:d:ef:gik:l:mn:op:rs:tuw:x:z"))
896 != -1) {
897 if (opt == '?') {
898 bad_switches = TRUE;
899 /*log_it("Invalid option: %c\n",optopt); */
900 } else {
901 if (flag_set[optopt]) {
902 bad_switches = TRUE;
903 sprintf(tmp, "Switch -%c previously defined as %s\n", opt,
904 flag_val[i]);
905 log_to_screen(tmp);
906 } else {
907 flag_set[opt] = TRUE;
908 if (optarg) {
909 len = strlen(optarg);
910 if (optarg[0] != '/' && optarg[len - 1] == '/') {
911 optarg[--len] = '\0';
912 log_to_screen
913 ("Warning - param '%s' should not have trailing slash!",
914 optarg);
915 }
916 if (opt == 'd') {
917 if (strchr(flag_val[opt], '/')
918 && flag_val[opt][0] != '/') {
919 sprintf(tmp,
920 "-%c flag --- must be absolute path --- '%s' isn't absolute",
921 opt, flag_val[opt]);
922 log_to_screen(tmp);
923 bad_switches = TRUE;
924 }
925 }
926 strcpy(flag_val[opt], optarg);
927 }
928 }
929 }
930 }
931 for (i = optind; i < argc; i++) {
932 bad_switches = TRUE;
933 sprintf(tmp, "Invalid arg -- %s\n", argv[i]);
934 log_to_screen(tmp);
935 }
936 return (bad_switches);
937}
938
939
940
941
942/**
943 * Print a not-so-helpful help message and exit.
944 */
945void help_screen(void)
946{
947 mr_msg(1, "Type 'man mondo-archive' for more information\n");
948 exit(1);
949}
950
951
952/**
953 * Terminate Mondo in response to a signal.
954 * @param sig The signal number received.
955 */
956void terminate_daemon(int sig)
957{
958 char tmp[64];
959 char tmp2[MAX_STR_LEN];
960 // char command[512];
961 // pid_t pid;
962
963 switch (sig) {
964 case SIGINT:
965 sprintf(tmp, "SIGINT");
966 strcpy(tmp2, "You interrupted me :-)");
967 break;
968 case SIGKILL:
969 sprintf(tmp, "SIGKILL");
970 strcpy(tmp2,
971 "I seriously have no clue how this signal even got to me. Something's wrong with your system.");
972 break;
973 case SIGTERM:
974 sprintf(tmp, "SIGTERM");
975 strcpy(tmp2, "Got terminate signal");
976 break;
977 case SIGHUP:
978 sprintf(tmp, "SIGHUP");
979 strcpy(tmp2, "Hangup on line");
980 break;
981 case SIGSEGV:
982 sprintf(tmp, "SIGSEGV");
983 strcpy(tmp2,
984 "Internal programming error. Please send a backtrace as well as your log.");
985 break;
986 case SIGPIPE:
987 sprintf(tmp, "SIGPIPE");
988 strcpy(tmp2, "Pipe was broken");
989 break;
990 case SIGABRT:
991 sprintf(tmp, "SIGABRT");
992 sprintf(tmp2,
993 "Abort - probably failed assertion. I'm sleeping for a few seconds so you can read the message.");
994 break;
995 default:
996 sprintf(tmp, "(Unknown)");
997 }
998
999 strcat(tmp, " signal received from OS");
1000 log_to_screen(tmp);
1001 log_to_screen(tmp2);
1002 if (sig == SIGABRT) {
1003 sleep(10);
1004 }
1005 kill_buffer();
1006 fatal_error
1007 ("Mondoarchive is terminating in response to a signal from the OS");
1008 finish(254); // just in case
1009}
1010
1011
1012
1013
1014/**
1015 * Turn signal-trapping on or off.
1016 * @param on If TRUE, turn it on; if FALSE, turn it off (we still trap it, just don't do as much).
1017 */
1018void set_signals(int on)
1019{
1020 int signals[] =
1021 { SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT, SIGKILL, SIGSTOP, 0 };
1022 int i;
1023
1024 signal(SIGPIPE, sigpipe_occurred);
1025 for (i = 0; signals[i]; i++) {
1026 if (on) {
1027 signal(signals[i], terminate_daemon);
1028 } else {
1029 signal(signals[i], termination_in_progress);
1030 }
1031 }
1032}
1033
1034
1035
1036
1037/**
1038 * Exit immediately without cleaning up.
1039 * @param sig The signal we are exiting due to.
1040 */
1041void termination_in_progress(int sig)
1042{
1043 mr_msg(1, "Termination in progress");
1044 usleep(1000);
1045 pthread_exit(0);
1046}
1047
1048/* @} - end of cliGroup */
Note: See TracBrowser for help on using the repository browser.