static char * ExtractCommandLineFromAddressSpaceFile(psinfo_t *procInfo) //IN: psinfo struct { int argc; int i; char tempPath[MAXPATHLEN]; char *buf; FileIODescriptor asFd; FileIOResult res; DynBuf cmdLine; DynBufArray args; pid_t pid; FileIO_Invalidate(&asFd); pid = procInfo->pr_pid; if (Str_Snprintf(tempPath, sizeof tempPath, "/proc/%"FMT64"d/as", (int64_t)pid) == -1) { /* This should not happen. MAXPATHLEN should be large enough. */ ASSERT(FALSE); } res = FileIO_Open(&asFd, tempPath, FILEIO_OPEN_ACCESS_READ, FILEIO_OPEN); if (res != FILEIO_SUCCESS) { Warning("Could not open address space file for pid %"FMT64"d, %s\n", (int64_t)pid, FileIO_MsgError(res)); return NULL; } buf = NULL; if (ReadArgsFromAddressSpaceFile(asFd, procInfo, &args)) { /* Concatenate the strings in args into cmdLine. */ DynBuf_Init(&cmdLine); argc = DynBufArray_Count(&args); for (i = 0; i < argc; i++) { buf = DynBuf_Get(DynBufArray_AddressOf(&args, i)); DynBuf_Append(&cmdLine, buf, strlen(buf)); if (i + 1 < argc) { DynBuf_Append(&cmdLine, " ", 1); } DynBuf_Destroy(DynBufArray_AddressOf(&args, i)); } DynBuf_AppendString(&cmdLine,""); DynBufArray_Destroy(&args); DynBuf_Trim(&cmdLine); buf = DynBuf_Detach(&cmdLine); DynBuf_Destroy(&cmdLine); } FileIO_Close(&asFd); return buf; }
void Str_UnitTests(void) { char buf[1024]; wchar_t bufw[1024]; int count; int32 num1 = 0xDEADBEEF; int32 num2 = 0x927F82CD; int64 num3 = CONST64U(0xCAFEBABE42439021); #ifdef _WIN32 double num4 = 5.1923843; double num5 = 0.000482734; double num6 = 8274102.3872; #endif int numChars; char empty[1] = {'\0'}; wchar_t wempty[1] = {L'\0'}; /* test empty string */ count = Str_Snprintf(buf, 1, empty); if (0 != count) { FAIL("Failed empty string test"); } count = Str_Snwprintf(bufw, 1, wempty); if (0 != count) { FAIL("Failed empty string test (W)"); } /* test borderline overflow */ count = Str_Snprintf(buf, 2, "ba"); if (-1 != count) { FAIL("Failed borderline overflow test - count"); } if (buf[1]) { FAIL("Failed borderline overflow test - NULL term"); } count = Str_Snwprintf(bufw, 2, L"ba"); if (-1 != count) { FAIL("Failed borderline overflow test - count (W)"); } if (bufw[1]) { FAIL("Failed borderline overflow test - NULL term (W)"); } /* test egregious overflow */ count = Str_Snprintf(buf, 2, "baabaa"); if (-1 != count) { FAIL("Failed egregious overflow test - count"); } if (buf[1]) { FAIL("Failed egregious overflow test - NULL term"); } count = Str_Snwprintf(bufw, 2, L"baabaa"); if (-1 != count) { FAIL("Failed egregious overflow test - count (W)"); } if (bufw[1]) { FAIL("Failed egregious overflow test - NULL term (W)"); } /* test 'n' argument */ count = Str_Snprintf(buf, 1024, "foo %n\n", &numChars); if (-1 == count) { FAIL("Failed 'n' arg test - count"); } if (4 != numChars) { FAIL("Failed 'n' arg test - numChars"); } count = Str_Snwprintf(bufw, 1024, L"foo %n\n", &numChars); if (-1 == count) { FAIL("Failed 'n' arg test - count (W)"); } if (4 != numChars) { FAIL("Failed 'n' arg test - numChars (W)"); } bCompare = TRUE; // simple PrintAndCheck("hello\n"); PrintAndCheckW(L"hello\n"); // string arguments PrintAndCheck("whazz %s up %S doc\n", "hello", L"hello"); PrintAndCheckW(L"whazz %s up %S doc\n", L"hello", "hello"); // character arguments PrintAndCheck("whazz %c up %C doc\n", 'a', L'a'); PrintAndCheckW(L"whazz %c up %C doc\n", L'a', 'a'); // 32-bit integer arguments PrintAndCheck("%d %i %o %u %x %X\n", num1, num1, num1, num1, num1, num1); PrintAndCheckW(L"%d %i %o %u %x %X\n", num1, num1, num1, num1, num1, num1); // 'p' argument bCompare = FALSE; PrintAndCheck("%p\n", buf); PrintAndCheckW(L"%p\n", buf); bCompare = TRUE; // 64-bit bCompare = FALSE; PrintAndCheck("%LX %llX %qX\n", num3, num3, num3); PrintAndCheckW(L"%LX %llX %qX\n", num3, num3, num3); bCompare = TRUE; // more 64-bit #ifdef _WIN32 PrintAndCheck("%I64X\n", num3); PrintAndCheckW(L"%I64X\n", num3); #else PrintAndCheck("%LX\n", num3); PrintAndCheckW(L"%LX\n", num3); #endif #ifdef _WIN32 // exponent digits printed differs vs. POSIX // floating-point PrintAndCheck("%e %E %f %g %G\n", num4, num5, num6); PrintAndCheckW(L"%e %E %f %g %G\n", num4, num5, num6); #endif // positional arguments bCompare = FALSE; PrintAndCheck("%3$LX %1$x %2$x\n", num1, num2, num3); PrintAndCheckW(L"%3$LX %1$x %2$x\n", num1, num2, num3); bCompare = TRUE; #ifdef _WIN32 // exponent digits printed differs vs. POSIX // width and precision PrintAndCheck("%15.1g %20.2f %*.*f\n", num6, num6, 15, 3, num6); PrintAndCheckW(L"%15.1g %20.2f %*.*f\n", num6, num6, 15, 3, num6); #endif #ifdef _WIN32 // exponent digits printed differs vs. POSIX // flags PrintAndCheck("%-15e %+f %015g\n", num4, num5, num6); PrintAndCheckW(L"%-15e %+f %015g\n", num4, num5, num6); #endif #ifdef _WIN32 // exponent digits printed differs vs. POSIX // more flags PrintAndCheck("%#X %#E %#G\n", num1, num1, num1); PrintAndCheckW(L"%#X %#E %#G\n", num1, num1, num1); #endif }
ProcMgrProcInfoArray * ProcMgr_ListProcesses(void) { ProcMgrProcInfoArray *procList = NULL; ProcMgrProcInfo processInfo; Bool failed = TRUE; DIR *dir; struct dirent *ent; procList = Util_SafeCalloc(1, sizeof *procList); ProcMgrProcInfoArray_Init(procList, 0); processInfo.procOwner = NULL; processInfo.procCmd = NULL; dir = opendir("/proc"); if (NULL == dir) { Warning("ProcMgr_ListProcesses unable to open /proc\n"); goto exit; } while (TRUE) { struct passwd *pwd; char tempPath[MAXPATHLEN]; psinfo_t procInfo; size_t strLen = 0; size_t numRead = 0; FileIODescriptor psInfoFd; FileIOResult res; errno = 0; FileIO_Invalidate(&psInfoFd); ent = readdir(dir); if (ent == NULL) { if (errno == 0) { break; } else { goto exit; } } if (Str_Snprintf(tempPath, sizeof tempPath, "/proc/%s/psinfo", ent->d_name) == -1) { Debug("Process id '%s' too large\n", ent->d_name); continue; } res = FileIO_Open(&psInfoFd, tempPath, FILEIO_OPEN_ACCESS_READ, FILEIO_OPEN); if (res != FILEIO_SUCCESS) { if ((res == FILEIO_FILE_NOT_FOUND) || (res == FILEIO_NO_PERMISSION)) { continue; } else { goto exit; } } res = FileIO_Read(&psInfoFd, &procInfo, sizeof procInfo, &numRead); FileIO_Close(&psInfoFd); if (res != FILEIO_SUCCESS) { goto exit; } processInfo.procStartTime = procInfo.pr_start.tv_sec; /* * Command line strings in procInfo.pr_psargs are truncated to PRARGZ * bytes. In this case we extract the arguments from the /proc/<pid>/as * file. Since most command line strings are expected to fit within * PRARGSZ bytes, we avoid calling * ExtractCommandLineFromAddressSpaceFile for every process. */ if (strlen(procInfo.pr_psargs) + 1 == PRARGSZ) { char *tmp; tmp = ExtractCommandLineFromAddressSpaceFile(&procInfo); if (tmp != NULL) { processInfo.procCmd = Unicode_Alloc(tmp, STRING_ENCODING_DEFAULT); free(tmp); } else { processInfo.procCmd = Unicode_Alloc(procInfo.pr_psargs, STRING_ENCODING_DEFAULT); } } else { processInfo.procCmd = Unicode_Alloc(procInfo.pr_psargs, STRING_ENCODING_DEFAULT); } /* * Store the pid in dynbuf. */ processInfo.procId = procInfo.pr_pid; /* * Store the owner of the process. */ pwd = getpwuid(procInfo.pr_uid); processInfo.procOwner = (NULL == pwd) ? Str_SafeAsprintf(&strLen, "%d", (int) procInfo.pr_uid) : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT); /* * Store the process info into a list buffer. */ if (!ProcMgrProcInfoArray_Push(procList, processInfo)) { Warning("%s: failed to expand DynArray - out of memory\n", __FUNCTION__); goto exit; } processInfo.procCmd = NULL; processInfo.procOwner = NULL; } // while (TRUE) if (0 < ProcMgrProcInfoArray_Count(procList)) { failed = FALSE; } exit: closedir(dir); free(processInfo.procOwner); free(processInfo.procCmd); if (failed) { ProcMgr_FreeProcList(procList); procList = NULL; } return procList; }
Bool FileIO_AtomicUpdate(FileIODescriptor *newFD, // IN/OUT: file IO descriptor FileIODescriptor *currFD) // IN/OUT: file IO descriptor { char *currPath = NULL; char *newPath = NULL; #if defined(_WIN32) uint32 currAccess; uint32 newAccess; FileIOResult status; FileIODescriptor tmpFD; #else int fd; #endif int savedErrno = 0; Bool ret = FALSE; ASSERT(FileIO_IsValid(newFD)); ASSERT(FileIO_IsValid(currFD)); if (HostType_OSIsVMK()) { #if defined(VMX86_SERVER) FS_SwapFilesArgs *args = NULL; char *dirName = NULL; char *fileName = NULL; char *dstDirName = NULL; char *dstFileName = NULL; currPath = File_FullPath(FileIO_Filename(currFD)); if (!currPath) { savedErrno = errno; Log("%s: File_FullPath of '%s' failed.\n", __FUNCTION__, FileIO_Filename(currFD)); goto swapdone; } newPath = File_FullPath(FileIO_Filename(newFD)); if (!newPath) { savedErrno = errno; Log("%s: File_FullPath of '%s' failed.\n", __FUNCTION__, FileIO_Filename(newFD)); goto swapdone; } File_GetPathName(newPath, &dirName, &fileName); File_GetPathName(currPath, &dstDirName, &dstFileName); ASSERT(dirName && *dirName); ASSERT(fileName && *fileName); ASSERT(dstDirName && *dstDirName); ASSERT(dstFileName && *dstFileName); ASSERT(!strcmp(dirName, dstDirName)); args = (FS_SwapFilesArgs *) Util_SafeCalloc(1, sizeof(*args)); if (Str_Snprintf(args->srcFile, sizeof(args->srcFile), "%s", fileName) < 0) { Log("%s: Path too long \"%s\".\n", __FUNCTION__, fileName); savedErrno = ENAMETOOLONG; goto swapdone; } if (Str_Snprintf(args->dstFilePath, sizeof(args->dstFilePath), "%s/%s", dstDirName, dstFileName) < 0) { Log("%s: Path too long \"%s\".\n", __FUNCTION__, dstFileName); savedErrno = ENAMETOOLONG; goto swapdone; } /* * Issue the ioctl on the directory rather than on the file, * because the file could be open. */ fd = Posix_Open(dirName, O_RDONLY); if (fd < 0) { Log("%s: Open failed \"%s\" %d.\n", __FUNCTION__, dirName, errno); ASSERT(errno != EBUSY); /* #615124. */ savedErrno = errno; goto swapdone; } if (ioctl(fd, IOCTLCMD_VMFS_SWAP_FILES, args) != 0) { savedErrno = errno; if (errno != ENOSYS && errno != ENOTTY) { Log("%s: ioctl failed %d.\n", __FUNCTION__, errno); ASSERT(errno != EBUSY); /* #615124. */ } } else { ret = TRUE; } close(fd); /* * Did we fail because we are on a file system that does not * support the IOCTLCMD_VMFS_SWAP_FILES ioctl? If so fallback to * using rename. * * Check for both ENOSYS and ENOTTY. PR 957695 */ if (savedErrno == ENOSYS || savedErrno == ENOTTY) { /* * NFS allows renames of locked files, even if both files * are locked. The file lock follows the file handle, not * the name, so after the rename we can swap the underlying * file descriptors instead of closing and reopening the * target file. * * This is different than the hosted path below because * ESX uses native file locks and hosted does not. * * We assume that all ESX file systems that support rename * have the same file lock semantics as NFS. */ if (File_Rename(newPath, currPath)) { Log("%s: rename of '%s' to '%s' failed %d.\n", __FUNCTION__, newPath, currPath, errno); savedErrno = errno; goto swapdone; } ret = TRUE; fd = newFD->posix; newFD->posix = currFD->posix; currFD->posix = fd; FileIO_Close(newFD); } swapdone: free(args); free(dirName); free(fileName); free(dstDirName); free(dstFileName); free(currPath); free(newPath); errno = savedErrno; return ret; #else NOT_REACHED(); #endif } #if defined(_WIN32) currPath = Unicode_Duplicate(FileIO_Filename(currFD)); newPath = Unicode_Duplicate(FileIO_Filename(newFD)); newAccess = newFD->flags; currAccess = currFD->flags; FileIO_Close(newFD); /* * The current file needs to be closed and reopened, * but we don't want to drop the file lock by calling * FileIO_Close() on it. Instead, use native close primitives. * We'll reopen it later with FileIO_Open. Set the * descriptor/handle to an invalid value while we're in the * middle of transferring ownership. */ CloseHandle(currFD->win32); currFD->win32 = INVALID_HANDLE_VALUE; if (File_RenameRetry(newPath, currPath, 10) == 0) { ret = TRUE; } else { savedErrno = errno; ASSERT(!ret); } FileIO_Invalidate(&tmpFD); /* * Clear the locking bits from the requested access so that reopening * the file ignores the advisory lock. */ ASSERT((currAccess & FILEIO_OPEN_LOCK_MANDATORY) == 0); currAccess &= ~(FILEIO_OPEN_LOCK_MANDATORY | FILEIO_OPEN_LOCK_ADVISORY | FILEIO_OPEN_LOCK_BEST | FILEIO_OPEN_LOCKED); status = FileIO_Open(&tmpFD, currPath, currAccess, FILEIO_OPEN); if (!FileIO_IsSuccess(status)) { Panic("Failed to reopen dictionary after renaming " "\"%s\" to \"%s\": %s (%d)\n", newPath, currPath, FileIO_ErrorEnglish(status), status); } ASSERT(tmpFD.lockToken == NULL); currFD->win32 = tmpFD.win32; FileIO_Cleanup(&tmpFD); Unicode_Free(currPath); Unicode_Free(newPath); errno = savedErrno; return ret; #else currPath = (char *)FileIO_Filename(currFD); newPath = (char *)FileIO_Filename(newFD); if (File_Rename(newPath, currPath)) { Log("%s: rename of '%s' to '%s' failed %d.\n", __FUNCTION__, newPath, currPath, errno); savedErrno = errno; } else { ret = TRUE; fd = newFD->posix; newFD->posix = currFD->posix; currFD->posix = fd; FileIO_Close(newFD); } errno = savedErrno; return ret; #endif }
gboolean ToolsDaemonHgfsImpersonated(RpcInData *data) // IN { VixError err; size_t hgfsPacketSize = 0; size_t hgfsReplySize = 0; const char *origArgs = data->args; Bool impersonatingVMWareUser = FALSE; char *credentialTypeStr = NULL; char *obfuscatedNamePassword = NULL; void *userToken = NULL; int actualUsed; #define STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING 20 #define OTHER_TEXT_SIZE 4 /* strlen(space zero space quote) */ static char resultPacket[STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING + OTHER_TEXT_SIZE + HGFS_LARGE_PACKET_MAX]; char *hgfsReplyPacket = resultPacket + STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING + OTHER_TEXT_SIZE; Debug(">ToolsDaemonHgfsImpersonated\n"); err = VIX_OK; /* * We assume VixError is 64 bits. If it changes, we need * to adjust STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING. * * There isn't much point trying to return gracefully * if sizeof(VixError) is larger than we expected: we didn't * allocate enough space to actually represent the error! * So we're stuck. Panic at this point. */ ASSERT_ON_COMPILE(sizeof (uint64) == sizeof err); /* * Get the authentication information. */ credentialTypeStr = ToolsDaemonTcloGetQuotedString(data->args, &data->args); obfuscatedNamePassword = ToolsDaemonTcloGetQuotedString(data->args, &data->args); /* * Make sure we are passed the correct arguments. */ if ((NULL == credentialTypeStr) || (NULL == obfuscatedNamePassword)) { err = VIX_E_INVALID_ARG; goto abort; } /* * Skip over our token that is right before the HGFS packet. * This makes ToolsDaemonTcloGetQuotedString parsing predictable, * since it will try to eat trailing spaces after a quoted string, * and the HGFS packet might begin with a space. */ if (((data->args - origArgs) >= data->argsSize) || ('#' != *(data->args))) { /* * Buffer too small or we got an unexpected token. */ err = VIX_E_FAIL; goto abort; } data->args++; /* * At this point args points to the HGFS packet. * If we're pointing beyond the end of the buffer, we'll * get a negative HGFS packet length and abort. */ hgfsPacketSize = data->argsSize - (data->args - origArgs); if (hgfsPacketSize <= 0) { err = VIX_E_FAIL; goto abort; } if (thisProcessRunsAsRoot) { impersonatingVMWareUser = VixToolsImpersonateUserImpl(credentialTypeStr, VIX_USER_CREDENTIAL_NONE, obfuscatedNamePassword, &userToken); if (!impersonatingVMWareUser) { err = VIX_E_GUEST_USER_PERMISSIONS; goto abort; } } /* * Impersonation was okay, so let's give our packet to * the HGFS server and forward the reply packet back. */ hgfsReplySize = sizeof resultPacket - (hgfsReplyPacket - resultPacket); HgfsServerManager_ProcessPacket(&gFoundryHgfsBkdrConn, // hgfs server connection data->args, // packet in buf hgfsPacketSize, // packet in size hgfsReplyPacket, // packet out buf &hgfsReplySize); // reply buf/data size abort: if (impersonatingVMWareUser) { VixToolsUnimpersonateUser(userToken); } VixToolsLogoutUser(userToken); /* * These were allocated by ToolsDaemonTcloGetQuotedString. */ free(credentialTypeStr); free(obfuscatedNamePassword); data->result = resultPacket; data->resultLen = STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING + OTHER_TEXT_SIZE + hgfsReplySize; /* * Render the foundry error codes into the buffer. */ actualUsed = Str_Snprintf(resultPacket, STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING + OTHER_TEXT_SIZE, "%"FMT64"d 0 ", err); if (actualUsed < 0) { /* * We computed our string length wrong! This should never happen. * But if it does, let's try to recover gracefully. The "1" in * the string below is VIX_E_FAIL. We don't try to use %d since * we couldn't even do that right the first time around. * That hash is needed for the parser on the other * end to stop before the HGFS packet, since the HGFS packet * can contain a space (and the parser can eat trailing spaces). */ ASSERT(0); actualUsed = Str_Snprintf(resultPacket, STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING, "1 0 #"); data->resultLen = actualUsed; } else { /* * We computed the string length correctly. Great! * * We allocated enough space to cover a large 64 bit number * for VixError. Chances are we didn't use all that space. * Instead, pad it with whitespace so the text parser can skip * over it. */ memset(resultPacket + actualUsed, ' ', STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING + OTHER_TEXT_SIZE - actualUsed); /* * Put a hash right before the HGFS packet. * So the buffer will look something like this: * "0 0 #" followed by the HGFS packet. */ resultPacket[STRLEN_OF_MAX_64_BIT_NUMBER_AS_STRING + OTHER_TEXT_SIZE - 1] = '#'; } Debug("<<<ToolsDaemonHgfsImpersonated\n"); return TRUE; } // ToolsDaemonHgfsImpersonated
ProcMgrProcInfoArray * ProcMgr_ListProcesses(void) { ProcMgrProcInfoArray *procList = NULL; ProcMgrProcInfo processInfo; Bool failed = TRUE; DIR *dir; struct dirent *ent; procList = Util_SafeCalloc(1, sizeof *procList); ProcMgrProcInfoArray_Init(procList, 0); processInfo.procOwner = NULL; processInfo.procCmdLine = NULL; processInfo.procCmdName = NULL; dir = opendir("/proc"); if (NULL == dir) { Warning("ProcMgr_ListProcesses unable to open /proc\n"); goto exit; } while (TRUE) { char *tmp; char *cmdNameBegin = NULL; char *cmdNameEnd = NULL; struct passwd *pwd; char tempPath[MAXPATHLEN]; psinfo_t procInfo; size_t strLen = 0; size_t numRead = 0; FileIODescriptor psInfoFd; FileIOResult res; Bool cmdNameLookup = TRUE; errno = 0; FileIO_Invalidate(&psInfoFd); ent = readdir(dir); if (ent == NULL) { if (errno == 0) { break; } else { goto exit; } } if (Str_Snprintf(tempPath, sizeof tempPath, "/proc/%s/psinfo", ent->d_name) == -1) { Debug("Process id '%s' too large\n", ent->d_name); continue; } res = FileIO_Open(&psInfoFd, tempPath, FILEIO_OPEN_ACCESS_READ, FILEIO_OPEN); if (res != FILEIO_SUCCESS) { if ((res == FILEIO_FILE_NOT_FOUND) || (res == FILEIO_NO_PERMISSION)) { continue; } else { goto exit; } } res = FileIO_Read(&psInfoFd, &procInfo, sizeof procInfo, &numRead); FileIO_Close(&psInfoFd); if (res != FILEIO_SUCCESS) { goto exit; } processInfo.procStartTime = procInfo.pr_start.tv_sec; /* * If the command name in the ps info struct is strictly less than the * maximum allowed size, then we can save it right now. Else we shall * need to try and parse it from the entire command line, to avoid * saving a truncated command name. */ if (strlen(procInfo.pr_fname) + 1 < sizeof procInfo.pr_fname) { processInfo.procCmdName = Unicode_Alloc(procInfo.pr_fname, STRING_ENCODING_DEFAULT); cmdNameLookup = FALSE; } /* * The logic below is this: * 1. If we are looking for the explicit command name, we need to * extract the arguments from the /proc/<pid>/as file and save argv[0]. * 2. If we are not looking for the explicit command name, but the command * line in the ps info struct is not strictly less than the maximum * allowed size, we still need to extract the arguments from the * /proc/<pid>/as file, to avoid saving truncated comand line. * 3. Else we can save the command line directly from the ps info struct. */ if (cmdNameLookup) { tmp = ExtractCommandLineFromAddressSpaceFile(&procInfo, &processInfo.procCmdName); } else if (strlen(procInfo.pr_psargs) + 1 >= sizeof procInfo.pr_psargs) { tmp = ExtractCommandLineFromAddressSpaceFile(&procInfo, NULL); } else { tmp = NULL; } if (tmp != NULL) { processInfo.procCmdLine = Unicode_Alloc(tmp, STRING_ENCODING_DEFAULT); cmdNameLookup = FALSE; } else { /* * We had some issues reading procfs, mostly due to lack of * permissions for certain system owned precesses. So let's resort to * what the procinfo structure provides as a last resort. */ processInfo.procCmdLine = Unicode_Alloc(procInfo.pr_psargs, STRING_ENCODING_DEFAULT); if (cmdNameLookup) { /* * Now let's try and get the best effort command name from the entire * command line. The method below does not take care of spaces in folder * names and executable file names. This is the best we can do at this * point, considering that spaces are not common in either file or * folder names in Solaris, specially when owned by the system. */ char *tmp2 = Unicode_Alloc(procInfo.pr_psargs, STRING_ENCODING_DEFAULT); cmdNameBegin = tmp2; /* * Assuming the command name to end at the first blank space. */ cmdNameEnd = cmdNameBegin; while ('\0' != *cmdNameEnd) { if ('/' == *cmdNameEnd) { cmdNameBegin = cmdNameEnd + 1; } if (' ' == *cmdNameEnd) { break; } cmdNameEnd++; } *cmdNameEnd = '\0'; processInfo.procCmdName = Str_SafeAsprintf(NULL, "%s", cmdNameBegin); free(tmp2); } } free(tmp); tmp = NULL; /* * Store the pid. */ processInfo.procId = procInfo.pr_pid; /* * Store the owner of the process. */ pwd = getpwuid(procInfo.pr_uid); processInfo.procOwner = (NULL == pwd) ? Str_SafeAsprintf(&strLen, "%d", (int) procInfo.pr_uid) : Unicode_Alloc(pwd->pw_name, STRING_ENCODING_DEFAULT); /* * Store the process info into a list buffer. */ if (!ProcMgrProcInfoArray_Push(procList, processInfo)) { Warning("%s: failed to expand DynArray - out of memory\n", __FUNCTION__); goto exit; } processInfo.procCmdName = NULL; processInfo.procCmdLine = NULL; processInfo.procOwner = NULL; } // while (TRUE) if (0 < ProcMgrProcInfoArray_Count(procList)) { failed = FALSE; } exit: closedir(dir); free(processInfo.procOwner); free(processInfo.procCmdLine); free(processInfo.procCmdName); if (failed) { ProcMgr_FreeProcList(procList); procList = NULL; } return procList; }
static char * ExtractCommandLineFromAddressSpaceFile(psinfo_t *procInfo, //IN: psinfo struct char **procCmdName) //OUT: command name { int argc; int i; char tempPath[MAXPATHLEN]; char *buf; FileIODescriptor asFd; FileIOResult res; DynBuf cmdLine; DynBufArray args; pid_t pid; char *cmdNameBegin; if (NULL != procCmdName) { *procCmdName = NULL; } FileIO_Invalidate(&asFd); pid = procInfo->pr_pid; if (Str_Snprintf(tempPath, sizeof tempPath, "/proc/%"FMT64"d/as", (int64_t)pid) == -1) { /* This should not happen. MAXPATHLEN should be large enough. */ ASSERT(FALSE); } res = FileIO_Open(&asFd, tempPath, FILEIO_OPEN_ACCESS_READ, FILEIO_OPEN); if (res != FILEIO_SUCCESS) { Warning("Could not open address space file for pid %"FMT64"d, %s\n", (int64_t)pid, FileIO_MsgError(res)); return NULL; } buf = NULL; if (ReadArgsFromAddressSpaceFile(asFd, procInfo, &args)) { /* Concatenate the strings in args into cmdLine. */ DynBuf_Init(&cmdLine); argc = DynBufArray_Count(&args); for (i = 0; i < argc; i++) { buf = DynBuf_Get(DynBufArray_AddressOf(&args, i)); DynBuf_Append(&cmdLine, buf, strlen(buf)); if (i + 1 < argc) { DynBuf_Append(&cmdLine, " ", 1); } if (NULL != procCmdName && 0 == i) { /* * Store the command name of the process. * Find the last path separator, to get the cmd name. * If no separator is found, then use the whole name. */ cmdNameBegin = strrchr(buf, '/'); if (NULL == cmdNameBegin) { cmdNameBegin = buf; } else { /* * Skip over the last separator. */ cmdNameBegin++; } *procCmdName = Unicode_Alloc(cmdNameBegin, STRING_ENCODING_DEFAULT); } DynBuf_Destroy(DynBufArray_AddressOf(&args, i)); } DynBuf_AppendString(&cmdLine,""); DynBufArray_Destroy(&args); DynBuf_Trim(&cmdLine); buf = DynBuf_Detach(&cmdLine); DynBuf_Destroy(&cmdLine); } FileIO_Close(&asFd); return buf; }