Beispiel #1
0
static gboolean
ToolsCoreRpcSetOption(RpcInData *data)
{

   gboolean retVal = FALSE;
   char *option;
   char *value;
   unsigned int index = 0;
   ToolsServiceState *state = data->clientData;

   /* Parse the option & value string. */
   option = StrUtil_GetNextToken(&index, data->args, " ");
   /* Ignore leading space before value. */
   index++;
   value = StrUtil_GetNextToken(&index, data->args, "");

   if (option != NULL && value != NULL && strlen(value) != 0) {

      g_debug("Setting option '%s' to '%s'.\n", option, value);
      g_signal_emit_by_name(state->ctx.serviceObj,
                            TOOLS_CORE_SIG_SET_OPTION,
                            &state->ctx,
                            option,
                            value,
                            &retVal);
   }

   vm_free(option);
   vm_free(value);

   RPCIN_SETRETVALS(data, retVal ? "" : "Unknown or invalid option", retVal);

   return retVal;
}
static Bool
ParseGid(const char *option,        // IN:  option string along with value
         HgfsMountInfo *mountInfo,  // OUT: mount data
         int *flags)                // OUT: mount flags
{
   Bool success = FALSE;
   unsigned int idx = 0;
   char *optString;
   char *gidString;
   gid_t myGid = 0;

   ASSERT(option);
   ASSERT(mountInfo);
   ASSERT(flags);

   /* Figure where value starts, we don't need result, just index. */
   optString = StrUtil_GetNextToken(&idx, option, "=");
   ASSERT(optString);
   gidString = StrUtil_GetNextToken(&idx, option, "=");
   if (!gidString) {
      LOG("Error getting the value for gid\n");
      goto out;
   }

   /*
    * The gid can be a direct value or a group name which we must first
    * translate to its numeric value.
    */
   if (isdigit(*gidString)) {
      errno = 0;
      myGid = strtoul(gidString, NULL, 10);
      if (errno == 0) {
         success = TRUE;
      } else {
         printf("Bad GID value \"%s\"\n", gidString);
      }
   } else {
      struct group *gr;

      if (!(gr = getgrnam(gidString))) {
         printf("Bad group name \"%s\"\n", gidString);
      } else {
         myGid = gr->gr_gid;
         success = TRUE;
      }
      endpwent();
   }

   if (success) {
      mountInfo->gid = myGid;
      mountInfo->gidSet = TRUE;
      LOG("Setting mount group to %"FMTUID"\n", myGid);
   }

   free(gidString);
out:
   free(optString);
   return success;
}
static void
PrintUsage(void)
{
   int i;

   printf("Usage: %s <sharename> <dir> [-o <options>]\n", thisProgramBase);
   printf("Mount the HGFS share, specified by name, to a local directory.\n");
   printf("Share name must be in host:dir format.\n\nOptions:\n");

   for (i = 0; i < ARRAYSIZE(mountOptions); i++) {
      Bool printOptName = TRUE;
      unsigned int tokidx = 0;
      char *msg;

      while ((msg = StrUtil_GetNextToken(&tokidx,
                                         mountOptions[i].helpMsg,
                                         "\n")) != NULL) {
         printf("  %-15s       %s\n",
                printOptName ? mountOptions[i].opt : "", msg);
         free(msg);
         printOptName = FALSE;
      }
   }

   printf("\n");
   printf("This command is intended to be run from within /bin/mount by\n");
   printf("passing the option '-t %s'. For example:\n", HGFS_NAME);
   printf("  mount -t %s .host:/ /mnt/hgfs/\n", HGFS_NAME);
   printf("  mount -t %s .host:/foo /mnt/foo\n", HGFS_NAME);
   printf("  mount -t %s .host:/foo/bar /var/lib/bar\n", HGFS_NAME);
   exit(EXIT_FAILURE);
}
static Bool
ParseTtl(const char *option,        // IN:  option string along with value
         HgfsMountInfo *mountInfo,  // OUT: mount data
         int *flags)                // OUT: mount flags
{
   Bool success = FALSE;
   unsigned int idx = 0;
   char *optString;
   int32 ttl;

   ASSERT(option);
   ASSERT(mountInfo);
   ASSERT(flags);

   /* Figure where value starts, we don't need result, just index. */
   optString = StrUtil_GetNextToken(&idx, option, "=");
   ASSERT(optString);

   if (StrUtil_GetNextIntToken(&ttl, &idx, option, "=") && ttl >= 0) {
      LOG("Setting maximum attribute TTL to %u\n", ttl);
      mountInfo->ttl = ttl;
      success = TRUE;
   } else {
      LOG("Error getting the value for ttl\n");
   }

   free(optString);
   return success;
}
static Bool
ParseMask(const char *option,         // IN:  option string along with value
          unsigned short *pmask)      // OUT: parsed mask
{
   Bool success = FALSE;
   unsigned int idx = 0;
   char *optString;
   char *maskString;
   unsigned short mask;

   optString = StrUtil_GetNextToken(&idx, option, "=");
   ASSERT(optString);
   maskString = StrUtil_GetNextToken(&idx, option, "=");
   if (!maskString) {
      LOG("Error getting the value for %s\n", optString);
      goto out;
   }

   /*
    * The way to check for an overflow in strtol(3), according to its
    * man page.
    */
   errno = 0;
   mask = strtol(maskString, NULL, 8);
   if (errno == 0) {
      *pmask = mask;
      success = TRUE;
   } else {
      LOG("Error, overflow in %s\n", optString);
   }

   free(maskString);
out:
   free(optString);
   return success;
}
Beispiel #6
0
gboolean
RpcChannel_Dispatch(RpcInData *data)
{
   char *name = NULL;
   unsigned int index = 0;
   size_t nameLen;
   Bool status;
   RpcChannelCallback *rpc = NULL;
   RpcChannelInt *chan = data->clientData;

   name = StrUtil_GetNextToken(&index, data->args, " ");
   if (name == NULL) {
      Debug(LGPFX "Bad command (null) received.\n");
      status = RPCIN_SETRETVALS(data, "Bad command", FALSE);
      goto exit;
   }

   if (chan->rpcs != NULL) {
      rpc = g_hash_table_lookup(chan->rpcs, name);
   }

   if (rpc == NULL) {
      Debug(LGPFX "Unknown Command '%s': Handler not registered.\n", name);
      status = RPCIN_SETRETVALS(data, "Unknown Command", FALSE);
      goto exit;
   }

   /* Adjust the RPC arguments. */
   nameLen = strlen(name);
   data->name = name;
   data->args = data->args + nameLen;
   data->argsSize -= nameLen;
   data->appCtx = chan->appCtx;
   data->clientData = rpc->clientData;

   if (rpc->xdrIn != NULL || rpc->xdrOut != NULL) {
      status = RpcChannelXdrWrapper(data, rpc);
   } else {
      status = rpc->callback(data);
   }

   ASSERT(data->result != NULL);

exit:
   data->name = NULL;
   free(name);
   return status;
}
Beispiel #7
0
Bool
StrUtil_GetNextInt64Token(int64 *out,             // OUT: The output value
                          unsigned int *index,    // IN/OUT: Index to start at
                          const char *str,        // IN    : String to parse
                          const char *delimiters) // IN    : Chars separating tokens
{
   char *resultStr;
   Bool result;

   ASSERT(out);
   ASSERT(index);
   ASSERT(str);
   ASSERT(delimiters);

   resultStr = StrUtil_GetNextToken(index, str, delimiters);
   result = resultStr ? StrUtil_StrToInt64(out, resultStr) : FALSE;
   free(resultStr);

   return result;
}
Beispiel #8
0
Bool
StrUtil_GetNextUintToken(uint32 *out,            // OUT   : parsed int
                         unsigned int *index,    // IN/OUT: Index to start at
                         const char *str,        // IN    : String to parse
                         const char *delimiters) // IN    : Chars separating tokens
{
   char *resultStr;
   Bool valid = FALSE;

   ASSERT(out);
   ASSERT(index);
   ASSERT(str);
   ASSERT(delimiters);

   resultStr = StrUtil_GetNextToken(index, str, delimiters);
   if (resultStr == NULL) {
      return FALSE;
   }

   valid = StrUtil_StrToUint(out, resultStr);
   free(resultStr);

   return valid;
}
static Bool
ParseOptions(const char *optionString, // IN:  Option string to parse
             HgfsMountInfo *mountInfo, // OUT: Where we put the results
             int *flags)               // OUT: Flags we might modify
{
   unsigned int commaIndex = 0;
   Bool success = FALSE;
   char *key = NULL;
   char *keyVal = NULL;
   int i;

   ASSERT(optionString);
   ASSERT(mountInfo);
   ASSERT(flags);

   /* Parse the options string. */
   LOG("Parsing option string: %s\n", optionString);

   /* Loop to tokenize <keyval1>,<keyval2>,<keyval3>. */
   while ((keyVal = StrUtil_GetNextToken(&commaIndex,
                                         optionString, ",")) != NULL) {
      /* Now tokenize <key>[=<val>]. */
      unsigned int equalsIndex = 0;
      key = StrUtil_GetNextToken(&equalsIndex, keyVal, "=");
      if (key == NULL) {
         printf("Malformed options string\n");
         goto out;
      }

      for (i = 0; i < ARRAYSIZE(mountOptions); i++) {
         Bool match = FALSE;
         unsigned int idx = 0;
         char *optName = StrUtil_GetNextToken(&idx, mountOptions[i].opt, "=");

         if (!optName) {
            printf("Failed to parse option name, out of memory?\n");
            goto out;
         }

         match = strcmp(key, optName) == 0;
         free(optName);

         if (match) {
            if (mountOptions[i].handler) {
               if (!mountOptions[i].handler(keyVal, mountInfo, flags)) {
                  goto out;
               }
            } else {
               if (mountOptions[i].set) {
                  *flags |= mountOptions[i].flag;
               } else {
                  *flags &= ~mountOptions[i].flag;
               }
               LOG("%s\n", mountOptions[i].logMsg);
            }
            break;
         }
      }

      if (i == ARRAYSIZE(mountOptions)) {
         LOG("Skipping unrecognized option \"%s\"\n", key);
      }

      free(key);
      free(keyVal);
      key = NULL;
      keyVal = NULL;
   }

   success = TRUE;

out:
   free(key);
   free(keyVal);
   return success;
}
static gboolean
RpcDebugSend(RpcChannel *chan,
             char const *data,
             size_t dataLen,
             char **result,
             size_t *resultLen)
{
   char *copy;
   gpointer xdrdata = NULL;
   DbgChannelData *cdata = chan->_private;
   RpcDebugPlugin *plugin = cdata->plugin;
   RpcDebugRecvMapping *mapping = NULL;
   RpcDebugRecvFn recvFn = NULL;
   gboolean ret = TRUE;

   ASSERT(cdata->ctx != NULL);

   /* Be paranoid. Like the VMX, NULL-terminate the incoming data. */
   copy = g_malloc(dataLen + 1);
   memcpy(copy, data, dataLen);
   copy[dataLen] = '\0';

   /* Try to find a mapping the the command in the RPC. */
   if (plugin->recvFns) {
      char *cmd;
      unsigned int idx = 0;

      cmd = StrUtil_GetNextToken(&idx, copy, " ");
      if (cmd != NULL) {
         RpcDebugRecvMapping *test;
         for (test = plugin->recvFns; test->name != NULL; test++) {
            if (strcmp(test->name, cmd) == 0) {
               mapping = test;
               break;
            }
         }
      }
      vm_free(cmd);
   }

   if (mapping != NULL) {
      recvFn = mapping->recvFn;
      if (mapping->xdrProc != NULL) {
         char *start;

         ASSERT(mapping->xdrSize > 0);

         /* Find out where the XDR data starts. */
         start = strchr(copy, ' ');
         if (start == NULL) {
            RpcDebug_SetResult("Can't find command delimiter.", result, resultLen);
            ret = FALSE;
            goto exit;
         }
         start++;

         xdrdata = g_malloc0(mapping->xdrSize);
         if (!XdrUtil_Deserialize(start,
                                  dataLen - (start - copy),
                                  mapping->xdrProc,
                                  xdrdata)) {
            RpcDebug_SetResult("XDR deserialization failed.", result, resultLen);
            ret = FALSE;
            goto exit;
         }
      }
   } else {
      recvFn = plugin->dfltRecvFn;
   }

   if (recvFn != NULL) {
      ret = recvFn((xdrdata != NULL) ? xdrdata : copy, dataLen, result, resultLen);
   } else {
      RpcDebug_SetResult("", result, resultLen);
   }

exit:
   if (xdrdata != NULL) {
      VMX_XDR_FREE(mapping->xdrProc, xdrdata);
      g_free(xdrdata);
   }
   g_free(copy);
   return ret;
}
static HashTable *
SNEBuildHash(const char **compatEnviron)
                // IN: original "compatibility" environment
{
   HashTable *environTable;
   const char **p;

   /*
    * Number of buckets picked arbitrarily.  We're more interested in having an
    * associative array than raw table performance.
    */
   environTable = HashTable_Alloc(64, HASH_STRING_KEY | HASH_FLAG_COPYKEY, free);

   for (p = compatEnviron; p && *p; p++) {
      const size_t prefixLength = sizeof "VMWARE_" - 1;
      char *key;
      char *value;
      unsigned int index;

      index = 0;
      key = StrUtil_GetNextToken(&index, *p, "=");
      if (!key) {
         /* XXX Must empty environment variables still contain a '=' delimiter? */
         Debug("%s: Encountered environment entry without '='.\n", __func__);
         continue;
      }

      /*
       * Copy the value beginning after the '=' delimiter (even if it's empty).
       */
      ++index;
      value = Util_SafeStrdup(&(*p)[index]);

      if (StrUtil_StartsWith(key, "VMWARE_") &&
          key[prefixLength] != '\0' &&
          (value[0] == '0' || value[0] == '1')) {
         /*
          * Okay, this appears to be one of the wrapper's variables, so let's
          * figure out the original environment variable name (by just indexing
          * past the prefix) and value (by indexing past the "was this variable
          * in the native environment?" marker).
          *
          * XXX Should we move this marker to a separate header?
          */
         char *realKey = &key[prefixLength];
         char *realValue = (value[0] == '0')
                           ? NULL
                           : Util_SafeStrdup(&value[1]);
         HashTable_ReplaceOrInsert(environTable, realKey, realValue);
      } else {
         HashTable_LookupOrInsert(environTable, key, value);
      }

      /*
       * The hash table makes a copy of our key, and it takes ownership of inserted
       * values (via our passed freeing function).  So that means we're responsible
       * for freeing 'key', but -not- 'value'.
       */
      free(key);
   }

   return environTable;
}
Beispiel #12
0
static Bool
RpcInExecRpc(RpcIn *in,            // IN
             const char *reply,    // IN
             size_t repLen,        // IN
             const char **errmsg)  // OUT
{
   unsigned int status;
   const char *statusStr;
   unsigned int statusLen;
   char *result;
   size_t resultLen;
   Bool freeResult = FALSE;

   /*
    * Execute the RPC
    */

#if defined(VMTOOLS_USE_GLIB)
   RpcInData data = { NULL, reply, repLen, NULL, 0, FALSE, NULL, in->clientData };

   status = in->dispatch(&data);
   result = data.result;
   resultLen = data.resultLen;
   freeResult = data.freeResult;
#else
   char *cmd;
   unsigned int index = 0;
   RpcInCallbackList *cb = NULL;

   cmd = StrUtil_GetNextToken(&index, reply, " ");
   if (cmd != NULL) {
      cb = RpcInLookupCallback(in, cmd);
      free(cmd);
      if (cb) {
         result = NULL;
         status = cb->callback((char const **) &result, &resultLen, cb->name,
                               reply + cb->length, repLen - cb->length,
                               cb->clientData);
         ASSERT(result);
      } else {
         status = FALSE;
         result = "Unknown Command";
         resultLen = strlen(result);
      }
   } else {
      status = FALSE;
      result = "Bad command";
      resultLen = strlen(result);
   }
#endif

   statusStr = status ? "OK " : "ERROR ";
   statusLen = strlen(statusStr);

   in->last_result = (char *)malloc(statusLen + resultLen);
   if (in->last_result == NULL) {
      *errmsg = "RpcIn: Not enough memory";
      return FALSE;
   }
   memcpy(in->last_result, statusStr, statusLen);
   memcpy(in->last_result + statusLen, result, resultLen);
   in->last_resultLen = statusLen + resultLen;

   if (freeResult) {
      free(result);
   }

   /*
    * Run the event pump (in case VMware sends a long sequence of RPCs and
    * perfoms a time-consuming job) and continue to loop immediately
    */
   in->delay = 0;

   return TRUE;
}