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

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

Replaced all occurrences of egrep with 'grep -E' and of fgrep with
'grep -F' in mondo.
egrep and fgrep are usually just script wrappers around grep these
days which means additional overhead compared to calling grep with the
relevant option. Also, it appears that egrep and fgrep have been
deprecated by POSIX some time ago.

  • Property svn:keywords set to Id
File size: 31.3 KB
RevLine 
[1]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
[116]9cvsid : $Id: mondo-cli.c 681 2006-06-25 02:41:57Z andree $
[1]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
[116]169//static char cvsid[] = "$Id: mondo-cli.c 681 2006-06-25 02:41:57Z andree $";
[1]170
171extern int g_loglevel;
172extern bool g_text_mode;
[116]173extern bool g_skip_floppies; ///< Whether to skip the creation of boot disks
174extern char g_startdir[MAX_STR_LEN]; ///< ????? @bug ?????
[1]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******** **************************************************/
[116]189bool g_debugging = FALSE; ///< ????? @bug ????? @ingroup globalGroup
190bool g_running_live = FALSE; ///< ????? @bug ????? @ingroup globalGroup
[1]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
[116]214extern char *resolve_softlinks_to_get_to_actual_device_file(char *);
[1]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
[116]230handle_incoming_parameters(int argc, char *argv[],
231 struct s_bkpinfo *bkpinfo)
[1]232{
[116]233 /*@ int *** */
234 int res = 0;
235 int retval = 0;
236 int i = 0, j;
[1]237
[116]238 /*@ buffers *************** */
239 char *tmp;
240 char flag_val[128][MAX_STR_LEN];
241 bool flag_set[128];
[1]242
[116]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 }
[541]249 // strcpy (bkpinfo->tmpdir, "/root/images/mondo");
250 // strcpy (bkpinfo->scratchdir, "/home");
[116]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 }
[1]262/*
263 if (!retval)
264 {
265*/
[116]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 }
[1]272 }
273// }
[116]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);
[1]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{
[116]305 int j;
306 char tmp[MAX_STR_LEN], *p, comment[MAX_STR_LEN];
[1]307
[116]308 assert(bkpinfo != NULL);
309 assert(value != NULL);
[1]310
[116]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);
[1]320 }
[116]321 for (; j <= MAX_NOOF_MEDIA; j++) {
322 bkpinfo->media_size[j] = friendly_sizestr_to_sizelong(p);
[1]323 }
324// bkpinfo->media_size[0] = bkpinfo->media_size[MAX_NOOF_MEDIA];
[116]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);
[1]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
[116]347process_switches(struct s_bkpinfo *bkpinfo,
348 char flag_val[128][MAX_STR_LEN], bool flag_set[128])
[1]349{
350
[116]351 /*@ ints *** */
352 int i = 0;
353 int retval = 0;
354 int percent = 0;
[1]355
[116]356 /*@ buffers ** */
357 char *tmp;
[542]358 char *tmp1;
[116]359 char *psz;
[603]360 char *p;
361 char *q;
[1]362
[116]363 long itbs;
[1]364
[289]365 struct stat buf;
366
[116]367 malloc_string(tmp);
368 malloc_string(psz);
[1]369
[116]370 assert(bkpinfo != NULL);
371 assert(flag_val != NULL);
372 assert(flag_set != NULL);
[1]373
[116]374 bkpinfo->internal_tape_block_size = DEFAULT_INTERNAL_TAPE_BLOCK_SIZE;
[1]375
376/* compulsory */
[116]377 i = flag_set['c'] + flag_set['i'] + flag_set['n'] +
378 flag_set['t'] + flag_set['u'] + flag_set['r'] +
379 flag_set['w'] + flag_set['C'];
380 if (i == 0) {
381 retval++;
[541]382 log_to_screen("You must specify the media type\n");
[1]383 }
[116]384 if (i > 1) {
385 retval++;
[541]386 log_to_screen("Please specify only one media type\n");
[1]387 }
[116]388 if (flag_set['K']) {
389 g_loglevel = atoi(flag_val['K']);
390 if (g_loglevel < 3) {
391 g_loglevel = 3;
392 }
[1]393 }
[116]394 if (flag_set['L'] && flag_set['0']) {
395 retval++;
[541]396 log_to_screen("You cannot have 'no compression' _and_ LZOP.\n");
[1]397 }
[116]398 bkpinfo->backup_data = flag_set['O'];
399 bkpinfo->verify_data = flag_set['V'];
400 if (flag_set['I'] && !bkpinfo->backup_data) {
[541]401 log_to_screen("-I switch is ignored if just verifying");
[116]402 }
403 if (flag_set['E'] && !bkpinfo->backup_data) {
[541]404 log_to_screen("-E switch is ignored if just verifying");
[116]405 }
[1]406
[116]407 if (!find_home_of_exe("afio")) {
408 if (find_home_of_exe("star")) {
409 flag_set['R'] = TRUE;
410 log_msg(1, "Using star instead of afio");
411 } else {
412 fatal_error
413 ("Neither afio nor star is installed. Please install at least one.");
414 }
[1]415 }
416
[116]417 if (flag_set['R']) {
418 bkpinfo->use_star = TRUE;
419 if (flag_set['L']) {
420 fatal_error("You may not use star and lzop at the same time.");
421 }
422 if (!find_home_of_exe("star")) {
423 fatal_error
424 ("Please install 'star' RPM or tarball if you are going to use -R. Thanks.");
425 }
[1]426 }
[116]427 if (flag_set['W']) {
428 bkpinfo->nonbootable_backup = TRUE;
429 log_to_screen("Warning - you have opted for non-bootable backup");
430 if (flag_set['f'] || flag_set['l']) {
431 log_to_screen
[541]432 ("You don't need to specify bootloader or bootdevice");
[116]433 }
[1]434 }
[116]435 if (flag_set['t'] && flag_set['H']) {
436 fatal_error
437 ("Sorry, you may not nuke w/o warning from tape. Drop -H, please.");
438 }
439 if (flag_set['I']) {
440 if (!strcmp(bkpinfo->include_paths, "/")) {
441 log_msg(2, "'/' is pleonastic.");
442 bkpinfo->include_paths[0] = '\0';
443 }
444 if (bkpinfo->include_paths[0]) {
445 strcat(bkpinfo->include_paths, " ");
446 }
[542]447 asprintf(&tmp1, flag_val['I']);
[603]448 p = tmp1;
449 q = tmp1;
[542]450
451 /* Cut the flag_val['I'] in parts containing all paths to test them */
452 while (p != NULL) {
453 q = strchr(p, ' ');
454 if (q != NULL) {
455 *q = '\0';
456 if (stat(p, &buf) != 0) {
457 log_msg(1, "ERROR ! %s doesn't exist", p);
458 fatal_error("ERROR ! You specified a directory to include which doesn't exist");
459 }
[633]460 p = q+1 ;
[542]461 } else {
462 if (stat(p, &buf) != 0) {
463 log_msg(1, "ERROR ! %s doesn't exist", p);
464 fatal_error("ERROR ! You specified a directory to include which doesn't exist");
465 }
466 p = NULL;
467 }
[289]468 }
[542]469 paranoid_free(tmp1);
470
[116]471 strncpy(bkpinfo->include_paths + strlen(bkpinfo->include_paths),
472 flag_val['I'],
[543]473 4*MAX_STR_LEN - strlen(bkpinfo->include_paths));
[116]474 log_msg(1, "include_paths is now '%s'", bkpinfo->include_paths);
475 if (bkpinfo->include_paths[0] == '-') {
476 retval++;
[541]477 log_to_screen("Please supply a sensible value with '-I'\n");
[116]478 }
479 }
[1]480
[116]481 if (g_kernel_version >= 2.6 && !flag_set['d']
482 && (flag_set['c'] || flag_set['w'])) {
483 fatal_error
484 ("If you are using the 2.6.x kernel, please specify the CD-R(W) device.");
[1]485 }
486
[116]487
488 if (flag_set['J']) {
489 if (flag_set['I']) {
490 retval++;
491 log_to_screen
[541]492 ("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. :-)");
[116]493 }
494 bkpinfo->make_filelist = FALSE;
495 strcpy(bkpinfo->include_paths, flag_val['J']);
[1]496 }
[116]497 if (flag_set['c'] || flag_set['w'] || flag_set['C'] || flag_set['r']) {
498 if (!flag_set['r'] && g_kernel_version <= 2.5
499 && strstr(flag_val['d'], "/dev/")) {
500 fatal_error
501 ("Please don't give a /dev entry. Give a SCSI node for the parameter of the -d flag.");
502 }
503 if (flag_set['r'] && g_kernel_version <= 2.5
504 && !strstr(flag_val['d'], "/dev/")) {
505 fatal_error
506 ("Please give a /dev entry, not a SCSI node, as the parameter of the -d flag.");
507 }
508 if (g_kernel_version >= 2.6 && !strstr(flag_val['d'], "/dev/")) {
509 log_to_screen
[541]510 ("Linus says 2.6 has a broken ide-scsi module. Proceed at your own risk...");
[116]511 }
512
513 if (system("which cdrecord > /dev/null 2> /dev/null")
514 && system("which dvdrecord > /dev/null 2> /dev/null")) {
515 fatal_error
516 ("Please install dvdrecord/cdrecord and try again.");
517 }
518 if (flag_set['C']) {
519 bkpinfo->cdrw_speed = atoi(flag_val['C']);
520 if (bkpinfo->cdrw_speed < 1) {
521 fatal_error
522 ("You specified a silly speed for a CD-R[W] drive");
523 }
524 if (!flag_set['L']) {
525 log_to_screen
[541]526 ("You must use -L with -C. Therefore I am setting it for you.");
[116]527 flag_set['L'] = 1;
528 flag_val['L'][0] = '\0';
529 }
530 } else {
531 log_msg(3, "flag_val['c'] = %s", flag_val['c']);
532 log_msg(3, "flag_val['w'] = %s", flag_val['w']);
533// log_msg(3, "flag_set['r'] = %i", flag_set['r'] );
534 if (flag_set['c']) {
535 bkpinfo->cdrw_speed = atoi(flag_val['c']);
536 } else if (flag_set['w']) {
537 bkpinfo->cdrw_speed = atoi(flag_val['w']);
538 } else if (flag_set['r']) {
539 bkpinfo->cdrw_speed = 1; /*atoi(flag_val['r']); */
540 }
541
542 if (bkpinfo->cdrw_speed < 1) {
543 fatal_error
544 ("You specified a silly speed for a CD-R[W] drive");
545 }
546 }
[1]547 }
[116]548 if (flag_set['t'] && !flag_set['d']) {
549 log_it("Hmm! No tape drive specified. Let's see what we can do.");
550 if (find_tape_device_and_size(flag_val['d'], tmp)) {
551 fatal_error
552 ("Tape device not specified. I couldn't find it either.");
553 }
554 flag_set['d'] = TRUE;
555 sprintf(tmp,
[541]556 "You didn't specify a tape streamer device. I'm assuming %s",
[116]557 flag_val['d']);
558 log_to_screen(tmp);
559 percent = 0;
560 }
561
562 if (flag_set['r']) // DVD
563 {
564 if (flag_set['m']) {
565 fatal_error
566 ("Manual CD tray (-m) not yet supported in conjunction w/ DVD drives. Drop -m.");
567 }
568 if (!flag_set['d']) {
569 if (!find_dvd_device(flag_val['d'], FALSE)) {
570 flag_set['d'] = TRUE;
[541]571 log_to_screen("I guess DVD drive is at %s", flag_val['d']);
[116]572 }
573 }
574 if (!find_home_of_exe("growisofs")) {
575 fatal_error
576 ("Please install growisofs (probably part of dvd+rw-tools). If you want DVD support, you need it.");
577 }
578 if (!find_home_of_exe("dvd+rw-format")) {
579 fatal_error
580 ("Please install dvd+rw-format (probably part of dvd+rw-tools). If you want DVD support, you need it.");
581 }
582 if (strchr(flag_val['d'], ',')) {
583 fatal_error
584 ("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
585 }
586 if (!flag_set['s']) {
587 sprintf(flag_val['s'], "%d", DEFAULT_DVD_DISK_SIZE); // 4.7 salesman's GB = 4.482 real GB = 4582 MB
588 strcat(flag_val['s'], "m");
589 log_to_screen
[541]590 ("You did not specify a size (-s) for DVD. I'm guessing %s.",
[116]591 flag_val['s']);
592 flag_set['s'] = 1;
593 }
[1]594/*
595 if (flag_set['Z']) {
596 bkpinfo->blank_dvd_first = TRUE;
597 }
598*/
[116]599 }
[1]600
[116]601 if (flag_set['t'] || flag_set['u']) { /* tape size */
602 if (strchr(flag_val['d'], ',')) {
603 fatal_error
604 ("Please don't give a SCSI node. Give a _device_, preferably a /dev entry, for the parameter of the -d flag.");
605 }
606 if (flag_set['O']) {
607 if (flag_set['s']) {
608 if (flag_set['t']) {
609 fatal_error
610 ("For the moment, please don't specify a tape size. Mondo should handle end-of-tape gracefully anyway.");
611 }
612 if (process_the_s_switch(bkpinfo, flag_val['s'])) {
613 fatal_error("Bad -s switch");
614 }
615 } else if (flag_set['u'] || flag_set['t']) {
616 for (i = 0; i <= MAX_NOOF_MEDIA; i++) {
617 bkpinfo->media_size[i] = 0;
618 }
619 } else {
620 retval++;
621 log_to_screen("Tape size not specified.\n");
622 }
623 }
624 } else { /* CD size */
625 if (flag_set['s']) {
626 if (process_the_s_switch(bkpinfo, flag_val['s'])) {
627 fatal_error("Bad -s switch");
628 }
629 }
630 if (flag_set['w']) {
631 bkpinfo->wipe_media_first = TRUE;
632 } /* CD-RW */
[1]633 }
[116]634 if (flag_set['n']) {
635 strncpy(bkpinfo->nfs_mount, flag_val['n'], MAX_STR_LEN);
636 if (!flag_set['d']) {
637 strncpy(bkpinfo->nfs_remote_dir, "/", MAX_STR_LEN);
638 }
639 sprintf(tmp, "mount | grep -x \"%s .*\" | cut -d' ' -f3",
640 bkpinfo->nfs_mount);
641 strncpy(bkpinfo->isodir,
642 call_program_and_get_last_line_of_output(tmp),
643 MAX_STR_LEN / 4);
644 if (strlen(bkpinfo->isodir) < 3) {
645 retval++;
[541]646 log_to_screen("NFS share is not mounted. Please mount it.\n");
[116]647 }
648 log_msg(3, "mount = %s", bkpinfo->nfs_mount);
649 log_msg(3, "isodir= %s", bkpinfo->isodir);
[1]650 }
[116]651 if (flag_set['c']) {
652 bkpinfo->backup_media_type = cdr;
[1]653 }
[116]654 if (flag_set['C']) {
655 bkpinfo->backup_media_type = cdstream;
[1]656 }
[116]657 if (flag_set['i']) {
658 bkpinfo->backup_media_type = iso;
659 }
660 if (flag_set['n']) {
661 bkpinfo->backup_media_type = nfs;
662 }
663 if (flag_set['r']) {
664 bkpinfo->backup_media_type = dvd;
665 }
666 if (flag_set['t']) {
667 bkpinfo->backup_media_type = tape;
668 }
669 if (flag_set['u']) {
670 bkpinfo->backup_media_type = udev;
671 }
672 if (flag_set['w']) {
673 bkpinfo->backup_media_type = cdrw;
674 }
[1]675
676/* optional, popular */
[116]677 if (flag_set['g']) {
678 g_text_mode = FALSE;
679 }
680 if (flag_set['E']) {
681 if (bkpinfo->exclude_paths[0]) {
682 strcat(bkpinfo->exclude_paths, " ");
683 }
[542]684 asprintf(&tmp1, flag_val['E']);
[605]685 p = tmp1;
686 q = tmp1;
[542]687
688 /* Cut the flag_val['E'] in parts containing all paths to test them */
689 while (p != NULL) {
690 q = strchr(p, ' ');
691 if (q != NULL) {
692 *q = '\0';
693 if (stat(p, &buf) != 0) {
694 log_msg(1, "WARNING ! %s doesn't exist", p);
695 }
[633]696 p = q+1 ;
[542]697 } else {
698 if (stat(p, &buf) != 0) {
699 log_msg(1, "WARNING ! %s doesn't exist", p);
700 }
701 p = NULL;
702 }
[289]703 }
[542]704 paranoid_free(tmp1);
705
[116]706 strncpy(bkpinfo->exclude_paths + strlen(bkpinfo->exclude_paths),
707 flag_val['E'],
[543]708 4*MAX_STR_LEN - strlen(bkpinfo->exclude_paths));
[116]709 }
710 if (flag_set['e']) {
711 bkpinfo->please_dont_eject = TRUE;
712 }
713 if (flag_set['N']) // exclude NFS mounts & devices
714 {
[1]715// strncpy(psz, list_of_NFS_devices_and_mounts(), MAX_STR_LEN);
[116]716 strncpy(psz, list_of_NFS_mounts_only(), MAX_STR_LEN);
717 if (bkpinfo->exclude_paths[0]) {
718 strncat(bkpinfo->exclude_paths, " ", MAX_STR_LEN);
719 }
720 strncat(bkpinfo->exclude_paths, psz, MAX_STR_LEN);
721 log_msg(3, "-N means we're now excluding %s",
722 bkpinfo->exclude_paths);
723 }
724 if (strlen(bkpinfo->exclude_paths) >= MAX_STR_LEN) {
725 fatal_error
726 ("Your '-E' parameter is too long. Please use '-J'. (See manual.)");
727 }
728 if (flag_set['b']) {
729 strcpy(psz, flag_val['b']);
730 log_msg(1, "psz = '%s'", psz);
731 if (psz[strlen(psz) - 1] == 'k') {
732 psz[strlen(psz) - 1] = '\0';
733 itbs = atol(psz) * 1024L;
734 } else {
735 itbs = atol(psz);
736 }
737 log_msg(1, "'%s' --> %ld", flag_val['b'], itbs);
738 log_msg(1, "Internal tape block size is now %ld bytes", itbs);
739 if (itbs % 512 != 0 || itbs < 256 || itbs > 1024L * 1024) {
740 fatal_error
741 ("Are you nuts? Silly, your internal tape block size is. Abort, I shall.");
742 }
743 bkpinfo->internal_tape_block_size = itbs;
744 }
745 if (flag_set['D']) {
746 bkpinfo->differential = 1;
[1]747// bkpinfo->differential = atoi (flag_val['D']);
[116]748 if ((bkpinfo->differential < 1) || (bkpinfo->differential > 9)) {
749 fatal_error
750 ("The D option should be between 1 and 9 inclusive");
751 }
[1]752 }
[116]753 if (flag_set['x']) {
754 strncpy(bkpinfo->image_devs, flag_val['x'], MAX_STR_LEN / 4);
[296]755 if (run_program_and_log_output("which ntfsclone", 2)) {
756 fatal_error("Please install ntfsprogs package/tarball.");
[116]757 }
[1]758 }
[116]759 if (flag_set['m']) {
760 bkpinfo->manual_cd_tray = TRUE;
[1]761 }
[116]762 if (flag_set['k']) {
763 strncpy(bkpinfo->kernel_path, flag_val['k'], MAX_STR_LEN);
764 if (!strcmp(bkpinfo->kernel_path, "failsafe")) {
765 strcpy(bkpinfo->kernel_path, "FAILSAFE");
766 }
767 if (strcmp(bkpinfo->kernel_path, "FAILSAFE")
768 && !does_file_exist(bkpinfo->kernel_path)) {
769 retval++;
770 sprintf(tmp,
[541]771 "You specified kernel '%s', which does not exist\n",
[116]772 bkpinfo->kernel_path);
773 log_to_screen(tmp);
774 }
775 }
776 if (flag_set['p']) {
777 strncpy(bkpinfo->prefix, flag_val['p'], MAX_STR_LEN / 4);
778 }
[1]779
780
[116]781 if (flag_set['d']) { /* backup directory (if ISO/NFS) */
782 if (flag_set['i']) {
783 strncpy(bkpinfo->isodir, flag_val['d'], MAX_STR_LEN / 4);
784 sprintf(tmp, "ls -l %s", bkpinfo->isodir);
785 if (run_program_and_log_output(tmp, FALSE)) {
786 fatal_error
787 ("output folder does not exist - please create it");
788 }
789 } else if (flag_set['n']) {
790 strncpy(bkpinfo->nfs_remote_dir, flag_val['d'], MAX_STR_LEN);
791 } else { /* backup device (if tape/CD-R/CD-RW) */
792
793 strncpy(bkpinfo->media_device, flag_val['d'], MAX_STR_LEN / 4);
794 }
[1]795 }
[116]796
797 if (flag_set['n']) {
798 sprintf(tmp, "echo hi > %s/%s/.dummy.txt", bkpinfo->isodir,
799 bkpinfo->nfs_remote_dir);
800 if (run_program_and_log_output(tmp, FALSE)) {
801 retval++;
802 sprintf(tmp,
[541]803 "Are you sure directory '%s' exists in remote dir '%s'?\nIf so, do you have rights to write to it?\n",
[116]804 bkpinfo->nfs_remote_dir, bkpinfo->nfs_mount);
805 log_to_screen(tmp);
806 }
[1]807 }
808
[116]809 if (!flag_set['d']
810 && (flag_set['c'] || flag_set['w'] || flag_set['C'])) {
811 if (g_kernel_version >= 2.6) {
812 if (popup_and_get_string
[541]813 ("Device", "Please specify the device",
[116]814 bkpinfo->media_device, MAX_STR_LEN / 4)) {
815 retval++;
[541]816 log_to_screen("User opted to cancel.");
[116]817 }
818 } else if (find_cdrw_device(bkpinfo->media_device)) {
819 retval++;
820 log_to_screen
[541]821 ("Tried and failed to find CD-R[W] drive automatically.\n");
[116]822 } else {
823 flag_set['d'] = TRUE;
824 strncpy(flag_val['d'], bkpinfo->media_device, MAX_STR_LEN / 4);
825 }
[1]826 }
827
[116]828 if (!flag_set['d'] && !flag_set['n'] && !flag_set['C']) {
829 retval++;
[541]830 log_to_screen("Please specify the backup device/directory.\n");
[116]831 fatal_error
832 ("You didn't use -d to specify the backup device/directory.");
[1]833 }
[116]834/* optional, obscure */
835 for (i = '0'; i <= '9'; i++) {
836 if (flag_set[i]) {
837 bkpinfo->compression_level = i - '0';
838 } /* not '\0' but '0' */
[1]839 }
[116]840 if (flag_set['S']) {
841 sprintf(bkpinfo->scratchdir, "%s/mondo.scratch.%ld", flag_val['S'],
842 random() % 32768);
[1]843 }
[116]844 if (flag_set['T']) {
845 sprintf(bkpinfo->tmpdir, "%s/tmp.mondo.%ld", flag_val['T'],
846 random() % 32768);
847 sprintf(tmp, "touch %s/.foo.dat", flag_val['T']);
848 if (run_program_and_log_output(tmp, 1)) {
849 retval++;
850 log_to_screen
[541]851 ("Please specify a tempdir which I can write to. :)");
[116]852 fatal_error("I cannot write to the tempdir you specified.");
853 }
854 sprintf(tmp, "ln -sf %s/.foo.dat %s/.bar.dat", flag_val['T'],
855 flag_val['T']);
856 if (run_program_and_log_output(tmp, 1)) {
857 retval++;
858 log_to_screen
[541]859 ("Please don't specify a SAMBA or VFAT or NFS tmpdir.");
[116]860 fatal_error("I cannot write to the tempdir you specified.");
861 }
[1]862 }
[116]863 if (flag_set['A']) {
864 strncpy(bkpinfo->call_after_iso, flag_val['A'], MAX_STR_LEN);
865 }
866 if (flag_set['B']) {
867 strncpy(bkpinfo->call_before_iso, flag_val['B'], MAX_STR_LEN);
868 }
869 if (flag_set['F']) {
870 g_skip_floppies = TRUE;
871 }
872 if (flag_set['H']) {
873 g_cd_recovery = TRUE;
874 }
875 if (flag_set['l']) {
[1]876#ifdef __FreeBSD__
877# define BOOT_LOADER_CHARS "GLBMR"
878#else
879# ifdef __IA64__
880# define BOOT_LOADER_CHARS "GER"
881# else
882# define BOOT_LOADER_CHARS "GLR"
883# endif
884#endif
[116]885 if (!strchr
886 (BOOT_LOADER_CHARS,
887 (bkpinfo->boot_loader = flag_val['l'][0]))) {
888 log_msg(1, "%c? WTF is %c? I need G, L, E or R.",
889 bkpinfo->boot_loader, bkpinfo->boot_loader);
890 fatal_error
891 ("Please specify GRUB, LILO, ELILO or RAW with the -l switch");
892 }
[1]893#undef BOOT_LOADER_CHARS
894 }
[116]895 if (flag_set['f']) {
896 strncpy(bkpinfo->boot_device,
897 resolve_softlinks_to_get_to_actual_device_file(flag_val
898 ['f']),
899 MAX_STR_LEN / 4);
900 }
901 if (flag_set['P']) {
902 strncpy(bkpinfo->postnuke_tarball, flag_val['P'], MAX_STR_LEN);
903 }
904 if (flag_set['Q']) {
905 i = which_boot_loader(tmp);
906 log_msg(3, "boot loader is %c, residing at %s", i, tmp);
[541]907 printf("boot loader is %c, residing at %s\n", i, tmp);
[116]908 finish(0);
909 }
910 if (flag_set['L']) {
911 bkpinfo->use_lzo = TRUE;
912 if (run_program_and_log_output("which lzop", FALSE)) {
913 retval++;
914 log_to_screen
[541]915 ("Please install LZOP. You can't use '-L' until you do.\n");
[116]916 }
917 }
[1]918
[116]919 if (!flag_set['o']
920 &&
921 !run_program_and_log_output
[681]922 ("grep -Ei suse /etc/issue.net | grep -E '9.0' | grep 64", TRUE)) {
[116]923 bkpinfo->make_cd_use_lilo = TRUE;
924 log_to_screen
[541]925 ("Forcing you to use LILO. SuSE 9.0 (64-bit) has a broken mkfs.vfat binary.");
[116]926 }
927 if (flag_set['o']) {
928 bkpinfo->make_cd_use_lilo = TRUE;
929 }
[1]930#ifndef __FreeBSD__
[116]931 else {
932 if (!is_this_a_valid_disk_format("vfat")) {
933 bkpinfo->make_cd_use_lilo = TRUE;
934 log_to_screen
[541]935 ("Your kernel appears not to support vfat filesystems. I am therefore");
[116]936 log_to_screen
[541]937 ("using LILO instead of SYSLINUX as the CD/floppy's boot loader.");
[116]938 }
939 if (run_program_and_log_output("which mkfs.vfat", FALSE)) {
940 bkpinfo->make_cd_use_lilo = TRUE;
[1]941#ifdef __IA32__
[116]942 log_to_screen
[541]943 ("Your filesystem is missing 'mkfs.vfat', so I cannot use SYSLINUX as");
[116]944 log_to_screen
[541]945 ("your boot loader. I shall therefore use LILO instead.");
[1]946#endif
947#ifdef __IA64__
[116]948 log_to_screen
[541]949 ("Your filesystem is missing 'mkfs.vfat', so I cannot prepare the EFI");
950 log_to_screen("environment correctly. Please install it.");
[116]951 fatal_error("Aborting");
[1]952#endif
[116]953 }
[1]954#ifdef __IA64__
[116]955 /* We force ELILO usage on IA64 */
956 bkpinfo->make_cd_use_lilo = TRUE;
[1]957#endif
[116]958 }
[1]959#endif
960
[116]961 if (bkpinfo->make_cd_use_lilo && !does_file_exist("/boot/boot.b")) {
962 paranoid_system("touch /boot/boot.b");
963 }
[1]964
[116]965 i = flag_set['O'] + flag_set['V'];
966 if (i == 0) {
967 retval++;
[541]968 log_to_screen("Specify backup (-O), verify (-V) or both (-OV).\n");
[116]969 }
[1]970
971/* and finally... */
972
[116]973 paranoid_free(tmp);
974 paranoid_free(psz);
975 return (retval);
[1]976}
977
978
979
980/**
981 * Get the switches from @p argc and @p argv using getopt() and place them in
982 * @p flag_set and @p flag_val.
983 * @param argc The argument count (@p argc passed to main()).
984 * @param argv The argument vector (@p argv passed to main()).
985 * @param flag_val An array indexed by switch letter - if a switch is set and
986 * has an argument then set flag_val[switch] to that argument.
987 * @param flag_set An array indexed by switch letter - if a switch is set then
988 * set flag_set[switch] to TRUE, else set it to FALSE.
989 * @return The number of problems with the command line (0 for success).
990 */
991int
[116]992retrieve_switches_from_command_line(int argc, char *argv[],
993 char flag_val[128][MAX_STR_LEN],
994 bool flag_set[128])
[1]995{
[116]996 /*@ ints ** */
997 int opt = 0;
998 char tmp[MAX_STR_LEN];
999 int i = 0;
1000 int len;
[1]1001
[116]1002 /*@ bools *** */
1003 bool bad_switches = FALSE;
[1]1004
[116]1005 assert(flag_val != NULL);
1006 assert(flag_set != NULL);
[1]1007
[116]1008 for (i = 0; i < 128; i++) {
1009 flag_val[i][0] = '\0';
1010 flag_set[i] = FALSE;
[1]1011 }
[116]1012 while ((opt =
1013 getopt(argc, argv,
1014 "0123456789A:B:C:DE:FHI:J:K:LNOP:QRS:T:VWb:c:d:ef:gik:l:mn:op:rs:tuw:x:"))
1015 != -1) {
1016 if (opt == '?') {
1017 bad_switches = TRUE;
1018 /*log_it("Invalid option: %c\n",optopt); */
1019 } else {
1020 if (flag_set[optopt]) {
1021 bad_switches = TRUE;
[541]1022 sprintf(tmp, "Switch -%c previously defined as %s\n", opt,
[116]1023 flag_val[i]);
1024 log_to_screen(tmp);
1025 } else {
1026 flag_set[opt] = TRUE;
1027 if (optarg) {
1028 len = strlen(optarg);
1029 if (optarg[0] != '/' && optarg[len - 1] == '/') {
1030 optarg[--len] = '\0';
1031 log_to_screen
[541]1032 ("Warning - param '%s' should not have trailing slash!",
[116]1033 optarg);
1034 }
1035 if (opt == 'd') {
1036 if (strchr(flag_val[opt], '/')
1037 && flag_val[opt][0] != '/') {
1038 sprintf(tmp,
[541]1039 "-%c flag --- must be absolute path --- '%s' isn't absolute",
[116]1040 opt, flag_val[opt]);
1041 log_to_screen(tmp);
1042 bad_switches = TRUE;
1043 }
1044 }
1045 strcpy(flag_val[opt], optarg);
1046 }
1047 }
[1]1048 }
1049 }
[116]1050 for (i = optind; i < argc; i++) {
1051 bad_switches = TRUE;
[541]1052 sprintf(tmp, "Invalid arg -- %s\n", argv[i]);
[116]1053 log_to_screen(tmp);
1054 }
1055 return (bad_switches);
[1]1056}
1057
1058
1059
1060
1061/**
1062 * Print a not-so-helpful help message and exit.
1063 */
[116]1064void help_screen()
[1]1065{
[116]1066 log_msg(1, "Type 'man mondo-archive' for more information\n");
1067 exit(1);
[1]1068}
1069
1070
1071/**
1072 * Terminate Mondo in response to a signal.
1073 * @param sig The signal number received.
1074 */
1075void terminate_daemon(int sig)
1076{
[116]1077 char tmp[64];
1078 char tmp2[MAX_STR_LEN];
1079 // char command[512];
1080 // pid_t pid;
[1]1081
[116]1082 switch (sig) {
[1]1083 case SIGINT:
1084 sprintf(tmp, "SIGINT");
[541]1085 strcpy(tmp2, "You interrupted me :-)");
[1]1086 break;
1087 case SIGKILL:
1088 sprintf(tmp, "SIGKILL");
[116]1089 strcpy(tmp2,
[541]1090 "I seriously have no clue how this signal even got to me. Something's wrong with your system.");
[1]1091 break;
1092 case SIGTERM:
1093 sprintf(tmp, "SIGTERM");
[541]1094 strcpy(tmp2, "Got terminate signal");
[1]1095 break;
1096 case SIGHUP:
1097 sprintf(tmp, "SIGHUP");
[541]1098 strcpy(tmp2, "Hangup on line");
[1]1099 break;
1100 case SIGSEGV:
1101 sprintf(tmp, "SIGSEGV");
[116]1102 strcpy(tmp2,
[541]1103 "Internal programming error. Please send a backtrace as well as your log.");
[1]1104 break;
1105 case SIGPIPE:
1106 sprintf(tmp, "SIGPIPE");
[541]1107 strcpy(tmp2, "Pipe was broken");
[1]1108 break;
[116]1109 case SIGABRT:
1110 sprintf(tmp, "SIGABRT");
1111 sprintf(tmp2,
[541]1112 "Abort - probably failed assertion. I'm sleeping for a few seconds so you can read the message.");
[116]1113 break;
[1]1114 default:
[541]1115 sprintf(tmp, "(Unknown)");
[116]1116 }
[1]1117
[541]1118 strcat(tmp, " signal received from OS");
[116]1119 log_to_screen(tmp);
1120 log_to_screen(tmp2);
1121 if (sig == SIGABRT) {
1122 sleep(10);
1123 }
1124 kill_buffer();
1125 fatal_error
1126 ("Mondoarchive is terminating in response to a signal from the OS");
1127 finish(254); // just in case
[1]1128}
1129
1130
1131
1132
1133/**
1134 * Turn signal-trapping on or off.
1135 * @param on If TRUE, turn it on; if FALSE, turn it off (we still trap it, just don't do as much).
1136 */
1137void set_signals(int on)
1138{
[116]1139 int signals[] =
1140 { SIGTERM, SIGHUP, SIGTRAP, SIGABRT, SIGINT, SIGKILL, SIGSTOP, 0 };
1141 int i;
1142
1143 signal(SIGPIPE, sigpipe_occurred);
1144 for (i = 0; signals[i]; i++) {
1145 if (on) {
1146 signal(signals[i], terminate_daemon);
1147 } else {
1148 signal(signals[i], termination_in_progress);
1149 }
1150 }
[1]1151}
1152
1153
1154
1155
1156/**
1157 * Exit immediately without cleaning up.
1158 * @param sig The signal we are exiting due to.
1159 */
1160void termination_in_progress(int sig)
1161{
[116]1162 log_msg(1, "Termination in progress");
1163 usleep(1000);
1164 pthread_exit(0);
[1]1165}
1166
1167/* @} - end of cliGroup */
Note: See TracBrowser for help on using the repository browser.