Imported Upstream version 2.5.2p1
[debian/amanda] / client-src / client_util.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1998 University of Maryland at College Park
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of U.M. not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  U.M. makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Authors: the Amanda Development Team.  Its members are listed in a
24  * file named AUTHORS, in the root directory of this distribution.
25  */
26 /* 
27  * $Id: client_util.c,v 1.34 2006/05/25 01:47:11 johnfranks Exp $
28  *
29  */
30
31 #include "amanda.h"
32 #include "conffile.h"
33 #include "client_util.h"
34 #include "getfsent.h"
35 #include "util.h"
36 #include "pipespawn.h"
37
38 #define MAXMAXDUMPS 16
39
40 static int add_exclude(FILE *file_exclude, char *aexc, int verbose);
41 static int add_include(char *disk, char *device, FILE *file_include, char *ainc, int verbose);
42 static char *build_name(char *disk, char *exin, int verbose);
43 static char *get_name(char *diskname, char *exin, time_t t, int n);
44
45
46 char *
47 fixup_relative(
48     char *      name,
49     char *      device)
50 {
51     char *newname;
52     if(*name != '/') {
53         char *dirname = amname_to_dirname(device);
54         newname = vstralloc(dirname, "/", name , NULL);
55         amfree(dirname);
56     }
57     else {
58         newname = stralloc(name);
59     }
60     return newname;
61 }
62
63
64 static char *
65 get_name(
66     char *      diskname,
67     char *      exin,
68     time_t      t,
69     int         n)
70 {
71     char number[NUM_STR_SIZE];
72     char *filename;
73     char *ts;
74
75     ts = construct_timestamp(&t);
76     if(n == 0)
77         number[0] = '\0';
78     else
79         snprintf(number, SIZEOF(number), "%03d", n - 1);
80         
81     filename = vstralloc(get_pname(), ".", diskname, ".", ts, number, ".",
82                          exin, NULL);
83     amfree(ts);
84     return filename;
85 }
86
87
88 static char *
89 build_name(
90     char *      disk,
91     char *      exin,
92     int         verbose)
93 {
94     int n;
95     int fd;
96     char *filename = NULL;
97     char *afilename = NULL;
98     char *diskname;
99     time_t curtime;
100     char *dbgdir;
101     char *e = NULL;
102     DIR *d;
103     struct dirent *entry;
104     char *test_name;
105     size_t match_len, d_name_len;
106     char *quoted;
107
108     time(&curtime);
109     diskname = sanitise_filename(disk);
110
111     dbgdir = stralloc2(AMANDA_TMPDIR, "/");
112     if((d = opendir(AMANDA_TMPDIR)) == NULL) {
113         error("open debug directory \"%s\": %s",
114                 AMANDA_TMPDIR, strerror(errno));
115         /*NOTREACHED*/
116     }
117     test_name = get_name(diskname, exin,
118                          curtime - (AMANDA_DEBUG_DAYS * 24 * 60 * 60), 0);
119     match_len = strlen(get_pname()) + strlen(diskname) + 2;
120     while((entry = readdir(d)) != NULL) {
121         if(is_dot_or_dotdot(entry->d_name)) {
122             continue;
123         }
124         d_name_len = strlen(entry->d_name);
125         if(strncmp(test_name, entry->d_name, match_len) != 0
126            || d_name_len < match_len + 14 + 8
127            || strcmp(entry->d_name+ d_name_len - 7, exin) != 0) {
128             continue;                           /* not one of our files */
129         }
130         if(strcmp(entry->d_name, test_name) < 0) {
131             e = newvstralloc(e, dbgdir, entry->d_name, NULL);
132             (void) unlink(e);                   /* get rid of old file */
133         }
134     }
135     amfree(test_name);
136     amfree(e);
137     closedir(d);
138
139     n=0;
140     do {
141         filename = get_name(diskname, exin, curtime, n);
142         afilename = newvstralloc(afilename, dbgdir, filename, NULL);
143         if((fd=open(afilename, O_WRONLY|O_CREAT|O_APPEND, 0600)) < 0){
144             amfree(afilename);
145             n++;
146         }
147         else {
148             close(fd);
149         }
150         amfree(filename);
151     } while(!afilename && n < 1000);
152
153     if(afilename == NULL) {
154         filename = get_name(diskname, exin, curtime, 0);
155         afilename = newvstralloc(afilename, dbgdir, filename, NULL);
156         quoted = quote_string(afilename);
157         dbprintf(("%s: Cannot create %s (%s)\n",
158                         debug_prefix_time(NULL), quoted, strerror(errno)));
159         if(verbose) {
160             printf("ERROR [cannot create %s (%s)]\n",
161                         quoted, strerror(errno));
162         }
163         amfree(quoted);
164         amfree(afilename);
165         amfree(filename);
166     }
167
168     amfree(dbgdir);
169     amfree(diskname);
170
171     return afilename;
172 }
173
174
175 static int
176 add_exclude(
177     FILE *      file_exclude,
178     char *      aexc,
179     int         verbose)
180 {
181     size_t l;
182     char *quoted, *file;
183
184     (void)verbose;      /* Quiet unused parameter warning */
185
186     l = strlen(aexc);
187     if(aexc[l-1] == '\n') {
188         aexc[l-1] = '\0';
189         l--;
190     }
191     file = quoted = quote_string(aexc);
192     if (*file == '"') {
193         file[strlen(file) - 1] = '\0';
194         file++;
195     }
196     fprintf(file_exclude, "%s\n", file);
197     amfree(quoted);
198     return 1;
199 }
200
201 static int
202 add_include(
203     char *      disk,
204     char *      device,
205     FILE *      file_include,
206     char *      ainc,
207     int         verbose)
208 {
209     size_t l;
210     int nb_exp=0;
211     char *quoted, *file;
212
213     (void)disk; /* Quiet unused parameter warning */
214
215     l = strlen(ainc);
216     if(ainc[l-1] == '\n') {
217         ainc[l-1] = '\0';
218         l--;
219     }
220     if (strncmp(ainc, "./", 2) != 0) {
221         quoted = quote_string(ainc);
222         dbprintf(("%s: include must start with './' (%s)\n",
223                   debug_prefix_time(NULL), quoted));
224         if(verbose) {
225             printf("ERROR [include must start with './' (%s)]\n", quoted);
226         }
227         amfree(quoted);
228     }
229     else {
230         char *incname = ainc+2;
231
232         if(strchr(incname, '/')) {
233             file = quoted = quote_string(ainc);
234             if (*file == '"') {
235                 file[strlen(file) - 1] = '\0';
236                 file++;
237             }
238             fprintf(file_include, "%s\n", file);
239             amfree(quoted);
240             nb_exp++;
241         }
242         else {
243             char *regex;
244             DIR *d;
245             struct dirent *entry;
246
247             regex = glob_to_regex(incname);
248             if((d = opendir(device)) == NULL) {
249                 quoted = quote_string(device);
250                 dbprintf(("%s: Can't open disk %s\n",
251                       debug_prefix_time(NULL), quoted));
252                 if(verbose) {
253                     printf("ERROR [Can't open disk %s]\n", quoted);
254                 }
255                 amfree(quoted);
256             }
257             else {
258                 while((entry = readdir(d)) != NULL) {
259                     if(is_dot_or_dotdot(entry->d_name)) {
260                         continue;
261                     }
262                     if(match(regex, entry->d_name)) {
263                         incname = vstralloc("./", entry->d_name, NULL);
264                         file = quoted = quote_string(incname);
265                         if (*file == '"') {
266                             file[strlen(file) - 1] = '\0';
267                             file++;
268                         }
269                         fprintf(file_include, "%s\n", file);
270                         amfree(quoted);
271                         amfree(incname);
272                         nb_exp++;
273                     }
274                 }
275                 closedir(d);
276             }
277             amfree(regex);
278         }
279     }
280     return nb_exp;
281 }
282
283 char *
284 build_exclude(
285     char *      disk,
286     char *      device,
287     option_t *  options,
288     int         verbose)
289 {
290     char *filename;
291     FILE *file_exclude;
292     FILE *exclude;
293     char *aexc;
294     sle_t *excl;
295     int nb_exclude = 0;
296     char *quoted;
297
298     if(options->exclude_file) nb_exclude += options->exclude_file->nb_element;
299     if(options->exclude_list) nb_exclude += options->exclude_list->nb_element;
300
301     if(nb_exclude == 0) return NULL;
302
303     if((filename = build_name(disk, "exclude", verbose)) != NULL) {
304         if((file_exclude = fopen(filename,"w")) != NULL) {
305
306             if(options->exclude_file) {
307                 for(excl = options->exclude_file->first; excl != NULL;
308                     excl = excl->next) {
309                     add_exclude(file_exclude, excl->name,
310                                 verbose && options->exclude_optional == 0);
311                 }
312             }
313
314             if(options->exclude_list) {
315                 for(excl = options->exclude_list->first; excl != NULL;
316                     excl = excl->next) {
317                     char *exclname = fixup_relative(excl->name, device);
318                     if((exclude = fopen(exclname, "r")) != NULL) {
319                         while ((aexc = agets(exclude)) != NULL) {
320                             if (aexc[0] == '\0') {
321                                 amfree(aexc);
322                                 continue;
323                             }
324                             add_exclude(file_exclude, aexc,
325                                         verbose && options->exclude_optional == 0);
326                             amfree(aexc);
327                         }
328                         fclose(exclude);
329                     }
330                     else {
331                         quoted = quote_string(exclname);
332                         dbprintf(("%s: Can't open exclude file %s (%s)\n",
333                                   debug_prefix_time(NULL),
334                                   quoted, strerror(errno)));
335                         if(verbose && (options->exclude_optional == 0 ||
336                                        errno != ENOENT)) {
337                             printf("ERROR [Can't open exclude file %s (%s)]\n",
338                                    quoted, strerror(errno));
339                         }
340                         amfree(quoted);
341                     }
342                     amfree(exclname);
343                 }
344             }
345             fclose(file_exclude);
346         }
347         else {
348             quoted = quote_string(filename);
349             dbprintf(("%s: Can't create exclude file %s (%s)\n",
350                       debug_prefix_time(NULL),
351                       quoted, strerror(errno)));
352             if(verbose) {
353                 printf("ERROR [Can't create exclude file %s (%s)]\n",
354                         quoted, strerror(errno));
355             }
356             amfree(quoted);
357         }
358     }
359
360     return filename;
361 }
362
363 char *
364 build_include(
365     char *      disk,
366     char *      device,
367     option_t *  options,
368     int         verbose)
369 {
370     char *filename;
371     FILE *file_include;
372     FILE *include;
373     char *ainc = NULL;
374     sle_t *incl;
375     int nb_include = 0;
376     int nb_exp = 0;
377     char *quoted;
378
379     if(options->include_file) nb_include += options->include_file->nb_element;
380     if(options->include_list) nb_include += options->include_list->nb_element;
381
382     if(nb_include == 0) return NULL;
383
384     if((filename = build_name(disk, "include", verbose)) != NULL) {
385         if((file_include = fopen(filename,"w")) != NULL) {
386
387             if(options->include_file) {
388                 for(incl = options->include_file->first; incl != NULL;
389                     incl = incl->next) {
390                     nb_exp += add_include(disk, device, file_include,
391                                   incl->name,
392                                   verbose && options->include_optional == 0);
393                 }
394             }
395
396             if(options->include_list) {
397                 for(incl = options->include_list->first; incl != NULL;
398                     incl = incl->next) {
399                     char *inclname = fixup_relative(incl->name, device);
400                     if((include = fopen(inclname, "r")) != NULL) {
401                         while ((ainc = agets(include)) != NULL) {
402                             if (ainc[0] == '\0') {
403                                 amfree(ainc);
404                                 continue;
405                             }
406                             nb_exp += add_include(disk, device,
407                                                   file_include, ainc,
408                                                   verbose && options->include_optional == 0);
409                             amfree(ainc);
410                         }
411                         fclose(include);
412                     }
413                     else {
414                         quoted = quote_string(inclname);
415                         dbprintf(("%s: Can't open include file %s (%s)\n",
416                                   debug_prefix_time(NULL), quoted, strerror(errno)));
417                         if(verbose && (options->include_optional == 0 ||
418                                        errno != ENOENT)) {
419                             printf("ERROR [Can't open include file %s (%s)]\n",
420                                    quoted, strerror(errno));
421                         }
422                         amfree(quoted);
423                    }
424                    amfree(inclname);
425                 }
426             }
427             fclose(file_include);
428         }
429         else {
430             quoted = quote_string(filename);
431             dbprintf(("%s: Can't create include file %s (%s)\n",
432                       debug_prefix_time(NULL), quoted, strerror(errno)));
433             if(verbose) {
434                 printf("ERROR [Can't create include file %s (%s)]\n",
435                         quoted, strerror(errno));
436             }
437             amfree(quoted);
438         }
439     }
440         
441     if(nb_exp == 0) {
442         quoted = quote_string(disk);
443         dbprintf(("%s: No include for %s\n", debug_prefix_time(NULL), quoted));
444         if(verbose && options->include_optional == 0) {
445             printf("ERROR [No include for %s]\n", quoted);
446         }
447         amfree(quoted);
448     }
449
450     return filename;
451 }
452
453
454 void
455 init_options(
456     option_t *options)
457 {
458     options->str = NULL;
459     options->compress = COMP_NONE;
460     options->srvcompprog = NULL;
461     options->clntcompprog = NULL;
462     options->encrypt = ENCRYPT_NONE;
463     options->srv_encrypt = NULL;
464     options->clnt_encrypt = NULL;
465     options->srv_decrypt_opt = NULL;
466     options->clnt_decrypt_opt = NULL;
467     options->no_record = 0;
468     options->createindex = 0;
469     options->auth = NULL;
470     options->exclude_file = NULL;
471     options->exclude_list = NULL;
472     options->include_file = NULL;
473     options->include_list = NULL;
474     options->exclude_optional = 0;
475     options->include_optional = 0;
476 }
477
478
479 option_t *
480 parse_options(
481     char *str,
482     char *disk,
483     char *device,
484     am_feature_t *fs,
485     int verbose)
486 {
487     char *exc;
488     char *inc;
489     option_t *options;
490     char *p, *tok;
491     char *quoted;
492
493     (void)disk;         /* Quiet unused parameter warning */
494     (void)device;       /* Quiet unused parameter warning */
495
496     options = alloc(SIZEOF(option_t));
497     init_options(options);
498     options->str = stralloc(str);
499
500     p = stralloc(str);
501     tok = strtok(p,";");
502
503     while (tok != NULL) {
504         if(am_has_feature(fs, fe_options_auth)
505            && BSTRNCMP(tok,"auth=") == 0) {
506             if(options->auth != NULL) {
507                 quoted = quote_string(tok + 5);
508                 dbprintf(("%s: multiple auth option %s\n",
509                           debug_prefix_time(NULL), quoted));
510                 if(verbose) {
511                     printf("ERROR [multiple auth option %s]\n", quoted);
512                 }
513                 amfree(quoted);
514             }
515             options->auth = stralloc(&tok[5]);
516         }
517         else if(am_has_feature(fs, fe_options_bsd_auth)
518            && BSTRNCMP(tok, "bsd-auth") == 0) {
519             if(options->auth != NULL) {
520                 dbprintf(("%s: multiple auth option\n",
521                           debug_prefix_time(NULL)));
522                 if(verbose) {
523                     printf("ERROR [multiple auth option]\n");
524                 }
525             }
526             options->auth = stralloc("bsd");
527         }
528         else if(am_has_feature(fs, fe_options_krb4_auth)
529            && BSTRNCMP(tok, "krb4-auth") == 0) {
530             if(options->auth != NULL) {
531                 dbprintf(("%s: multiple auth option\n",
532                           debug_prefix_time(NULL)));
533                 if(verbose) {
534                     printf("ERROR [multiple auth option]\n");
535                 }
536             }
537             options->auth = stralloc("krb4");
538         }
539         else if(BSTRNCMP(tok, "compress-fast") == 0) {
540             if(options->compress != COMP_NONE) {
541                 dbprintf(("%s: multiple compress option\n",
542                           debug_prefix_time(NULL)));
543                 if(verbose) {
544                     printf("ERROR [multiple compress option]\n");
545                 }
546             }
547             options->compress = COMP_FAST;
548         }
549         else if(BSTRNCMP(tok, "compress-best") == 0) {
550             if(options->compress != COMP_NONE) {
551                 dbprintf(("%s: multiple compress option\n",
552                           debug_prefix_time(NULL)));
553                 if(verbose) {
554                     printf("ERROR [multiple compress option]\n");
555                 }
556             }
557             options->compress = COMP_BEST;
558         }
559         else if(BSTRNCMP(tok, "srvcomp-fast") == 0) {
560             if(options->compress != COMP_NONE) {
561                 dbprintf(("%s: multiple compress option\n",
562                           debug_prefix_time(NULL)));
563                 if(verbose) {
564                     printf("ERROR [multiple compress option]\n");
565                 }
566             }
567             options->compress = COMP_SERVER_FAST;
568         }
569         else if(BSTRNCMP(tok, "srvcomp-best") == 0) {
570             if(options->compress != COMP_NONE) {
571                 dbprintf(("%s: multiple compress option\n",
572                           debug_prefix_time(NULL)));
573                 if(verbose) {
574                     printf("ERROR [multiple compress option]\n");
575                 }
576             }
577             options->compress = COMP_SERVER_BEST;
578         }
579         else if(BSTRNCMP(tok, "srvcomp-cust=") == 0) {
580             if(options->compress != COMP_NONE) {
581                 dbprintf(("%s: multiple compress option\n", 
582                           debug_prefix_time(NULL)));
583                 if(verbose) {
584                     printf("ERROR [multiple compress option]\n");
585                 }
586             }
587             options->srvcompprog = stralloc(tok + SIZEOF("srvcomp-cust=") -1);
588             options->compress = COMP_SERVER_CUST;
589         }
590         else if(BSTRNCMP(tok, "comp-cust=") == 0) {
591             if(options->compress != COMP_NONE) {
592                 dbprintf(("%s: multiple compress option\n", 
593                           debug_prefix_time(NULL)));
594                 if(verbose) {
595                     printf("ERROR [multiple compress option]\n");
596                 }
597             }
598             options->clntcompprog = stralloc(tok + SIZEOF("comp-cust=") -1);
599             options->compress = COMP_CUST;
600             /* parse encryption options */
601         } 
602         else if(BSTRNCMP(tok, "encrypt-serv-cust=") == 0) {
603             if(options->encrypt != ENCRYPT_NONE) {
604                 dbprintf(("%s: multiple encrypt option\n", 
605                           debug_prefix_time(NULL)));
606                 if(verbose) {
607                     printf("ERROR [multiple encrypt option]\n");
608                 }
609             }
610             options->srv_encrypt = stralloc(tok + SIZEOF("encrypt-serv-cust=") -1);
611             options->encrypt = ENCRYPT_SERV_CUST;
612         } 
613         else if(BSTRNCMP(tok, "encrypt-cust=") == 0) {
614             if(options->encrypt != ENCRYPT_NONE) {
615                 dbprintf(("%s: multiple encrypt option\n", 
616                           debug_prefix_time(NULL)));
617                 if(verbose) {
618                     printf("ERROR [multiple encrypt option]\n");
619                 }
620             }
621             options->clnt_encrypt= stralloc(tok + SIZEOF("encrypt-cust=") -1);
622             options->encrypt = ENCRYPT_CUST;
623         } 
624         else if(BSTRNCMP(tok, "server-decrypt-option=") == 0) {
625           options->srv_decrypt_opt = stralloc(tok + SIZEOF("server-decrypt-option=") -1);
626         }
627         else if(BSTRNCMP(tok, "client-decrypt-option=") == 0) {
628           options->clnt_decrypt_opt = stralloc(tok + SIZEOF("client-decrypt-option=") -1);
629         }
630         else if(BSTRNCMP(tok, "no-record") == 0) {
631             if(options->no_record != 0) {
632                 dbprintf(("%s: multiple no-record option\n",
633                           debug_prefix_time(NULL)));
634                 if(verbose) {
635                     printf("ERROR [multiple no-record option]\n");
636                 }
637             }
638             options->no_record = 1;
639         }
640         else if(BSTRNCMP(tok, "index") == 0) {
641             if(options->createindex != 0) {
642                 dbprintf(("%s: multiple index option\n",
643                           debug_prefix_time(NULL)));
644                 if(verbose) {
645                     printf("ERROR [multiple index option]\n");
646                 }
647             }
648             options->createindex = 1;
649         }
650         else if(BSTRNCMP(tok, "exclude-optional") == 0) {
651             if(options->exclude_optional != 0) {
652                 dbprintf(("%s: multiple exclude-optional option\n",
653                           debug_prefix_time(NULL)));
654                 if(verbose) {
655                     printf("ERROR [multiple exclude-optional option]\n");
656                 }
657             }
658             options->exclude_optional = 1;
659         }
660         else if(strcmp(tok, "include-optional") == 0) {
661             if(options->include_optional != 0) {
662                 dbprintf(("%s: multiple include-optional option\n",
663                           debug_prefix_time(NULL)));
664                 if(verbose) {
665                     printf("ERROR [multiple include-optional option]\n");
666                 }
667             }
668             options->include_optional = 1;
669         }
670         else if(BSTRNCMP(tok,"exclude-file=") == 0) {
671             exc = unquote_string(&tok[13]);
672             options->exclude_file = append_sl(options->exclude_file, exc);
673             amfree(exc);
674         }
675         else if(BSTRNCMP(tok,"exclude-list=") == 0) {
676             exc = unquote_string(&tok[13]);
677             options->exclude_list = append_sl(options->exclude_list, exc);
678             amfree(exc);
679         }
680         else if(BSTRNCMP(tok,"include-file=") == 0) {
681             inc = unquote_string(&tok[13]);
682             options->include_file = append_sl(options->include_file, inc);
683             amfree(inc);
684         }
685         else if(BSTRNCMP(tok,"include-list=") == 0) {
686             inc = unquote_string(&tok[13]);
687             options->include_list = append_sl(options->include_list, inc);
688             amfree(inc);
689         }
690         else if(strcmp(tok,"|") != 0) {
691             quoted = quote_string(tok);
692             dbprintf(("%s: unknown option %s\n",
693                         debug_prefix_time(NULL), quoted));
694             if(verbose) {
695                 printf("ERROR [unknown option: %s]\n", quoted);
696             }
697             amfree(quoted);
698         }
699         tok = strtok(NULL, ";");
700     }
701     amfree(p);
702     return options;
703 }
704
705 void
706 output_tool_property(
707     FILE     *tool,
708     option_t *options)
709 {
710     sle_t *sle;
711     char *q;
712
713     if (!is_empty_sl(options->exclude_file)) {
714         for(sle = options->exclude_file->first ; sle != NULL; sle=sle->next) {
715             q = quote_string(sle->name);
716             fprintf(tool, "EXCLUDE-FILE %s\n", q);
717             amfree(q);
718         }
719     }
720
721     if (!is_empty_sl(options->exclude_list)) {
722         for(sle = options->exclude_list->first ; sle != NULL; sle=sle->next) {
723             q = quote_string(sle->name);
724             fprintf(tool, "EXCLUDE-LIST %s\n", q);
725             amfree(q);
726         }
727     }
728
729     if (!is_empty_sl(options->include_file)) {
730         for(sle = options->include_file->first ; sle != NULL; sle=sle->next) {
731             q = quote_string(sle->name);
732             fprintf(tool, "INCLUDE-FILE %s\n", q);
733             amfree(q);
734         }
735     }
736
737     if (!is_empty_sl(options->include_list)) {
738         for(sle = options->include_list->first ; sle != NULL; sle=sle->next) {
739             q = quote_string(sle->name);
740             fprintf(tool, "INCLUDE-LIST %s\n", q);
741             amfree(q);
742         }
743     }
744
745     if (!is_empty_sl(options->exclude_file) ||
746         !is_empty_sl(options->exclude_list)) {
747         if (options->exclude_optional)
748             fprintf(tool, "EXCLUDE-OPTIONAL YES\n");
749         else
750             fprintf(tool, "EXCLUDE-OPTIONAL NO\n");
751     }
752
753     if (!is_empty_sl(options->include_file) ||
754         !is_empty_sl(options->include_list)) {
755         if (options->include_optional)
756             fprintf(tool, "INCLUDE-OPTIONAL YES\n");
757         else
758             fprintf(tool, "INCLUDE-OPTIONAL NO\n");
759     }
760 }
761
762 backup_support_option_t *
763 backup_support_option(
764     char       *program,
765     g_option_t *g_options,
766     char       *disk,
767     char       *amdevice)
768 {
769     pid_t   supportpid;
770     int     supportin, supportout, supporterr;
771     char   *cmd;
772     char  **argvchild;
773     int     i;
774     FILE   *streamout;
775     char   *line;
776     backup_support_option_t *bsu;
777
778     cmd = vstralloc(DUMPER_DIR, "/", program, NULL);
779     argvchild = malloc(5 * SIZEOF(char *));
780     i = 0;
781     argvchild[i++] = program;
782     argvchild[i++] = "support";
783     if (g_options->config) {
784         argvchild[i++] = "--config";
785         argvchild[i++] = g_options->config;
786     }
787     if (g_options->hostname) {
788         argvchild[i++] = "--host";
789         argvchild[i++] = g_options->hostname;
790     }
791     if (disk) {
792         argvchild[i++] = "--disk";
793         argvchild[i++] = disk;
794     }
795     if (amdevice) {
796         argvchild[i++] = "--device";
797         argvchild[i++] = amdevice;
798     }
799     argvchild[i++] = NULL;
800
801     supporterr = fileno(stderr);
802     supportpid = pipespawnv(cmd, STDIN_PIPE|STDOUT_PIPE, &supportin,
803                             &supportout, &supporterr, argvchild);
804
805     aclose(supportin);
806
807     bsu = malloc(SIZEOF(*bsu));
808     memset(bsu, '\0', SIZEOF(*bsu));
809     streamout = fdopen(supportout, "r");
810     while((line = agets(streamout)) != NULL) {
811         dbprintf(("support line: %s\n", line));
812         if (strncmp(line,"CONFIG ", 7) == 0) {
813             if (strcmp(line+7, "YES") == 0)
814                 bsu->config = 1;
815         } else if (strncmp(line,"HOST ", 5) == 0) {
816             if (strcmp(line+5, "YES") == 0)
817             bsu->host = 1;
818         } else if (strncmp(line,"DISK ", 5) == 0) {
819             if (strcmp(line+5, "YES") == 0)
820                 bsu->host = 1;
821         } else if (strncmp(line,"INDEX-LINE ", 11) == 0) {
822             if (strcmp(line+11, "YES") == 0)
823                 bsu->index_line = 1;
824         } else if (strncmp(line,"INDEX-XML ", 10) == 0) {
825             if (strcmp(line+10, "YES") == 0)
826                 bsu->index_xml = 1;
827         } else if (strncmp(line,"MESSAGE-LINE ", 13) == 0) {
828             if (strcmp(line+13, "YES") == 0)
829                 bsu->message_line = 1;
830         } else if (strncmp(line,"MESSAGE-XML ", 12) == 0) {
831             if (strcmp(line+12, "YES") == 0)
832                 bsu->message_xml = 1;
833         } else if (strncmp(line,"RECORD ", 7) == 0) {
834             if (strcmp(line+7, "YES") == 0)
835                 bsu->record = 1;
836         } else if (strncmp(line,"INCLUDE-FILE ", 13) == 0) {
837             if (strcmp(line+13, "YES") == 0)
838                 bsu->include_file = 1;
839         } else if (strncmp(line,"INCLUDE-LIST ", 13) == 0) {
840             if (strcmp(line+13, "YES") == 0)
841                 bsu->include_list = 1;
842         } else if (strncmp(line,"EXCLUDE-FILE ", 13) == 0) {
843             if (strcmp(line+13, "YES") == 0)
844                 bsu->exclude_file = 1;
845         } else if (strncmp(line,"EXCLUDE-LIST ", 13) == 0) {
846             if (strcmp(line+13, "YES") == 0)
847                 bsu->exclude_list = 1;
848         } else if (strncmp(line,"COLLECTION ", 11) == 0) {
849             if (strcmp(line+11, "YES") == 0)
850                 bsu->collection = 1;
851         } else if (strncmp(line,"MAX-LEVEL ", 10) == 0) {
852             bsu->max_level  = atoi(line+10);
853         } else {
854             dbprintf(("Invalid support line: %s\n", line));
855         }
856         amfree(line);
857     }
858     aclose(supportout);
859
860     return NULL;
861 }
862