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; }
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; }
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; }
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; }
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; }