+ }
+ 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 = strchr(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);