X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=client-src%2Fclient_util.c;h=ef28c1a87ed0e881a69b9d76e2fb569cf97d0e2e;hb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;hp=71ce4b4c6443c8152d97fb176b4b10bdfb4b6db4;hpb=12179dea039515c06168c0037d048566a3f623de;p=debian%2Famanda diff --git a/client-src/client_util.c b/client-src/client_util.c index 71ce4b4..ef28c1a 100644 --- a/client-src/client_util.c +++ b/client-src/client_util.c @@ -29,9 +29,18 @@ */ #include "amanda.h" +#include "conffile.h" #include "client_util.h" #include "getfsent.h" #include "util.h" +#include "glib-util.h" +#include "timestamp.h" +#include "pipespawn.h" +#include "amxml.h" +#include "glob.h" +#include "clock.h" +#include "amandates.h" +#include "version.h" #define MAXMAXDUMPS 16 @@ -70,11 +79,11 @@ get_name( char *filename; char *ts; - ts = construct_timestamp(&t); + ts = get_timestamp_from_time(t); if(n == 0) number[0] = '\0'; else - snprintf(number, SIZEOF(number), "%03d", n - 1); + g_snprintf(number, SIZEOF(number), "%03d", n - 1); filename = vstralloc(get_pname(), ".", diskname, ".", ts, number, ".", exin, NULL); @@ -108,7 +117,7 @@ build_name( dbgdir = stralloc2(AMANDA_TMPDIR, "/"); if((d = opendir(AMANDA_TMPDIR)) == NULL) { - error("open debug directory \"%s\": %s", + error(_("open debug directory \"%s\": %s"), AMANDA_TMPDIR, strerror(errno)); /*NOTREACHED*/ } @@ -152,10 +161,9 @@ build_name( filename = get_name(diskname, exin, curtime, 0); afilename = newvstralloc(afilename, dbgdir, filename, NULL); quoted = quote_string(afilename); - dbprintf(("%s: Cannot create %s (%s)\n", - debug_prefix(NULL), quoted, strerror(errno))); + dbprintf(_("Cannot create %s (%s)\n"), quoted, strerror(errno)); if(verbose) { - printf("ERROR [cannot create %s (%s)]\n", + g_printf(_("ERROR [cannot create %s (%s)]\n"), quoted, strerror(errno)); } amfree(quoted); @@ -191,7 +199,7 @@ add_exclude( file[strlen(file) - 1] = '\0'; file++; } - fprintf(file_exclude, "%s\n", file); + g_fprintf(file_exclude, "%s\n", file); amfree(quoted); return 1; } @@ -208,7 +216,8 @@ add_include( int nb_exp=0; char *quoted, *file; - (void)disk; /* Quiet unused parameter warning */ + (void)disk; /* Quiet unused parameter warning */ + (void)device; /* Quiet unused parameter warning */ l = strlen(ainc); if(ainc[l-1] == '\n') { @@ -217,62 +226,57 @@ add_include( } if (strncmp(ainc, "./", 2) != 0) { quoted = quote_string(ainc); - dbprintf(("%s: include must start with './' (%s)\n", - debug_prefix(NULL), quoted)); + dbprintf(_("include must start with './' (%s)\n"), quoted); if(verbose) { - printf("ERROR [include must start with './' (%s)]\n", quoted); + g_printf(_("ERROR [include must start with './' (%s)]\n"), quoted); } amfree(quoted); } else { char *incname = ainc+2; + int set_root; - if(strchr(incname, '/')) { + set_root = set_root_privs(1); + /* Take as is if not root && many '/' */ + if(!set_root && strchr(incname, '/')) { file = quoted = quote_string(ainc); if (*file == '"') { file[strlen(file) - 1] = '\0'; file++; } - fprintf(file_include, "%s\n", file); + g_fprintf(file_include, "%s\n", file); amfree(quoted); nb_exp++; } else { - char *regex; - DIR *d; - struct dirent *entry; - - regex = glob_to_regex(incname); - if((d = opendir(device)) == NULL) { - quoted = quote_string(device); - dbprintf(("%s: Can't open disk %s\n", - debug_prefix(NULL), quoted)); - if(verbose) { - printf("ERROR [Can't open disk %s]\n", quoted); - } - amfree(quoted); + int nb; + glob_t globbuf; + char *cwd; + + globbuf.gl_offs = 0; + + cwd = g_get_current_dir(); + if (chdir(device) != 0) { + error(_("Failed to chdir(%s): %s\n"), device, strerror(errno)); } - else { - while((entry = readdir(d)) != NULL) { - if(is_dot_or_dotdot(entry->d_name)) { - continue; - } - if(match(regex, entry->d_name)) { - incname = vstralloc("./", entry->d_name, NULL); - file = quoted = quote_string(incname); - if (*file == '"') { - file[strlen(file) - 1] = '\0'; - file++; - } - fprintf(file_include, "%s\n", file); - amfree(quoted); - amfree(incname); - nb_exp++; - } + glob(incname, 0, NULL, &globbuf); + if (chdir(cwd) != 0) { + error(_("Failed to chdir(%s): %s\n"), cwd, strerror(errno)); + } + if (set_root) + set_root_privs(0); + nb_exp = globbuf.gl_pathc; + for (nb=0; nb < nb_exp; nb++) { + file = stralloc2("./", globbuf.gl_pathv[nb]); + quoted = quote_string(file); + if (*file == '"') { + file[strlen(file) - 1] = '\0'; + file++; } - closedir(d); + g_fprintf(file_include, "%s\n", file); + amfree(quoted); + amfree(file); } - amfree(regex); } } return nb_exp; @@ -280,10 +284,8 @@ add_include( char * build_exclude( - char * disk, - char * device, - option_t * options, - int verbose) + dle_t *dle, + int verbose) { char *filename; FILE *file_exclude; @@ -293,26 +295,26 @@ build_exclude( int nb_exclude = 0; char *quoted; - if(options->exclude_file) nb_exclude += options->exclude_file->nb_element; - if(options->exclude_list) nb_exclude += options->exclude_list->nb_element; + if (dle->exclude_file) nb_exclude += dle->exclude_file->nb_element; + if (dle->exclude_list) nb_exclude += dle->exclude_list->nb_element; - if(nb_exclude == 0) return NULL; + if (nb_exclude == 0) return NULL; - if((filename = build_name(disk, "exclude", verbose)) != NULL) { - if((file_exclude = fopen(filename,"w")) != NULL) { + if ((filename = build_name(dle->disk, "exclude", verbose)) != NULL) { + if ((file_exclude = fopen(filename,"w")) != NULL) { - if(options->exclude_file) { - for(excl = options->exclude_file->first; excl != NULL; + if (dle->exclude_file) { + for(excl = dle->exclude_file->first; excl != NULL; excl = excl->next) { add_exclude(file_exclude, excl->name, - verbose && options->exclude_optional == 0); + verbose && dle->exclude_optional == 0); } } - if(options->exclude_list) { - for(excl = options->exclude_list->first; excl != NULL; + if (dle->exclude_list) { + for(excl = dle->exclude_list->first; excl != NULL; excl = excl->next) { - char *exclname = fixup_relative(excl->name, device); + char *exclname = fixup_relative(excl->name, dle->device); if((exclude = fopen(exclname, "r")) != NULL) { while ((aexc = agets(exclude)) != NULL) { if (aexc[0] == '\0') { @@ -320,19 +322,18 @@ build_exclude( continue; } add_exclude(file_exclude, aexc, - verbose && options->exclude_optional == 0); + verbose && dle->exclude_optional == 0); amfree(aexc); } fclose(exclude); } else { quoted = quote_string(exclname); - dbprintf(("%s: Can't open exclude file %s (%s)\n", - debug_prefix(NULL), - quoted, strerror(errno))); - if(verbose && (options->exclude_optional == 0 || + dbprintf(_("Can't open exclude file %s (%s)\n"), + quoted, strerror(errno)); + if(verbose && (dle->exclude_optional == 0 || errno != ENOENT)) { - printf("ERROR [Can't open exclude file %s (%s)]\n", + g_printf(_("ERROR [Can't open exclude file %s (%s)]\n"), quoted, strerror(errno)); } amfree(quoted); @@ -341,14 +342,12 @@ build_exclude( } } fclose(file_exclude); - } - else { + } else { quoted = quote_string(filename); - dbprintf(("%s: Can't create exclude file %s (%s)\n", - debug_prefix(NULL), - quoted, strerror(errno))); - if(verbose) { - printf("ERROR [Can't create exclude file %s (%s)]\n", + dbprintf(_("Can't create exclude file %s (%s)\n"), + quoted, strerror(errno)); + if (verbose) { + g_printf(_("ERROR [Can't create exclude file %s (%s)]\n"), quoted, strerror(errno)); } amfree(quoted); @@ -360,10 +359,8 @@ build_exclude( char * build_include( - char * disk, - char * device, - option_t * options, - int verbose) + dle_t *dle, + int verbose) { char *filename; FILE *file_include; @@ -374,47 +371,47 @@ build_include( int nb_exp = 0; char *quoted; - if(options->include_file) nb_include += options->include_file->nb_element; - if(options->include_list) nb_include += options->include_list->nb_element; + if (dle->include_file) nb_include += dle->include_file->nb_element; + if (dle->include_list) nb_include += dle->include_list->nb_element; - if(nb_include == 0) return NULL; + if (nb_include == 0) return NULL; - if((filename = build_name(disk, "include", verbose)) != NULL) { - if((file_include = fopen(filename,"w")) != NULL) { + if ((filename = build_name(dle->disk, "include", verbose)) != NULL) { + if ((file_include = fopen(filename,"w")) != NULL) { - if(options->include_file) { - for(incl = options->include_file->first; incl != NULL; + if (dle->include_file) { + for (incl = dle->include_file->first; incl != NULL; incl = incl->next) { - nb_exp += add_include(disk, device, file_include, + nb_exp += add_include(dle->disk, dle->device, file_include, incl->name, - verbose && options->include_optional == 0); + verbose && dle->include_optional == 0); } } - if(options->include_list) { - for(incl = options->include_list->first; incl != NULL; + if (dle->include_list) { + for (incl = dle->include_list->first; incl != NULL; incl = incl->next) { - char *inclname = fixup_relative(incl->name, device); - if((include = fopen(inclname, "r")) != NULL) { + char *inclname = fixup_relative(incl->name, dle->device); + if ((include = fopen(inclname, "r")) != NULL) { while ((ainc = agets(include)) != NULL) { if (ainc[0] == '\0') { amfree(ainc); continue; } - nb_exp += add_include(disk, device, + nb_exp += add_include(dle->disk, dle->device, file_include, ainc, - verbose && options->include_optional == 0); + verbose && dle->include_optional == 0); amfree(ainc); } fclose(include); } else { quoted = quote_string(inclname); - dbprintf(("%s: Can't open include file %s (%s)\n", - debug_prefix(NULL), quoted, strerror(errno))); - if(verbose && (options->include_optional == 0 || + dbprintf(_("Can't open include file %s (%s)\n"), + quoted, strerror(errno)); + if (verbose && (dle->include_optional == 0 || errno != ENOENT)) { - printf("ERROR [Can't open include file %s (%s)]\n", + g_printf(_("ERROR [Can't open include file %s (%s)]\n"), quoted, strerror(errno)); } amfree(quoted); @@ -423,24 +420,23 @@ build_include( } } fclose(file_include); - } - else { + } else { quoted = quote_string(filename); - dbprintf(("%s: Can't create include file %s (%s)\n", - debug_prefix(NULL), quoted, strerror(errno))); - if(verbose) { - printf("ERROR [Can't create include file %s (%s)]\n", + dbprintf(_("Can't create include file %s (%s)\n"), + quoted, strerror(errno)); + if (verbose) { + g_printf(_("ERROR [Can't create include file %s (%s)]\n"), quoted, strerror(errno)); } amfree(quoted); } } - if(nb_exp == 0) { - quoted = quote_string(disk); - dbprintf(("%s: No include for %s\n", debug_prefix(NULL), quoted)); - if(verbose && options->include_optional == 0) { - printf("ERROR [No include for %s]\n", quoted); + if (nb_exp == 0) { + quoted = quote_string(dle->disk); + dbprintf(_("No include for %s\n"), quoted); + if (verbose && dle->include_optional == 0) { + g_printf(_("ERROR [No include for %s]\n"), quoted); } amfree(quoted); } @@ -450,252 +446,1092 @@ build_include( void -init_options( - option_t *options) -{ - options->str = NULL; - options->compress = NO_COMPR; - options->srvcompprog = NULL; - options->clntcompprog = NULL; - options->encrypt = ENCRYPT_NONE; - options->srv_encrypt = NULL; - options->clnt_encrypt = NULL; - options->srv_decrypt_opt = NULL; - options->clnt_decrypt_opt = NULL; - options->no_record = 0; - options->createindex = 0; - options->auth = NULL; - options->exclude_file = NULL; - options->exclude_list = NULL; - options->include_file = NULL; - options->include_list = NULL; - options->exclude_optional = 0; - options->include_optional = 0; -} - - -option_t * parse_options( - char *str, - char *disk, - char *device, + char *str, + dle_t *dle, am_feature_t *fs, - int verbose) + int verbose) { char *exc; char *inc; - option_t *options; char *p, *tok; char *quoted; - (void)disk; /* Quiet unused parameter warning */ - (void)device; /* Quiet unused parameter warning */ - - options = alloc(SIZEOF(option_t)); - init_options(options); - options->str = stralloc(str); - p = stralloc(str); tok = strtok(p,";"); while (tok != NULL) { if(am_has_feature(fs, fe_options_auth) && BSTRNCMP(tok,"auth=") == 0) { - if(options->auth != NULL) { + if (dle->auth != NULL) { quoted = quote_string(tok + 5); - dbprintf(("%s: multiple auth option %s\n", - debug_prefix(NULL), quoted)); + dbprintf(_("multiple auth option %s\n"), quoted); if(verbose) { - printf("ERROR [multiple auth option %s]\n", quoted); + g_printf(_("ERROR [multiple auth option %s]\n"), quoted); } amfree(quoted); } - options->auth = stralloc(&tok[5]); + dle->auth = stralloc(&tok[5]); } else if(am_has_feature(fs, fe_options_bsd_auth) && BSTRNCMP(tok, "bsd-auth") == 0) { - if(options->auth != NULL) { - dbprintf(("%s: multiple auth option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple auth option]\n"); + if (dle->auth != NULL) { + dbprintf(_("multiple auth option\n")); + if (verbose) { + g_printf(_("ERROR [multiple auth option]\n")); } } - options->auth = stralloc("bsd"); + dle->auth = stralloc("bsd"); } - else if(am_has_feature(fs, fe_options_krb4_auth) + else if (am_has_feature(fs, fe_options_krb4_auth) && BSTRNCMP(tok, "krb4-auth") == 0) { - if(options->auth != NULL) { - dbprintf(("%s: multiple auth option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple auth option]\n"); + if (dle->auth != NULL) { + dbprintf(_("multiple auth option\n")); + if (verbose) { + g_printf(_("ERROR [multiple auth option]\n")); } } - options->auth = stralloc("krb4"); + dle->auth = stralloc("krb4"); } - else if(BSTRNCMP(tok, "compress-fast") == 0) { - if(options->compress != NO_COMPR) { - dbprintf(("%s: multiple compress option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple compress option]\n"); + else if (BSTRNCMP(tok, "compress-fast") == 0) { + if (dle->compress != COMP_NONE) { + dbprintf(_("multiple compress option\n")); + if (verbose) { + g_printf(_("ERROR [multiple compress option]\n")); } } - options->compress = COMPR_FAST; + dle->compress = COMP_FAST; } - else if(BSTRNCMP(tok, "compress-best") == 0) { - if(options->compress != NO_COMPR) { - dbprintf(("%s: multiple compress option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple compress option]\n"); + else if (BSTRNCMP(tok, "compress-best") == 0) { + if (dle->compress != COMP_NONE) { + dbprintf(_("multiple compress option\n")); + if (verbose) { + g_printf(_("ERROR [multiple compress option]\n")); } } - options->compress = COMPR_BEST; + dle->compress = COMP_BEST; } - else if(BSTRNCMP(tok, "srvcomp-fast") == 0) { - if(options->compress != NO_COMPR) { - dbprintf(("%s: multiple compress option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple compress option]\n"); + else if (BSTRNCMP(tok, "srvcomp-fast") == 0) { + if (dle->compress != COMP_NONE) { + dbprintf(_("multiple compress option\n")); + if (verbose) { + g_printf(_("ERROR [multiple compress option]\n")); } } - options->compress = COMPR_SERVER_FAST; + dle->compress = COMP_SERVER_FAST; } - else if(BSTRNCMP(tok, "srvcomp-best") == 0) { - if(options->compress != NO_COMPR) { - dbprintf(("%s: multiple compress option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple compress option]\n"); + else if (BSTRNCMP(tok, "srvcomp-best") == 0) { + if (dle->compress != COMP_NONE) { + dbprintf(_("multiple compress option\n")); + if (verbose) { + g_printf(_("ERROR [multiple compress option]\n")); } } - options->compress = COMPR_SERVER_BEST; + dle->compress = COMP_SERVER_BEST; } - else if(BSTRNCMP(tok, "srvcomp-cust=") == 0) { - if(options->compress != NO_COMPR) { - dbprintf(("%s: multiple compress option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple compress option]\n"); + else if (BSTRNCMP(tok, "srvcomp-cust=") == 0) { + if (dle->compress != COMP_NONE) { + dbprintf(_("multiple compress option\n")); + if (verbose) { + g_printf(_("ERROR [multiple compress option]\n")); } } - options->srvcompprog = stralloc(tok + SIZEOF("srvcomp-cust=") -1); - options->compress = COMPR_SERVER_CUST; + dle->compprog = stralloc(tok + SIZEOF("srvcomp-cust=") -1); + dle->compress = COMP_SERVER_CUST; } - else if(BSTRNCMP(tok, "comp-cust=") == 0) { - if(options->compress != NO_COMPR) { - dbprintf(("%s: multiple compress option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple compress option]\n"); + else if (BSTRNCMP(tok, "comp-cust=") == 0) { + if (dle->compress != COMP_NONE) { + dbprintf(_("multiple compress option\n")); + if (verbose) { + g_printf(_("ERROR [multiple compress option]\n")); } } - options->clntcompprog = stralloc(tok + SIZEOF("comp-cust=") -1); - options->compress = COMPR_CUST; + dle->compprog = stralloc(tok + SIZEOF("comp-cust=") -1); + dle->compress = COMP_CUST; /* parse encryption options */ } - else if(BSTRNCMP(tok, "encrypt-serv-cust=") == 0) { - if(options->encrypt != ENCRYPT_NONE) { - dbprintf(("%s: multiple encrypt option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple encrypt option]\n"); + else if (BSTRNCMP(tok, "encrypt-serv-cust=") == 0) { + if (dle->encrypt != ENCRYPT_NONE) { + dbprintf(_("multiple encrypt option\n")); + if (verbose) { + g_printf(_("ERROR [multiple encrypt option]\n")); } } - options->srv_encrypt = stralloc(tok + SIZEOF("encrypt-serv-cust=") -1); - options->encrypt = ENCRYPT_SERV_CUST; + dle->srv_encrypt = stralloc(tok + SIZEOF("encrypt-serv-cust=") -1); + dle->encrypt = ENCRYPT_SERV_CUST; } - else if(BSTRNCMP(tok, "encrypt-cust=") == 0) { - if(options->encrypt != ENCRYPT_NONE) { - dbprintf(("%s: multiple encrypt option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple encrypt option]\n"); + else if (BSTRNCMP(tok, "encrypt-cust=") == 0) { + if (dle->encrypt != ENCRYPT_NONE) { + dbprintf(_("multiple encrypt option\n")); + if (verbose) { + g_printf(_("ERROR [multiple encrypt option]\n")); } } - options->clnt_encrypt= stralloc(tok + SIZEOF("encrypt-cust=") -1); - options->encrypt = ENCRYPT_CUST; + dle->clnt_encrypt= stralloc(tok + SIZEOF("encrypt-cust=") -1); + dle->encrypt = ENCRYPT_CUST; } - else if(BSTRNCMP(tok, "server-decrypt-option=") == 0) { - options->srv_decrypt_opt = stralloc(tok + SIZEOF("server-decrypt-option=") -1); + else if (BSTRNCMP(tok, "server-decrypt-option=") == 0) { + dle->srv_decrypt_opt = stralloc(tok + SIZEOF("server-decrypt-option=") -1); } - else if(BSTRNCMP(tok, "client-decrypt-option=") == 0) { - options->clnt_decrypt_opt = stralloc(tok + SIZEOF("client-decrypt-option=") -1); + else if (BSTRNCMP(tok, "client-decrypt-option=") == 0) { + dle->clnt_decrypt_opt = stralloc(tok + SIZEOF("client-decrypt-option=") -1); } - else if(BSTRNCMP(tok, "no-record") == 0) { - if(options->no_record != 0) { - dbprintf(("%s: multiple no-record option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple no-record option]\n"); + else if (BSTRNCMP(tok, "no-record") == 0) { + if (dle->record != 1) { + dbprintf(_("multiple no-record option\n")); + if (verbose) { + g_printf(_("ERROR [multiple no-record option]\n")); } } - options->no_record = 1; + dle->record = 0; } - else if(BSTRNCMP(tok, "index") == 0) { - if(options->createindex != 0) { - dbprintf(("%s: multiple index option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple index option]\n"); + else if (BSTRNCMP(tok, "index") == 0) { + if (dle->create_index != 0) { + dbprintf(_("multiple index option\n")); + if (verbose) { + g_printf(_("ERROR [multiple index option]\n")); } } - options->createindex = 1; + dle->create_index = 1; } - else if(BSTRNCMP(tok, "exclude-optional") == 0) { - if(options->exclude_optional != 0) { - dbprintf(("%s: multiple exclude-optional option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple exclude-optional option]\n"); + else if (BSTRNCMP(tok, "exclude-optional") == 0) { + if (dle->exclude_optional != 0) { + dbprintf(_("multiple exclude-optional option\n")); + if (verbose) { + g_printf(_("ERROR [multiple exclude-optional option]\n")); } } - options->exclude_optional = 1; + dle->exclude_optional = 1; } - else if(strcmp(tok, "include-optional") == 0) { - if(options->include_optional != 0) { - dbprintf(("%s: multiple include-optional option\n", - debug_prefix(NULL))); - if(verbose) { - printf("ERROR [multiple include-optional option]\n"); + else if (strcmp(tok, "include-optional") == 0) { + if (dle->include_optional != 0) { + dbprintf(_("multiple include-optional option\n")); + if (verbose) { + g_printf(_("ERROR [multiple include-optional option]\n")); } } - options->include_optional = 1; + dle->include_optional = 1; } - else if(BSTRNCMP(tok,"exclude-file=") == 0) { + else if (BSTRNCMP(tok,"exclude-file=") == 0) { exc = unquote_string(&tok[13]); - options->exclude_file = append_sl(options->exclude_file, exc); + dle->exclude_file = append_sl(dle->exclude_file, exc); amfree(exc); } - else if(BSTRNCMP(tok,"exclude-list=") == 0) { + else if (BSTRNCMP(tok,"exclude-list=") == 0) { exc = unquote_string(&tok[13]); - options->exclude_list = append_sl(options->exclude_list, exc); + dle->exclude_list = append_sl(dle->exclude_list, exc); amfree(exc); } - else if(BSTRNCMP(tok,"include-file=") == 0) { + else if (BSTRNCMP(tok,"include-file=") == 0) { inc = unquote_string(&tok[13]); - options->include_file = append_sl(options->include_file, inc); + dle->include_file = append_sl(dle->include_file, inc); amfree(inc); } - else if(BSTRNCMP(tok,"include-list=") == 0) { + else if (BSTRNCMP(tok,"include-list=") == 0) { inc = unquote_string(&tok[13]); - options->include_list = append_sl(options->include_list, inc); + dle->include_list = append_sl(dle->include_list, inc); amfree(inc); } - else if(strcmp(tok,"|") != 0) { + else if (BSTRNCMP(tok,"kencrypt") == 0) { + dle->kencrypt = 1; + } + else if (strcmp(tok,"|") != 0) { quoted = quote_string(tok); - dbprintf(("%s: unknown option %s\n", - debug_prefix(NULL), quoted)); - if(verbose) { - printf("ERROR [unknown option: %s]\n", quoted); + dbprintf(_("unknown option %s\n"), quoted); + if (verbose) { + g_printf(_("ERROR [unknown option: %s]\n"), quoted); } amfree(quoted); } tok = strtok(NULL, ";"); } amfree(p); - return options; +} + +int +application_property_argv_size(dle_t *dle) { + int nb; + + nb = 0; + if (dle->include_list) + nb += dle->include_list->nb_element; + if (dle->include_file) + nb += dle->include_file->nb_element; + nb++; /* include optional */ + if (dle->exclude_list) + nb += dle->exclude_list->nb_element; + if (dle->exclude_file) + nb += dle->exclude_file->nb_element; + nb++; /* exclude optional */ + nb *= 2; /*name + value */ + nb += property_argv_size(dle->application_property); + + return nb; +} + +int +application_property_add_to_argv( + char **argvchild, + dle_t *dle, + backup_support_option_t *bsu) +{ + char **argv = argvchild; + sle_t *incl, *excl; + + if (bsu) { + if (bsu->include_file && dle->include_file) { + for (incl = dle->include_file->first; incl != NULL; + incl = incl->next) { + *argv = stralloc("--include-file"); + argv++; + *argv = stralloc(incl->name); + argv++; + } + } + if (bsu->include_list && dle->include_list) { + for (incl = dle->include_list->first; incl != NULL; + incl = incl->next) { + *argv = stralloc("--include-list"); + argv++; + *argv = stralloc(incl->name); + argv++; + } + } + if (bsu->include_optional && dle->include_optional) { + *argv = stralloc("--include-optional"); + argv++; + *argv = stralloc("yes"); + argv++; + } + + if (bsu->exclude_file && dle->exclude_file) { + for (excl = dle->exclude_file->first; excl != NULL; + excl = excl->next) { + *argv = stralloc("--exclude-file"); + argv++; + *argv = stralloc(excl->name); + argv++; + } + } + if (bsu->exclude_list && dle->exclude_list) { + for (excl = dle->exclude_list->first; excl != NULL; + excl = excl->next) { + *argv = stralloc("--exclude-list"); + argv++; + *argv = stralloc(excl->name); + argv++; + } + } + if (bsu->exclude_optional && dle->exclude_optional) { + *argv = stralloc("--exclude-optional"); + argv++; + *argv = stralloc("yes"); + argv++; + } + } + + g_hash_table_foreach(dle->application_property, + &proplist_add_to_argv, &argv); + return (argv - argvchild); +} + +backup_support_option_t * +backup_support_option( + char *program, + g_option_t *g_options, + char *disk, + char *amdevice, + GPtrArray **errarray) +{ + pid_t supportpid; + int supportin, supportout, supporterr; + char *cmd; + char **argvchild; + int i; + FILE *streamout; + FILE *streamerr; + char *line; + int status; + char *err = NULL; + backup_support_option_t *bsu; + + *errarray = g_ptr_array_new(); + cmd = vstralloc(APPLICATION_DIR, "/", program, NULL); + argvchild = g_new0(char *, 12); + i = 0; + argvchild[i++] = program; + argvchild[i++] = "support"; + if (g_options->config) { + argvchild[i++] = "--config"; + argvchild[i++] = g_options->config; + } + if (g_options->hostname) { + argvchild[i++] = "--host"; + argvchild[i++] = g_options->hostname; + } + if (disk) { + argvchild[i++] = "--disk"; + argvchild[i++] = disk; + } + if (amdevice) { + argvchild[i++] = "--device"; + argvchild[i++] = stralloc(amdevice); + } + argvchild[i++] = NULL; + + supporterr = fileno(stderr); + supportpid = pipespawnv(cmd, STDIN_PIPE|STDOUT_PIPE|STDERR_PIPE, 0, + &supportin, &supportout, &supporterr, argvchild); + + aclose(supportin); + + bsu = g_new0(backup_support_option_t, 1); + bsu->config = 1; + bsu->host = 1; + bsu->disk = 1; + streamout = fdopen(supportout, "r"); + if (!streamout) { + error(_("Error opening pipe to child: %s"), strerror(errno)); + /* NOTREACHED */ + } + while((line = agets(streamout)) != NULL) { + dbprintf(_("support line: %s\n"), line); + if (strncmp(line,"CONFIG ", 7) == 0) { + if (strcmp(line+7, "YES") == 0) + bsu->config = 1; + } else if (strncmp(line,"HOST ", 5) == 0) { + if (strcmp(line+5, "YES") == 0) + bsu->host = 1; + } else if (strncmp(line,"DISK ", 5) == 0) { + if (strcmp(line+5, "YES") == 0) + bsu->disk = 1; + } else if (strncmp(line,"INDEX-LINE ", 11) == 0) { + if (strcmp(line+11, "YES") == 0) + bsu->index_line = 1; + } else if (strncmp(line,"INDEX-XML ", 10) == 0) { + if (strcmp(line+10, "YES") == 0) + bsu->index_xml = 1; + } else if (strncmp(line,"MESSAGE-LINE ", 13) == 0) { + if (strcmp(line+13, "YES") == 0) + bsu->message_line = 1; + } else if (strncmp(line,"MESSAGE-XML ", 12) == 0) { + if (strcmp(line+12, "YES") == 0) + bsu->message_xml = 1; + } else if (strncmp(line,"RECORD ", 7) == 0) { + if (strcmp(line+7, "YES") == 0) + bsu->record = 1; + } else if (strncmp(line,"INCLUDE-FILE ", 13) == 0) { + if (strcmp(line+13, "YES") == 0) + bsu->include_file = 1; + } else if (strncmp(line,"INCLUDE-LIST ", 13) == 0) { + if (strcmp(line+13, "YES") == 0) + bsu->include_list = 1; + } else if (strncmp(line,"INCLUDE-OPTIONAL ", 17) == 0) { + if (strcmp(line+17, "YES") == 0) + bsu->include_optional = 1; + } else if (strncmp(line,"EXCLUDE-FILE ", 13) == 0) { + if (strcmp(line+13, "YES") == 0) + bsu->exclude_file = 1; + } else if (strncmp(line,"EXCLUDE-LIST ", 13) == 0) { + if (strcmp(line+13, "YES") == 0) + bsu->exclude_list = 1; + } else if (strncmp(line,"EXCLUDE-OPTIONAL ", 17) == 0) { + if (strcmp(line+17, "YES") == 0) + bsu->exclude_optional = 1; + } else if (strncmp(line,"COLLECTION ", 11) == 0) { + if (strcmp(line+11, "YES") == 0) + bsu->collection = 1; + } else if (strncmp(line,"CALCSIZE ", 9) == 0) { + if (strcmp(line+9, "YES") == 0) + bsu->calcsize = 1; + } else if (strncmp(line,"MULTI-ESTIMATE ", 15) == 0) { + if (strcmp(line+15, "YES") == 0) + bsu->multi_estimate = 1; + } else if (strncmp(line,"MAX-LEVEL ", 10) == 0) { + bsu->max_level = atoi(line+10); + } else if (strncmp(line,"RECOVER-MODE ", 13) == 0) { + if (strcasecmp(line+13, "SMB") == 0) + bsu->smb_recover_mode = 1; + } else { + dbprintf(_("Invalid support line: %s\n"), line); + } + amfree(line); + } + aclose(supportout); + streamerr = fdopen(supporterr, "r"); + if (!streamerr) { + error(_("Error opening pipe to child: %s"), strerror(errno)); + /* NOTREACHED */ + } + while((line = agets(streamerr)) != NULL) { + if (strlen(line) > 0) { + g_ptr_array_add(*errarray, line); + dbprintf("Application '%s': %s\n", program, line); + } + amfree(bsu); + } + aclose(supporterr); + + if (waitpid(supportpid, &status, 0) < 0) { + err = vstrallocf(_("waitpid failed: %s"), strerror(errno)); + } else if (!WIFEXITED(status)) { + err = vstrallocf(_("exited with signal %d"), WTERMSIG(status)); + } else if (WEXITSTATUS(status) != 0) { + err = vstrallocf(_("exited with status %d"), WEXITSTATUS(status)); + } + + if (err) { + g_ptr_array_add(*errarray, err); + dbprintf("Application '%s': %s\n", program, err); + amfree(bsu); + } + return bsu; +} + +void +run_client_script( + script_t *script, + execute_on_t execute_on, + g_option_t *g_options, + dle_t *dle) +{ + pid_t scriptpid; + int scriptin, scriptout, scripterr; + char *cmd; + char **argvchild; + int i; + FILE *streamout; + FILE *streamerr; + char *line; + int argv_size; + amwait_t wait_status; + + if ((script->execute_on & execute_on) == 0) + return; + if (script->execute_where != ES_CLIENT) + return; + + cmd = vstralloc(APPLICATION_DIR, "/", script->plugin, NULL); + argv_size = 14 + property_argv_size(script->property); + if (dle->level) + argv_size += 2 * g_slist_length(dle->level); + argvchild = g_new0(char *, argv_size); + i = 0; + argvchild[i++] = script->plugin; + + switch (execute_on) { + case EXECUTE_ON_PRE_DLE_AMCHECK: + argvchild[i++] = "PRE-DLE-AMCHECK"; break; + case EXECUTE_ON_PRE_HOST_AMCHECK: + argvchild[i++] = "PRE-HOST-AMCHECK"; break; + case EXECUTE_ON_POST_DLE_AMCHECK: + argvchild[i++] = "POST-DLE-AMCHECK"; break; + case EXECUTE_ON_POST_HOST_AMCHECK: + argvchild[i++] = "POST-HOST-AMCHECK"; break; + case EXECUTE_ON_PRE_DLE_ESTIMATE: + argvchild[i++] = "PRE-DLE-ESTIMATE"; break; + case EXECUTE_ON_PRE_HOST_ESTIMATE: + argvchild[i++] = "PRE-HOST-ESTIMATE"; break; + case EXECUTE_ON_POST_DLE_ESTIMATE: + argvchild[i++] = "POST-DLE-ESTIMATE"; break; + case EXECUTE_ON_POST_HOST_ESTIMATE: + argvchild[i++] = "POST-HOST-ESTIMATE"; break; + case EXECUTE_ON_PRE_DLE_BACKUP: + argvchild[i++] = "PRE-DLE-BACKUP"; break; + case EXECUTE_ON_PRE_HOST_BACKUP: + argvchild[i++] = "PRE-HOST-BACKUP"; break; + case EXECUTE_ON_POST_DLE_BACKUP: + argvchild[i++] = "POST-DLE-BACKUP"; break; + case EXECUTE_ON_POST_HOST_BACKUP: + argvchild[i++] = "POST-HOST-BACKUP"; break; + case EXECUTE_ON_PRE_RECOVER: + argvchild[i++] = "PRE-RECOVER"; break; + case EXECUTE_ON_POST_RECOVER: + argvchild[i++] = "POST-RECOVER"; break; + case EXECUTE_ON_PRE_LEVEL_RECOVER: + argvchild[i++] = "PRE-LEVEL-RECOVER"; break; + case EXECUTE_ON_POST_LEVEL_RECOVER: + argvchild[i++] = "POST-LEVEL-RECOVER"; break; + case EXECUTE_ON_INTER_LEVEL_RECOVER: + argvchild[i++] = "INTER-LEVEL-RECOVER"; break; + } + + argvchild[i++] = "--execute-where"; + argvchild[i++] = "client"; + + if (g_options->config) { + argvchild[i++] = "--config"; + argvchild[i++] = g_options->config; + } + if (g_options->hostname) { + argvchild[i++] = "--host"; + argvchild[i++] = g_options->hostname; + } + if (dle->disk) { + argvchild[i++] = "--disk"; + argvchild[i++] = dle->disk; + } + if (dle->device) { + argvchild[i++] = "--device"; + argvchild[i++] = stralloc(dle->device); + } + if (dle->level) { + GSList *level; + char number[NUM_STR_SIZE]; + for (level=dle->level; level; level=level->next) { + argvchild[i++] = "--level"; + g_snprintf(number, SIZEOF(number), "%d", + GPOINTER_TO_INT(level->data)); + argvchild[i++] = stralloc(number); + } + } + i += property_add_to_argv(&argvchild[i], script->property); + argvchild[i++] = NULL; + + scriptpid = pipespawnv(cmd, STDIN_PIPE|STDOUT_PIPE|STDERR_PIPE, 0, + &scriptin, &scriptout, &scripterr, argvchild); + + close(scriptin); + + script->result = g_new0(client_script_result_t, 1); + script->result->proplist = + g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL); + script->result->output = g_ptr_array_new(); + script->result->err = g_ptr_array_new(); + + streamout = fdopen(scriptout, "r"); + if (streamout) { + while((line = agets(streamout)) != NULL) { + dbprintf("script: %s\n", line); + if (BSTRNCMP(line, "PROPERTY ") == 0) { + char *property_name, *property_value; + property_name = line + 9; + property_value = index(property_name,' '); + if (property_value == NULL) { + char *msg = g_strdup_printf( + "ERROR %s: Bad output property: %s", + script->plugin, line); + g_ptr_array_add(script->result->output, msg); + } else { + property_t *property; + + *property_value++ = '\0'; + property_name = stralloc(property_name); + property_value = stralloc(property_value); + property = g_hash_table_lookup(script->result->proplist, + property_name); + if (!property) { + property = g_new0(property_t, 1); + g_hash_table_insert(script->result->proplist, + property_name, property); + } + property->values = g_slist_append(property->values, + property_value); + } + amfree(line); + } else { + g_ptr_array_add(script->result->output, line); + } + } + } + fclose(streamout); + + streamerr = fdopen(scripterr, "r"); + if (streamerr) { + while((line = agets(streamerr)) != NULL) { + g_ptr_array_add(script->result->err, + g_strdup_printf(_("Script '%s' command '%s': %s"), + script->plugin, argvchild[1], + line)); + amfree(line); + } + } + + waitpid(scriptpid, &wait_status, 0); + if (WIFSIGNALED(wait_status)) { + g_ptr_array_add(script->result->err, + g_strdup_printf(_("Script '%s' command '%s' terminated with signal %d: see %s"), + script->plugin, argvchild[1], + WTERMSIG(wait_status), + dbfn())); + } else if (WIFEXITED(wait_status)) { + if (WEXITSTATUS(wait_status) != 0) { + g_ptr_array_add(script->result->err, + g_strdup_printf(_("Script '%s' command '%s' exited with status %d: see %s"), + script->plugin, argvchild[1], + WEXITSTATUS(wait_status), + dbfn())); + } else { + /* Normal exit */ + } + } + +} + +void run_client_script_output(gpointer data, gpointer user_data); +void run_client_script_err_amcheck(gpointer data, gpointer user_data); +void run_client_script_err_estimate(gpointer data, gpointer user_data); +void run_client_script_err_backup(gpointer data, gpointer user_data); +void run_client_script_err_recover(gpointer data, gpointer user_data); + +typedef struct script_output_s { + FILE *stream; + dle_t *dle; +} script_output_t; + +void +run_client_script_output( + gpointer data, + gpointer user_data) +{ + char *line = data; + script_output_t *so = user_data; + + if (line && so->stream) { + g_fprintf(so->stream, "%s\n", line); + } +} + +void +run_client_script_err_amcheck( + gpointer data, + gpointer user_data) +{ + char *line = data; + script_output_t *so = user_data; + + if (line && so->stream) { + g_fprintf(so->stream, "ERROR %s\n", line); + } +} + +void +run_client_script_err_estimate( + gpointer data, + gpointer user_data) +{ + char *line = data; + script_output_t *so = user_data; + + if (line && so->stream) { + char *qdisk = quote_string(so->dle->disk); + g_fprintf(so->stream, "%s 0 WARNING \"%s\"\n", qdisk, line); + amfree(qdisk); + } +} + +void +run_client_script_err_backup( + gpointer data, + gpointer user_data) +{ + char *line = data; + script_output_t *so = user_data; + + if (line && so->stream) { + g_fprintf(so->stream, "? %s\n", line); + } +} + +void +run_client_script_err_recover( + gpointer data, + gpointer user_data) +{ + char *line = data; + script_output_t *so = user_data; + + if (line && so->stream) { + g_fprintf(so->stream, "%s\n", line); + } +} + +void +run_client_scripts( + execute_on_t execute_on, + g_option_t *g_options, + dle_t *dle, + FILE *streamout) +{ + GSList *scriptlist; + script_t *script; + GFunc client_script_err = NULL; + script_output_t so = { streamout, dle }; + + for (scriptlist = dle->scriptlist; scriptlist != NULL; + scriptlist = scriptlist->next) { + script = (script_t *)scriptlist->data; + run_client_script(script, execute_on, g_options, dle); + if (script->result && script->result->output) { + g_ptr_array_foreach(script->result->output, + run_client_script_output, + &so); + g_ptr_array_free(script->result->output, TRUE); + script->result->output = NULL; + } + if (script->result && script->result->err) { + switch (execute_on) { + case EXECUTE_ON_PRE_DLE_AMCHECK: + case EXECUTE_ON_PRE_HOST_AMCHECK: + case EXECUTE_ON_POST_DLE_AMCHECK: + case EXECUTE_ON_POST_HOST_AMCHECK: + client_script_err = run_client_script_err_amcheck; + break; + case EXECUTE_ON_PRE_DLE_ESTIMATE: + case EXECUTE_ON_PRE_HOST_ESTIMATE: + case EXECUTE_ON_POST_DLE_ESTIMATE: + case EXECUTE_ON_POST_HOST_ESTIMATE: + if (am_has_feature(g_options->features, + fe_sendsize_rep_warning)) { + client_script_err = run_client_script_err_estimate; + } + break; + case EXECUTE_ON_PRE_DLE_BACKUP: + case EXECUTE_ON_PRE_HOST_BACKUP: + case EXECUTE_ON_POST_DLE_BACKUP: + case EXECUTE_ON_POST_HOST_BACKUP: + client_script_err = run_client_script_err_backup; + break; + case EXECUTE_ON_PRE_RECOVER: + case EXECUTE_ON_POST_RECOVER: + case EXECUTE_ON_PRE_LEVEL_RECOVER: + case EXECUTE_ON_POST_LEVEL_RECOVER: + case EXECUTE_ON_INTER_LEVEL_RECOVER: + client_script_err = run_client_script_err_recover; + } + if (client_script_err != NULL) { + g_ptr_array_foreach(script->result->err, + client_script_err, + &so); + } + g_ptr_array_free(script->result->err, TRUE); + script->result->err = NULL; + } + } +} + + +void +run_calcsize( + char *config, + char *program, + char *disk, + char *dirname, + GSList *levels, + char *file_exclude, + char *file_include) +{ + char *cmd, *cmdline; + char *my_argv[DUMP_LEVELS*2+22]; + int my_argc; + char tmppath[PATH_MAX]; + char number[NUM_STR_SIZE]; + GSList *alevel; + int level; + int i; + char *match_expr; + int pipefd = -1, nullfd = -1; + pid_t calcpid; + times_t start_time; + FILE *dumpout = NULL; + int dumpsince; + char *errmsg = NULL; + off_t size = (off_t)1; + char *line = NULL; + amwait_t wait_status; + int len; + char *qdisk; + amandates_t *amdp; + char *amandates_file; + + qdisk = quote_string(disk); + + amandates_file = getconf_str(CNF_AMANDATES); + if(!start_amandates(amandates_file, 0)) { + char *errstr = strerror(errno); + char *errmsg = vstrallocf(_("could not open %s: %s"), amandates_file, errstr); + char *qerrmsg = quote_string(errmsg); + g_printf(_("ERROR %s\n"), qerrmsg); + amfree(qdisk); + amfree(errmsg); + amfree(qerrmsg); + return; + } + + startclock(); + cmd = vstralloc(amlibexecdir, "/", "calcsize", versionsuffix(), NULL); + + my_argc = 0; + + my_argv[my_argc++] = stralloc("calcsize"); + if (config) + my_argv[my_argc++] = stralloc(config); + else + my_argv[my_argc++] = stralloc("NOCONFIG"); + + my_argv[my_argc++] = stralloc(program); + + canonicalize_pathname(disk, tmppath); + my_argv[my_argc++] = stralloc(tmppath); + canonicalize_pathname(dirname, tmppath); + my_argv[my_argc++] = stralloc(tmppath); + + if (file_exclude) { + my_argv[my_argc++] = stralloc("-X"); + my_argv[my_argc++] = file_exclude; + } + + if (file_include) { + my_argv[my_argc++] = stralloc("-I"); + my_argv[my_argc++] = file_include; + } + + for (alevel = levels; alevel != NULL; alevel = alevel->next) { + amdp = amandates_lookup(disk); + level = GPOINTER_TO_INT(alevel->data); + dbprintf("level: %d\n", level); + dumpsince = 0; + for (i=0; i < level; i++) { + if (dumpsince < amdp->dates[i]) + dumpsince = amdp->dates[i]; + } + g_snprintf(number, SIZEOF(number), "%d", level); + my_argv[my_argc++] = stralloc(number); + g_snprintf(number, SIZEOF(number), "%d", dumpsince); + my_argv[my_argc++] = stralloc(number); + } + + my_argv[my_argc] = NULL; + cmdline = stralloc(my_argv[0]); + for(i = 1; i < my_argc; i++) + cmdline = vstrextend(&cmdline, " ", my_argv[i], NULL); + dbprintf(_("running: \"%s\"\n"), cmdline); + amfree(cmdline); + + start_time = curclock(); + + fflush(stderr); fflush(stdout); + + if ((nullfd = open("/dev/null", O_RDWR)) == -1) { + errmsg = vstrallocf(_("Cannot access /dev/null : %s"), + strerror(errno)); + dbprintf("%s\n", errmsg); + goto common_exit; + } + + calcpid = pipespawnv(cmd, STDERR_PIPE, 0, + &nullfd, &nullfd, &pipefd, my_argv); + amfree(cmd); + + dumpout = fdopen(pipefd,"r"); + if (!dumpout) { + error(_("Can't fdopen: %s"), strerror(errno)); + /*NOTREACHED*/ + } + + match_expr = vstralloc(" %d SIZE %lld", NULL); + len = strlen(qdisk); + for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) { + long long size_ = (long long)0; + if (line[0] == '\0' || (int)strlen(line) <= len) + continue; + /* Don't use sscanf for qdisk because it can have a '%'. */ + if (strncmp(line, qdisk, len) == 0 && + sscanf(line+len, match_expr, &level, &size_) == 2) { + g_printf("%d %lld %d\n", level, size_, 1); /* write to sendsize */ + dbprintf(_("estimate size for %s level %d: %lld KB\n"), + qdisk, level, size_); + } + size = (off_t)size_; + } + amfree(match_expr); + + dbprintf(_("waiting for %s %s child (pid=%d)\n"), + my_argv[0], qdisk, (int)calcpid); + waitpid(calcpid, &wait_status, 0); + if (WIFSIGNALED(wait_status)) { + errmsg = vstrallocf(_("%s terminated with signal %d: see %s"), + "calcsize", WTERMSIG(wait_status), + dbfn()); + } else if (WIFEXITED(wait_status)) { + if (WEXITSTATUS(wait_status) != 0) { + errmsg = vstrallocf(_("%s exited with status %d: see %s"), + "calcsize", WEXITSTATUS(wait_status), + dbfn()); + } else { + /* Normal exit */ + } + } else { + errmsg = vstrallocf(_("%s got bad exit: see %s"), + "calcsize", dbfn()); + } + + dbprintf(_("after %s %s wait: child pid=%d status=%d\n"), + my_argv[0], qdisk, + (int)calcpid, WEXITSTATUS(wait_status)); + + dbprintf(_(".....\n")); + dbprintf(_("estimate time for %s: %s\n"), + qdisk, + walltime_str(timessub(curclock(), start_time))); + +common_exit: + if (errmsg && errmsg[0] != '\0') { + char *qerrmsg = quote_string(errmsg); + dbprintf(_("errmsg is %s\n"), errmsg); + g_printf("ERROR %s\n", qerrmsg); + amfree(qerrmsg); + } + amfree(qdisk); + amfree(errmsg); + for(i = 0; i < my_argc; i++) { + amfree(my_argv[i]); + } + amfree(cmd); + +} + + +void +check_access( + char * filename, + int mode) +{ + char *noun, *adjective; + char *quoted = quote_string(filename); + + if(mode == F_OK) + noun = "find", adjective = "exists"; + else if((mode & X_OK) == X_OK) + noun = "execute", adjective = "executable"; + else if((mode & (W_OK|R_OK)) == (W_OK|R_OK)) + noun = "read/write", adjective = "read/writable"; + else + noun = "access", adjective = "accessible"; + + if(access(filename, mode) == -1) + g_printf(_("ERROR [can not %s %s: %s]\n"), noun, quoted, strerror(errno)); + else + g_printf(_("OK %s %s\n"), quoted, adjective); + amfree(quoted); +} + +void +check_file( + char * filename, + int mode) +{ + struct stat stat_buf; + char *quoted; + + if(!stat(filename, &stat_buf)) { + if(!S_ISREG(stat_buf.st_mode)) { + quoted = quote_string(filename); + g_printf(_("ERROR [%s is not a file]\n"), quoted); + amfree(quoted); + } + } + if (getuid() == geteuid()) { + check_access(filename, mode); + } +} + +void +check_dir( + char * dirname, + int mode) +{ + struct stat stat_buf; + char *quoted; + char *dir; + + if(!stat(dirname, &stat_buf)) { + if(!S_ISDIR(stat_buf.st_mode)) { + quoted = quote_string(dirname); + g_printf(_("ERROR [%s is not a directory]\n"), quoted); + amfree(quoted); + } + } else { + quoted = quote_string(dirname); + g_printf(_("ERROR [%s: %s]\n"), quoted, strerror(errno)); + amfree(quoted); + } + if (getuid() == geteuid()) { + dir = stralloc2(dirname, "/."); + check_access(dir, mode); + amfree(dir); + } +} + +void +check_suid( + char * filename) +{ +#ifndef SINGLE_USERID + struct stat stat_buf; + char *quoted = quote_string(filename); + + if(!stat(filename, &stat_buf)) { + if(stat_buf.st_uid != 0 ) { + g_printf(_("ERROR [%s is not owned by root]\n"), quoted); + } + if((stat_buf.st_mode & S_ISUID) != S_ISUID) { + g_printf(_("ERROR [%s is not SUID root]\n"), quoted); + } + } + else { + g_printf(_("ERROR [can not stat %s]\n"), quoted); + } + amfree(quoted); +#else + (void)filename; /* Quiet unused parameter warning */ +#endif +} + +/* + * Returns the value of the first integer in a string. + */ + +double +the_num( + char * str, + int pos) +{ + char *num; + int ch; + double d; + + do { + ch = *str++; + while(ch && !isdigit(ch)) ch = *str++; + if (pos == 1) break; + pos--; + while(ch && (isdigit(ch) || ch == '.')) ch = *str++; + } while (ch); + num = str - 1; + while(isdigit(ch) || ch == '.') ch = *str++; + str[-1] = '\0'; + d = atof(num); + str[-1] = (char)ch; + return d; +} + + +char * +config_errors_to_error_string( + GSList *errlist) +{ + char *errmsg; + gboolean multiple_errors = FALSE; + + if (errlist) { + errmsg = (char *)errlist->data; + if (errlist->next) + multiple_errors = TRUE; + } else { + errmsg = _("(no error message)"); + } + + return vstrallocf("ERROR %s%s", errmsg, + multiple_errors? _(" (additional errors not displayed)"):""); }