source: MondoRescue/trunk/mondo/src/mondoarchive/mondo-cli.c@ 914

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

merge -r902:913 $SVN_M/branches/stable

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