source: MondoRescue/branches/2.06/mondo/mondo/mondoarchive/mondo-cli.c@ 296

Last change on this file since 296 was 296, checked in by andree, 18 years ago

Replaced partimagehack with ntfsclone from ntfsprogs package. Replaced
all occurrences of strings 'partimagehack' and 'partimage' with 'ntfsprog'.

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