Unicode * Unicode_AllocList(char **srcList, // IN: list of strings ssize_t length, // IN: list StringEncoding encoding) // IN: { Unicode *dstList = NULL; ssize_t i; ASSERT(srcList != NULL); encoding = Unicode_ResolveEncoding(encoding); if (length < 0) { length = 0; while (srcList[length] != NULL) { length++; } /* Include the sentinel element. */ length++; } dstList = Util_SafeMalloc(length * sizeof *dstList); for (i = 0; i < length; i++) { dstList[i] = Unicode_Alloc(srcList[i], encoding); } return dstList; }
Bool ProcMgr_GetImpersonatedUserInfo(char **userName, // OUT char **homeDir) // OUT { char buffer[BUFSIZ]; struct passwd pw; struct passwd *ppw; *userName = NULL; *homeDir = NULL; ppw = &pw; if ((ppw = getpwuid_r(Id_GetEUid(), &pw, buffer, sizeof buffer)) == NULL) { return FALSE; } *userName = Unicode_Alloc(ppw->pw_name, STRING_ENCODING_DEFAULT); *homeDir = Unicode_Alloc(ppw->pw_dir, STRING_ENCODING_DEFAULT); return TRUE; }
Unicode System_GetTimeAsString(void) { struct timeval tv; time_t sec; int msec; size_t charsWritten; size_t bufSize = 8; // Multiplied by 2 for the initial allocation. char *buf = NULL; Unicode dateTime = NULL; Unicode output = NULL; if (gettimeofday(&tv, NULL)) { goto out; } sec = tv.tv_sec; msec = tv.tv_usec / 1000; /* * Loop repeatedly trying to format the time into a buffer, doubling the * buffer with each failure. This should be safe as the manpage for * strftime(3) seems to suggest that it only fails if the buffer isn't large * enough. * * The resultant string is encoded according to the current locale. */ do { char *newBuf; bufSize *= 2; newBuf = realloc(buf, bufSize); if (newBuf == NULL) { goto out; } buf = newBuf; charsWritten = strftime(buf, bufSize, "%b %d %H:%M:%S", localtime(&sec)); } while (charsWritten == 0); /* * Append the milliseconds field, but only after converting the date/time * string from encoding specified in the current locale to an opaque type. */ dateTime = Unicode_Alloc(buf, STRING_ENCODING_DEFAULT); if (dateTime == NULL) { goto out; } output = Unicode_Format("%s.%03d", dateTime, msec); out: free(buf); Unicode_Free(dateTime); return output; }
char * VixToolsGetNextEnvVar(VixToolsEnvIterator *envItr) // IN { char *envVar; if (NULL == envItr) { return NULL; } #ifdef _WIN32 if (VIX_TOOLS_ENV_TYPE_ENV_BLOCK == envItr->envType) { if (L'\0' == envItr->data.eb.currEnvVar[0]) { envVar = NULL; } else { envVar = Unicode_AllocWithUTF16(envItr->data.eb.currEnvVar); while(*envItr->data.eb.currEnvVar++); } } else if (VIX_TOOLS_ENV_TYPE_ENVIRON == envItr->envType) { if (NULL == *envItr->data.environ) { envVar = NULL; } else { envVar = Unicode_AllocWithUTF16(*envItr->data.environ); envItr->data.environ++; } } else { /* Is someone using uninitialized memory? */ NOT_IMPLEMENTED(); } #else if (NULL == *envItr->environ) { envVar = NULL; } else { envVar = Unicode_Alloc(*envItr->environ, STRING_ENCODING_DEFAULT); envItr->environ++; } #endif return envVar; }
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; }
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; }