static int
ScriptToggle(const char *progName,  // IN: program name (argv[0])
             const char *apm,       // IN: APM name
             Bool enable)           // IN: status
{
   const char *path;
   const char *confName;
   int ret = EXIT_SUCCESS;
   GKeyFile *confDict;
   GError *err = NULL;

   confName = GetConfName(apm);

   if (!confName) {
      ToolsCmd_UnknownEntityError(progName,
                                  SU_(script.operation, "operation"),
                                  apm);
      return EX_USAGE;
   }

   confDict = LoadConfFile();

   if (!enable) {
      path = "";
   } else {
      path = GuestApp_GetDefaultScript(confName);
   }

   g_key_file_set_string(confDict, "powerops", confName, path);
   if (!VMTools_WriteConfig(NULL, confDict, &err)) {
      ToolsCmd_PrintErr(SU_(script.write.error, "Error writing config: %s\n"),
                        err->message);
      g_clear_error(&err);
      ret = EX_TEMPFAIL;
   }

   g_key_file_free(confDict);
   return ret;
}
static int
GetConfEntry(const char *progName,  // IN: program name (argv[0])
             const char *apm,       // IN: apm name
             ScriptType type)       // IN: Script type (default or current)
{
   gchar *entry;
   GKeyFile *confDict;
   const char *confName;
   int len;
   int ret;

   confName = GetConfName(apm);
   if (!confName) {
      ToolsCmd_UnknownEntityError(progName,
                                  SU_(script.operation, "operation"),
                                  apm);
      return EX_USAGE;
   }

   confDict = LoadConfFile();

   switch (type) {
   case Current:
      entry = g_key_file_get_string(confDict, "powerops", confName, NULL);
      if (entry) {
         break;
      }
      /* Fall through */

   default:
      entry = g_strdup(GuestApp_GetDefaultScript(confName));
      break;
   }

   len = strlen(entry);
   if (len > 0) {

      /* If script path is not absolute, assume the Tools install path. */
      if (!g_path_is_absolute(entry)) {
         char *defaultPath = GuestApp_GetInstallPath();
         char *tmp;
         Bool quoted;

         ASSERT(defaultPath != NULL);

         /* Cope with old configs that added quotes around script paths. */
         quoted = (entry[0] == '"' && entry[len - 1] == '"');
         tmp = g_strdup_printf("%s%c%.*s", defaultPath, DIRSEPC,
                                quoted ? len - 2 : len,
                                quoted ? entry + 1 : entry);

         vm_free(defaultPath);

         g_free(entry);
         entry = tmp;
      }

      g_print("%s\n", entry);
      ret = EXIT_SUCCESS;
   } else {
      ToolsCmd_PrintErr(SU_(script.unknownop, "No script for operation %s.\n"),
                        apm);
      ret = EX_TEMPFAIL;
   }

   g_free(entry);
   g_key_file_free(confDict);
   return ret;
}
static gboolean
PowerOpsStateChange(RpcInData *data)
{
   size_t i;
   PowerOpState *state = data->clientData;

   if (state->pid != INVALID_PID) {
      g_debug("State change already in progress.\n");
      return RPCIN_SETRETVALS(data,  "State change already in progress", FALSE);
   }

   g_debug("State change: %s\n", data->name);

   for (i = 0; i < ARRAYSIZE(stateChangeCmdTable); i++) {
      if (strcmp(data->name, stateChangeCmdTable[i].tcloCmd) == 0) {
         gchar *script;
         const char *result;
         const char *confName;
         Bool ret;

         state->stateChgInProgress = stateChangeCmdTable[i].id;

         /* Check for the toolScripts option. */
         if (!state->scriptEnabled[stateChangeCmdTable[i].id]) {
            PowerOpsStateChangeDone(state, TRUE);
            g_debug("Script for %s not configured to run\n",
                    stateChangeCmdTable[i].tcloCmd);
            return RPCIN_SETRETVALS(data, "", TRUE);
         }

         confName = stateChgConfNames[stateChangeCmdTable[i].id];
         script = g_key_file_get_string(state->ctx->config,
                                        "powerops",
                                        confName,
                                        NULL);

         if (script == NULL) {
            /* Use default script if not set in config file. */
            const char *dfltScript = GuestApp_GetDefaultScript(confName);
            if (dfltScript == NULL) {
               g_debug("No default script to run for state change %s.\n",
                       stateChangeCmdTable[i].name);
               PowerOpsStateChangeDone(state, TRUE);
               return RPCIN_SETRETVALS(data, "", TRUE);
            }
            script = g_strdup(dfltScript);
         } else if (strlen(script) == 0) {
            g_debug("No script to run for state change %s.\n",
                    stateChangeCmdTable[i].name);
            g_free(script);
            PowerOpsStateChangeDone(state, TRUE);
            return RPCIN_SETRETVALS(data, "", TRUE);
         }

         /* If script path is not absolute, assume the Tools install path. */
         if (!g_path_is_absolute(script)) {
            char *dfltPath;
            char *tmp;

            dfltPath = GuestApp_GetInstallPath();
            ASSERT(dfltPath != NULL);

            /*
             * Before the switch to vmtoolsd, the config file was saved with
             * quotes around the script path to make the old VMware dict code
             * happy. Now we need to undo that when modifying the script path.
             *
             * PowerOpsRunScript will "re-quote" the script path.
             */
            if (script[0] == '"') {
                script[strlen(script) - 1] = '\0';
                tmp = g_strdup_printf("%s%c%s", dfltPath, DIRSEPC, script + 1);
            } else {
               tmp = g_strdup_printf("%s%c%s", dfltPath, DIRSEPC, script);
            }

            g_free(script);
            vm_free(dfltPath);
            script = tmp;
         }

         if (PowerOpsRunScript(state, script)) {
            result = "";
            ret = TRUE;
         } else {
            PowerOpsStateChangeDone(state, FALSE);
            result = "Error starting script";
            ret = FALSE;
         }

         g_free(script);
         return RPCIN_SETRETVALS(data, (char *) result, ret);
      }
   }

   g_warning("Invalid state change command.\n");
   return RPCIN_SETRETVALS(data, "Invalid state change command", FALSE);
}