diff options
Diffstat (limited to 'agent/mibgroup/host/hr_swrun.c')
-rw-r--r-- | agent/mibgroup/host/hr_swrun.c | 1574 |
1 files changed, 1574 insertions, 0 deletions
diff --git a/agent/mibgroup/host/hr_swrun.c b/agent/mibgroup/host/hr_swrun.c new file mode 100644 index 0000000..854883e --- /dev/null +++ b/agent/mibgroup/host/hr_swrun.c @@ -0,0 +1,1574 @@ +/* Portions of this file are subject to the following copyright(s). See + * the Net-SNMP's COPYING file for more details and other copyrights + * that may apply: + */ +/* + * Portions of this file are copyrighted by: + * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms specified in the COPYING file + * distributed with the Net-SNMP package. + */ + +/* + * Host Resources MIB - Running Software group implementation - hr_swrun.c + * (also includes Running Software Performance group ) + * + */ + +#include <net-snmp/net-snmp-config.h> +#if HAVE_STDLIB_H +#include <stdlib.h> +#endif +#include <fcntl.h> +#if HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <sys/param.h> +#include <ctype.h> +#if HAVE_SYS_PSTAT_H +#include <sys/pstat.h> +#endif +#if HAVE_SYS_USER_H +#ifdef solaris2 +#include <libgen.h> +#define _KMEMUSER +#endif +#include <sys/user.h> +#endif +#if HAVE_SYS_PROC_H +#include <sys/proc.h> +#endif +#if HAVE_KVM_H +#include <kvm.h> +#endif +#if HAVE_SYS_SYSCTL_H +#include <sys/sysctl.h> +#endif +#if HAVE_DIRENT_H && !defined(cygwin) +#include <dirent.h> +#else +# define dirent direct +# if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# if HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# if HAVE_NDIR_H +# include <ndir.h> +# endif +#endif +#ifdef cygwin +#include <windows.h> +#include <sys/cygwin.h> +#include <tlhelp32.h> +#include <psapi.h> +#endif + +#if _SLASH_PROC_METHOD_ +#include <procfs.h> +#endif + +#if HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif + +#include <stdio.h> + +#include <net-snmp/output_api.h> +#include "host_res.h" +#include "hr_swrun.h" +#include <net-snmp/agent/auto_nlist.h> +#include "kernel.h" +#ifdef solaris2 +#if _SLASH_PROC_METHOD_ && defined _ILP32 +#include <net-snmp/agent/cache_handler.h> +#include <net-snmp/agent/hardware/memory.h> +#endif + +#include "kernel_sunos5.h" +#endif +#if defined(aix4) || defined(aix5) || defined(aix6) +#include <procinfo.h> +#include <sys/types.h> +#endif + + /********************* + * + * Initialisation & common implementation functions + * + *********************/ +void Init_HR_SWRun(void); +int Get_Next_HR_SWRun(void); +void End_HR_SWRun(void); +int header_hrswrun(struct variable *, oid *, size_t *, int, + size_t *, WriteMethod **); +int header_hrswrunEntry(struct variable *, oid *, size_t *, + int, size_t *, WriteMethod **); + +#ifdef dynix +pid_t nextproc; +static prpsinfo_t lowpsinfo, mypsinfo; +#endif +#ifdef cygwin +static struct external_pinfo *curproc; +static struct external_pinfo lowproc; +#elif !defined(linux) +static int LowProcIndex; +#endif +#if defined(hpux10) || defined(hpux11) +struct pst_status *proc_table; +struct pst_dynamic pst_dyn; +#elif HAVE_KVM_GETPROCS +struct kinfo_proc *proc_table; +#elif defined(solaris2) +int *proc_table; +#elif defined(aix4) || defined(aix5) || defined(aix6) +struct procsinfo *proc_table; +#else +struct proc *proc_table; +#endif +#ifndef dynix +int current_proc_entry; +#endif + + +#define HRSWRUN_OSINDEX 1 + +#define HRSWRUN_INDEX 2 +#define HRSWRUN_NAME 3 +#define HRSWRUN_ID 4 +#define HRSWRUN_PATH 5 +#define HRSWRUN_PARAMS 6 +#define HRSWRUN_TYPE 7 +#define HRSWRUN_STATUS 8 + +#define HRSWRUNPERF_CPU 9 +#define HRSWRUNPERF_MEM 10 + +struct variable4 hrswrun_variables[] = { + {HRSWRUN_OSINDEX, ASN_INTEGER, RONLY, var_hrswrun, 1, {1}}, + {HRSWRUN_INDEX, ASN_INTEGER, RONLY, var_hrswrun, 3, {2, 1, 1}}, + {HRSWRUN_NAME, ASN_OCTET_STR, RONLY, var_hrswrun, 3, {2, 1, 2}}, + {HRSWRUN_ID, ASN_OBJECT_ID, RONLY, var_hrswrun, 3, {2, 1, 3}}, + {HRSWRUN_PATH, ASN_OCTET_STR, RONLY, var_hrswrun, 3, {2, 1, 4}}, + {HRSWRUN_PARAMS, ASN_OCTET_STR, RONLY, var_hrswrun, 3, {2, 1, 5}}, + {HRSWRUN_TYPE, ASN_INTEGER, RONLY, var_hrswrun, 3, {2, 1, 6}}, + {HRSWRUN_STATUS, ASN_INTEGER, RONLY, var_hrswrun, 3, {2, 1, 7}} +}; + +struct variable4 hrswrunperf_variables[] = { + {HRSWRUNPERF_CPU, ASN_INTEGER, RONLY, var_hrswrun, 3, {1, 1, 1}}, + {HRSWRUNPERF_MEM, ASN_INTEGER, RONLY, var_hrswrun, 3, {1, 1, 2}} +}; + +oid hrswrun_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 4 }; +oid hrswrunperf_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 5 }; + +#ifdef cygwin + +/* + * a lot of this is "stolen" from cygwin ps.cc + */ + +typedef BOOL(WINAPI * ENUMPROCESSMODULES) (HANDLE hProcess, + HMODULE * lphModule, + DWORD cb, + LPDWORD lpcbNeeded); + +typedef DWORD(WINAPI * GETMODULEFILENAME) (HANDLE hProcess, + HMODULE hModule, + LPTSTR lpstrFIleName, + DWORD nSize); + +typedef DWORD(WINAPI * GETPROCESSMEMORYINFO) (HANDLE hProcess, + PPROCESS_MEMORY_COUNTERS + pmc, DWORD nSize); + +typedef HANDLE(WINAPI * CREATESNAPSHOT) (DWORD dwFlags, + DWORD th32ProcessID); + +typedef BOOL(WINAPI * PROCESSWALK) (HANDLE hSnapshot, + LPPROCESSENTRY32 lppe); + +ENUMPROCESSMODULES myEnumProcessModules; +GETMODULEFILENAME myGetModuleFileNameEx; +CREATESNAPSHOT myCreateToolhelp32Snapshot; +PROCESSWALK myProcess32First; +PROCESSWALK myProcess32Next; +GETPROCESSMEMORYINFO myGetProcessMemoryInfo = NULL; +cygwin_getinfo_types query = CW_GETPINFO; + +static BOOL WINAPI +dummyprocessmodules(HANDLE hProcess, + HMODULE * lphModule, DWORD cb, LPDWORD lpcbNeeded) +{ + lphModule[0] = (HMODULE) * lpcbNeeded; + *lpcbNeeded = 1; + return 1; +} + +static DWORD WINAPI +GetModuleFileNameEx95(HANDLE hProcess, + HMODULE hModule, LPTSTR lpstrFileName, DWORD n) +{ + HANDLE h; + DWORD pid = (DWORD) hModule; + PROCESSENTRY32 proc; + + h = myCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (!h) + return 0; + proc.dwSize = sizeof(proc); + if (myProcess32First(h, &proc)) + do + if (proc.th32ProcessID == pid) { + CloseHandle(h); + strcpy(lpstrFileName, proc.szExeFile); + return 1; + } + while (myProcess32Next(h, &proc)); + CloseHandle(h); + return 0; +} + +#define FACTOR (0x19db1ded53ea710LL) +#define NSPERSEC 10000000LL +#define NSPERMSEC 10000LL + +static time_t __stdcall +to_time_t(PFILETIME ptr) +{ + long rem; + long long x = + ((long long) ptr->dwHighDateTime << 32) + + ((unsigned) ptr->dwLowDateTime); + x -= FACTOR; + rem = x % NSPERSEC; + rem += NSPERSEC / 2; + x /= NSPERSEC; + x += rem / NSPERSEC; + return x; +} + +static long +to_msec(PFILETIME ptr) +{ + long long x = + ((long long) ptr->dwHighDateTime << 32) + + (unsigned) ptr->dwLowDateTime; + x /= NSPERMSEC; + return x; +} + +#endif /* cygwin */ + + +void +init_hr_swrun(void) +{ +#ifdef cygwin + OSVERSIONINFO ver; + HMODULE h; + + memset(&ver, 0, sizeof ver); + ver.dwOSVersionInfoSize = sizeof ver; + GetVersionEx(&ver); + + if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) { + h = LoadLibrary("psapi.dll"); + if (h) { + myEnumProcessModules = + (ENUMPROCESSMODULES) GetProcAddress(h, + "EnumProcessModules"); + myGetModuleFileNameEx = + (GETMODULEFILENAME) GetProcAddress(h, + "GetModuleFileNameExA"); + myGetProcessMemoryInfo = + (GETPROCESSMEMORYINFO) GetProcAddress(h, + "GetProcessMemoryInfo"); + if (myEnumProcessModules && myGetModuleFileNameEx) + query = CW_GETPINFO_FULL; + else + snmp_log(LOG_ERR, "hr_swrun failed NT init\n"); + } else + snmp_log(LOG_ERR, "hr_swrun failed to load psapi.dll\n"); + } else { + h = GetModuleHandle("KERNEL32.DLL"); + myCreateToolhelp32Snapshot = + (CREATESNAPSHOT) GetProcAddress(h, "CreateToolhelp32Snapshot"); + myProcess32First = + (PROCESSWALK) GetProcAddress(h, "Process32First"); + myProcess32Next = (PROCESSWALK) GetProcAddress(h, "Process32Next"); + myEnumProcessModules = dummyprocessmodules; + myGetModuleFileNameEx = GetModuleFileNameEx95; + if (myCreateToolhelp32Snapshot && myProcess32First + && myProcess32Next) +#if 0 + /* + * This doesn't work after all on Win98 SE + */ + query = CW_GETPINFO_FULL; +#else + query = CW_GETPINFO; +#endif + else + snmp_log(LOG_ERR, "hr_swrun failed non-NT init\n"); + } +#endif /* cygwin */ +#ifdef PROC_SYMBOL + auto_nlist(PROC_SYMBOL, 0, 0); +#endif +#ifdef NPROC_SYMBOL + auto_nlist(NPROC_SYMBOL, 0, 0); +#endif + + proc_table = 0; + + REGISTER_MIB("host/hr_swrun", hrswrun_variables, variable4, + hrswrun_variables_oid); + REGISTER_MIB("host/hr_swrun", hrswrunperf_variables, variable4, + hrswrunperf_variables_oid); +} + +/* + * header_hrswrun(... + * Arguments: + * vp IN - pointer to variable entry that points here + * name IN/OUT - IN/name requested, OUT/name found + * length IN/OUT - length of IN/OUT oid's + * exact IN - TRUE if an exact match was requested + * var_len OUT - length of variable or 0 if function returned + * write_method + * + */ + +int +header_hrswrun(struct variable *vp, + oid * name, + size_t * length, + int exact, size_t * var_len, WriteMethod ** write_method) +{ +#define HRSWRUN_NAME_LENGTH 9 + oid newname[MAX_OID_LEN]; + int result; + + DEBUGMSGTL(("host/hr_swrun", "var_hrswrun: ")); + DEBUGMSGOID(("host/hr_swrun", name, *length)); + DEBUGMSG(("host/hr_swrun", " %d\n", exact)); + + memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid)); + newname[HRSWRUN_NAME_LENGTH] = 0; + result = snmp_oid_compare(name, *length, newname, vp->namelen + 1); + if ((exact && (result != 0)) || (!exact && (result >= 0))) + return (MATCH_FAILED); + memcpy((char *) name, (char *) newname, + (vp->namelen + 1) * sizeof(oid)); + *length = vp->namelen + 1; + + *write_method = 0; + *var_len = sizeof(long); /* default to 'long' results */ + return (MATCH_SUCCEEDED); +} + +int +header_hrswrunEntry(struct variable *vp, + oid * name, + size_t * length, + int exact, + size_t * var_len, WriteMethod ** write_method) +{ +#define HRSWRUN_ENTRY_NAME_LENGTH 11 + oid newname[MAX_OID_LEN]; + int pid, LowPid = -1; + int result; + + DEBUGMSGTL(("host/hr_swrun", "var_hrswrunEntry: ")); + DEBUGMSGOID(("host/hr_swrun", name, *length)); + DEBUGMSG(("host/hr_swrun", " %d\n", exact)); + + memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid)); + + /* + * Find the "next" running process + */ + Init_HR_SWRun(); + for (;;) { + pid = Get_Next_HR_SWRun(); +#ifndef linux +#ifndef dynix + DEBUGMSG(("host/hr_swrun", + "(index %d (entry #%d) ....", pid, current_proc_entry)); +#else + DEBUGMSG(("host/hr_swrun", "pid %d; nextproc %d ....", pid, + nextproc)); +#endif +#endif + if (pid == -1) + break; + newname[HRSWRUN_ENTRY_NAME_LENGTH] = pid; + DEBUGMSGOID(("host/hr_swrun", newname, *length)); + DEBUGMSG(("host/hr_swrun", "\n")); + result = snmp_oid_compare(name, *length, newname, vp->namelen + 1); + if (exact && (result == 0)) { + LowPid = pid; +#ifdef cygwin + lowproc = *curproc; +#elif dynix + memcpy(&lowpsinfo, &mypsinfo, sizeof(prpsinfo_t)); +#elif !defined(linux) + LowProcIndex = current_proc_entry - 1; +#endif + DEBUGMSGTL(("host/hr_swrun", " saved\n")); + /* + * Save process status information + */ + break; + } + if ((!exact && (result < 0)) && (LowPid == -1 || pid < LowPid)) { + LowPid = pid; +#ifdef cygwin + lowproc = *curproc; +#elif !defined(linux) + LowProcIndex = current_proc_entry - 1; +#endif + /* + * Save process status information + */ + DEBUGMSG(("host/hr_swrun", " saved")); + } + DEBUGMSG(("host/hr_swrun", "\n")); + } + End_HR_SWRun(); + + if (LowPid == -1) { + DEBUGMSGTL(("host/hr_swrun", "... index out of range\n")); + return (MATCH_FAILED); + } + + newname[HRSWRUN_ENTRY_NAME_LENGTH] = LowPid; + memcpy((char *) name, (char *) newname, + (vp->namelen + 1) * sizeof(oid)); + *length = vp->namelen + 1; + *write_method = 0; + *var_len = sizeof(long); /* default to 'long' results */ + + DEBUGMSGTL(("host/hr_swrun", "... get process stats ")); + DEBUGMSGOID(("host/hr_swrun", name, *length)); + DEBUGMSG(("host/hr_swrun", "\n")); + return LowPid; +} + + /********************* + * + * System specific implementation functions + * + *********************/ + + +u_char * +var_hrswrun(struct variable * vp, + oid * name, + size_t * length, + int exact, size_t * var_len, WriteMethod ** write_method) +{ + int pid = 0; + static char string[1024]; +#ifdef HAVE_SYS_PSTAT_H + struct pst_status proc_buf; +#elif defined(solaris2) +#if _SLASH_PROC_METHOD_ + static psinfo_t psinfo; + static psinfo_t *proc_buf; + int procfd; + int ret; + char procfn[sizeof "/proc/00000/psinfo"]; +#else + static struct proc *proc_buf; + char *cp1; +#endif /* _SLASH_PROC_METHOD_ */ + static time_t when = 0; + time_t now; + static int oldpid = -1; +#endif +#if HAVE_KVM_GETPROCS + char **argv; +#endif +#ifdef linux + FILE *fp; + char buf[1024]; + int i; +#endif + char *cp; + + if (vp->magic == HRSWRUN_OSINDEX) { + if (header_hrswrun(vp, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + } else { + + pid = + header_hrswrunEntry(vp, name, length, exact, var_len, + write_method); + if (pid == MATCH_FAILED) + return NULL; + } + +#ifdef HAVE_SYS_PSTAT_H + if (pstat_getproc(&proc_buf, sizeof(struct pst_status), 0, pid) == -1) + return NULL; +#elif defined(solaris2) + time(&now); + if (pid == oldpid) { + if (now != when) + oldpid = -1; + } + if (oldpid != pid || proc_buf == NULL) { +#if _SLASH_PROC_METHOD_ + proc_buf = &psinfo; + sprintf(procfn, "/proc/%.5d/psinfo", pid); + if ((procfd = open(procfn, O_RDONLY)) != -1) { + ret = read(procfd, proc_buf, sizeof(*proc_buf)); + close(procfd); + if (ret != sizeof(*proc_buf)) + proc_buf = NULL; + } else + proc_buf = NULL; +#else + if (kd == NULL) + return NULL; + if ((proc_buf = kvm_getproc(kd, pid)) == NULL) + return NULL; +#endif + oldpid = pid; + when = now; + } +#endif + + switch (vp->magic) { + case HRSWRUN_OSINDEX: +#if NETSNMP_NO_DUMMY_VALUES + return NULL; +#else + /* + * per dts, on coders: + * cos (in general) we won't know which process should + * be regarded as "the primary O/S process". + * The most obvious candidate on a Unix box is probably 'init' + * which is typically (always?) process #1. + */ + long_return = 1; /* Probably! */ + return (u_char *) & long_return; +#endif + + case HRSWRUN_INDEX: + long_return = pid; + return (u_char *) & long_return; + case HRSWRUN_NAME: +#ifdef HAVE_SYS_PSTAT_H + snprintf(string, sizeof(string), "%s", proc_buf.pst_cmd); + string[ sizeof(string)-1 ] = 0; + cp = strchr(string, ' '); + if (cp != NULL) + *cp = '\0'; +#elif defined(dynix) + snprintf(string, sizeof(string), "%s", lowpsinfo.pr_fname); + string[ sizeof(string)-1 ] = 0; + cp = strchr(string, ' '); + if (cp != NULL) + *cp = '\0'; +#elif defined(solaris2) +#if _SLASH_PROC_METHOD_ + if (proc_buf) { + char *pos=strchr(proc_buf->pr_psargs,' '); + if (pos != NULL) *pos = '\0'; + strlcpy(string, basename(proc_buf->pr_psargs),sizeof(string)); + if (pos != NULL) *pos=' '; + } else { + strcpy(string, "<exited>"); + } + string[ sizeof(string)-1 ] = 0; +#else + strncpy(string, proc_buf->p_user.u_comm, sizeof(string)); + string[ sizeof(string)-1 ] = 0; +#endif +#elif defined(aix4) || defined(aix5) || defined(aix6) + strncpy(string, proc_table[LowProcIndex].pi_comm, sizeof(string)); + string[ sizeof(string)-1 ] = 0; + cp = strchr(string, ' '); + if (cp != NULL) + *cp = '\0'; +#elif HAVE_KVM_GETPROCS + #if defined(freebsd5) && __FreeBSD_version >= 500014 + strcpy(string, proc_table[LowProcIndex].ki_comm); + #else + strcpy(string, proc_table[LowProcIndex].kp_proc.p_comm); + #endif +#elif defined(linux) + sprintf(string, "/proc/%d/status", pid); + if ((fp = fopen(string, "r")) == NULL) { + strcpy(string, "<exited>"); + *var_len = strlen(string); + return (u_char *) string; + } + fgets(buf, sizeof(buf), fp); /* Name: process name */ + cp = buf; + while (*cp != ':') + ++cp; + ++cp; + while (isspace(*cp)) + ++cp; + strcpy(string, cp); + fclose(fp); +#elif defined(cygwin) + /* if (lowproc.process_state & (PID_ZOMBIE | PID_EXITED)) */ + if (lowproc.process_state & PID_EXITED || (lowproc.exitcode & ~0xffff)) + strcpy(string, "<defunct>"); + else if (lowproc.ppid) { + cygwin_conv_to_posix_path(lowproc.progname, string); + cp = strrchr(string, '/'); + if (cp) + strcpy(string, cp + 1); + } else if (query == CW_GETPINFO_FULL) { + DWORD n = lowproc.dwProcessId & 0xffff; + HANDLE h = + OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, n); + + if (h) { + HMODULE hm[1000]; + if (!myEnumProcessModules(h, hm, sizeof hm, &n)) { + snmp_log(LOG_DEBUG, "no module handle for %lu\n", n); + n = 0; + } + if (n + && myGetModuleFileNameEx(h, hm[0], string, + sizeof string)) { + cp = strrchr(string, '\\'); + if (cp) + strcpy(string, cp + 1); + } else + strcpy(string, "*** unknown"); + CloseHandle(h); + } else { + snmp_log(LOG_INFO, "no process handle for %lu\n", n); + strcpy(string, "** unknown"); + } + } else + strcpy(string, "* unknown"); + cp = strchr(string, '\0') - 4; + if (cp > string && strcasecmp(cp, ".exe") == 0) + *cp = '\0'; +#else +#if NETSNMP_NO_DUMMY_VALUES + return NULL; +#endif + sprintf(string, "process name"); +#endif + *var_len = strlen(string); + /* + * remove trailing newline + */ + if (*var_len) { + cp = string + *var_len - 1; + if (*cp == '\n') + --(*var_len); + } + if (*var_len > 64) { /* MIB limit */ + *var_len = 64; + string[64] = '\0'; + } + return (u_char *) string; + case HRSWRUN_ID: + *var_len = nullOidLen; + return (u_char *) nullOid; + case HRSWRUN_PATH: +#ifdef HAVE_SYS_PSTAT_H + /* + * Path not available - use argv[0] + */ + sprintf(string, "%s", proc_buf.pst_cmd); + cp = strchr(string, ' '); + if (cp != NULL) + *cp = '\0'; +#elif defined(dynix) + /* + * Path not available - use argv[0] + */ + sprintf(string, "%s", lowpsinfo.pr_psargs); + cp = strchr(string, ' '); + if (cp != NULL) + *cp = '\0'; +#elif defined(solaris2) +#ifdef _SLASH_PROC_METHOD_ + if (proc_buf) + strcpy(string, proc_buf->pr_psargs); + else + sprintf(string, "<exited>"); + cp = strchr(string, ' '); + if (cp) + *cp = 0; +#else + cp = proc_buf->p_user.u_psargs; + cp1 = string; + while (*cp && *cp != ' ') + *cp1++ = *cp++; + *cp1 = 0; +#endif +#elif defined(aix4) || defined(aix5) || defined(aix6) + strncpy(string, proc_table[LowProcIndex].pi_comm, sizeof(string)); + string[ sizeof(string)-1 ] = 0; + cp = strchr(string, ' '); + if (cp != NULL) + *cp = '\0'; +#elif HAVE_KVM_GETPROCS + #if defined(freebsd5) && __FreeBSD_version >= 500014 + strcpy(string, proc_table[LowProcIndex].ki_comm); + #else + strcpy(string, proc_table[LowProcIndex].kp_proc.p_comm); + #endif +#elif defined(linux) + sprintf(string, "/proc/%d/cmdline", pid); + if ((fp = fopen(string, "r")) == NULL) { + strcpy(string, "<exited>"); + *var_len = strlen(string); + return (u_char *) string; + } + if (fgets(buf, sizeof(buf) - 1, fp)) /* argv[0] '\0' argv[1] '\0' .... */ + strcpy(string, buf); + else { + /* + * swapped out - no cmdline + */ + fclose(fp); + sprintf(string, "/proc/%d/status", pid); + if ((fp = fopen(string, "r")) == NULL) + return NULL; + if (!fgets(buf, sizeof(buf), fp)) { + fclose(fp); + return NULL; /* the process probably died */ + } + cp = strchr(buf, ':'); + if ( cp == NULL ) { + fclose(fp); + return NULL; /* the process file is malformed */ + } + ++cp; + while (isspace(*cp)) + ++cp; + strcpy(string, cp); + cp = strchr(string, '\n'); + if (cp) + *cp = 0; + } + fclose(fp); +#elif defined(cygwin) + /* if (lowproc.process_state & (PID_ZOMBIE | PID_EXITED)) */ + if (lowproc.process_state & PID_EXITED || (lowproc.exitcode & ~0xffff)) + strcpy(string, "<defunct>"); + else if (lowproc.ppid) + cygwin_conv_to_posix_path(lowproc.progname, string); + else if (query == CW_GETPINFO_FULL) { + DWORD n = lowproc.dwProcessId & 0xFFFF; + HANDLE h = + OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, n); + if (h) { + HMODULE hm[1000]; + if (!myEnumProcessModules(h, hm, sizeof hm, &n)) + n = 0; + if (!n + || !myGetModuleFileNameEx(h, hm[0], string, + sizeof string)) + strcpy(string, "*** unknown"); + CloseHandle(h); + } else + strcpy(string, "** unknown"); + } else + strcpy(string, "* unknown"); +#else +#if NETSNMP_NO_DUMMY_VALUES + return NULL; +#endif + sprintf(string, "/bin/wombat"); +#endif + *var_len = strlen(string); + if (*var_len > 128) { /* MIB limit */ + *var_len = 128; + string[128] = '\0'; + } + return (u_char *) string; + case HRSWRUN_PARAMS: +#ifdef HAVE_SYS_PSTAT_H + cp = strchr(proc_buf.pst_cmd, ' '); + if (cp != NULL) { + cp++; + sprintf(string, "%s", cp); + } else + string[0] = '\0'; +#elif defined(dynix) + cp = strchr(lowpsinfo.pr_psargs, ' '); + if (cp != NULL) { + cp++; + sprintf(string, "%s", cp); + } else + string[0] = '\0'; +#elif defined(solaris2) +#ifdef _SLASH_PROC_METHOD_ + if (proc_buf) { + cp = strchr(proc_buf->pr_psargs, ' '); + if (cp) + strcpy(string, cp + 1); + else + string[0] = 0; + } else + string[0] = 0; +#else + cp = proc_buf->p_user.u_psargs; + while (*cp && *cp != ' ') + cp++; + if (*cp == ' ') + cp++; + strcpy(string, cp); +#endif +#elif defined(aix4) || defined(aix5) || defined(aix6) + cp = strchr(proc_table[LowProcIndex].pi_comm, ' '); + if (cp != NULL) { + cp++; + sprintf(string, "%s", cp); + } else + string[0] = '\0'; +#elif HAVE_KVM_GETPROCS + string[0] = 0; + argv = kvm_getargv(kd, proc_table + LowProcIndex, sizeof(string)); + if (argv) + argv++; + while (argv && *argv) { + if (string[0] != 0) + strcat(string, " "); + strcat(string, *argv); + argv++; + } +#elif defined(linux) + sprintf(string, "/proc/%d/cmdline", pid); + if ((fp = fopen(string, "r")) == NULL) { + strcpy(string, ""); + *var_len = 0; + return (u_char *) string; + } + memset(buf, 0, sizeof(buf)); + + /* + * argv[0] '\0' argv[1] '\0' .... + */ + if (!fgets(buf, sizeof(buf) - 2, fp)) { + /* + * maybe be empty (even argv[0] is missing) + */ + string[0] = '\0'; + *var_len = 0; + fclose(fp); + return string; + } + + /* + * Skip over argv[0] + */ + cp = buf; + while (*cp) + ++cp; + ++cp; + /* + * Now join together separate arguments. + */ + while (1) { + while (*cp) + ++cp; + if (*(cp + 1) == '\0') + break; /* '\0''\0' => End of command line */ + *cp = ' '; + } + + cp = buf; + while (*cp) + ++cp; + ++cp; + strcpy(string, cp); + fclose(fp); +#elif defined(cygwin) + string[0] = 0; +#else +#if NETSNMP_NO_DUMMY_VALUES + return NULL; +#endif + sprintf(string, "-h -q -v"); +#endif + *var_len = strlen(string); + if (*var_len > 128) { /* MIB limit */ + *var_len = 128; + string[128] = '\0'; + } + return (u_char *) string; + case HRSWRUN_TYPE: +#ifdef PID_MAXSYS + if (pid < PID_MAXSYS) + long_return = 2; /* operatingSystem */ + else + long_return = 4; /* application */ +#elif defined(aix4) || defined(aix5) || defined(aix6) + if (proc_table[LowProcIndex].pi_flags & SKPROC) { + long_return = 2; /* kernel process */ + } else + long_return = 4; /* application */ +#elif HAVE_KVM_GETPROCS + #if defined(freebsd5) && __FreeBSD_version >= 500014 + if (proc_table[LowProcIndex].ki_flag & P_SYSTEM) { + if (proc_table[LowProcIndex].ki_pri.pri_class == PRI_ITHD) + long_return = 3;/* deviceDriver */ + else + long_return = 2;/* operatingSystem */ + } else + long_return = 4; /* application */ + #else + if (proc_table[LowProcIndex].kp_proc.p_flag & P_SYSTEM) + long_return = 2; /* operatingSystem */ + else + long_return = 4; /* application */ + #endif +#else + long_return = 4; /* application */ +#endif + return (u_char *) & long_return; + case HRSWRUN_STATUS: +#if defined(cygwin) + if (lowproc.process_state & PID_STOPPED) + long_return = 3; /* notRunnable */ + /* else if (lowproc.process_state & PID_ZOMBIE) */ + else if (lowproc.exitcode & ~0xffff) + long_return = 4; /* invalid */ + else + long_return = 1; /* running */ +#elif !defined(linux) +#if defined(hpux10) || defined(hpux11) + switch (proc_table[LowProcIndex].pst_stat) { + case PS_STOP: + long_return = 3; /* notRunnable */ + break; + case PS_SLEEP: + long_return = 2; /* runnable */ + break; + case PS_RUN: + long_return = 1; /* running */ + break; + case PS_ZOMBIE: + case PS_IDLE: + case PS_OTHER: + default: + long_return = 4; /* invalid */ + break; + } +#else +#if HAVE_KVM_GETPROCS + #if defined(freebsd5) && __FreeBSD_version >= 500014 + switch (proc_table[LowProcIndex].ki_stat) { + #else + switch (proc_table[LowProcIndex].kp_proc.p_stat) { + #endif +#elif defined(dynix) + switch (lowpsinfo.pr_state) { +#elif defined(solaris2) +#if _SLASH_PROC_METHOD_ + switch (proc_buf ? proc_buf->pr_lwp.pr_state : SIDL) { +#else + switch (proc_buf->p_stat) { +#endif +#elif defined(aix4) || defined(aix5) || defined(aix6) + switch (proc_table[LowProcIndex].pi_state) { +#else + switch (proc_table[LowProcIndex].p_stat) { +#endif + case SSTOP: + long_return = 3; /* notRunnable */ + break; + case 0: +#ifdef SSWAP + case SSWAP: +#endif +#ifdef SSLEEP + case SSLEEP: +#endif +#ifdef SWAIT + case SWAIT: +#endif + long_return = 2; /* runnable */ + break; +#ifdef SACTIVE + case SACTIVE: +#endif +#ifdef SRUN + case SRUN: +#endif +#ifdef SONPROC + case SONPROC: +#endif + long_return = 1; /* running */ + break; + case SIDL: + case SZOMB: + default: + long_return = 4; /* invalid */ + break; + } +#endif +#else + sprintf(string, "/proc/%d/stat", pid); + if ((fp = fopen(string, "r")) != NULL) { + fgets(buf, sizeof(buf), fp); + cp = buf; + for (i = 0; i < 2; ++i) { /* skip two fields */ + while (*cp != ' ') + ++cp; + ++cp; + } + + switch (*cp) { + case 'R': + long_return = 1; /* running */ + break; + case 'S': + long_return = 2; /* runnable */ + break; + case 'D': + case 'T': + long_return = 3; /* notRunnable */ + break; + case 'Z': + default: + long_return = 4; /* invalid */ + break; + } + fclose(fp); + } else + long_return = 4; /* invalid */ +#endif + return (u_char *) & long_return; + + case HRSWRUNPERF_CPU: +#ifdef HAVE_SYS_PSTAT_H + long_return = proc_buf.pst_cptickstotal; + /* + * Not convinced this is right, but.... + */ +#elif defined(dynix) + long_return = lowpsinfo.pr_time.tv_sec * 100 + + lowpsinfo.pr_time.tv_nsec / 10000000; +#elif defined(solaris2) +#if _SLASH_PROC_METHOD_ + long_return = proc_buf ? proc_buf->pr_time.tv_sec * 100 + + proc_buf->pr_time.tv_nsec / 10000000 : 0; +#else + long_return = proc_buf->p_utime * 100 + proc_buf->p_stime * 100; +#endif +#elif HAVE_KVM_GETPROCS + #if defined(NOT_DEFINED) && defined(freebsd5) && __FreeBSD_version >= 500014 + /* XXX: Accessing ki_paddr causes sig10 ... + long_return = proc_table[LowProcIndex].ki_paddr->p_uticks + + proc_table[LowProcIndex].ki_paddr->p_sticks + + proc_table[LowProcIndex].ki_paddr->p_iticks; */ + long_return = 0; + #elif defined(freebsd5) + long_return = proc_table[LowProcIndex].ki_runtime / 100000; + #else + long_return = proc_table[LowProcIndex].kp_proc.p_uticks + + proc_table[LowProcIndex].kp_proc.p_sticks + + proc_table[LowProcIndex].kp_proc.p_iticks; + #endif +#elif defined(linux) + sprintf(string, "/proc/%d/stat", pid); + if ((fp = fopen(string, "r")) == NULL) { + long_return = 0; + return (u_char *) & long_return; + } + fgets(buf, sizeof(buf), fp); + cp = buf; + for (i = 0; i < 13; ++i) { /* skip 13 fields */ + while (*cp != ' ') + ++cp; + ++cp; + } + + long_return = atoi(cp); /* utime */ + + while (*cp != ' ') + ++cp; + ++cp; + long_return += atoi(cp); /* + stime */ + fclose(fp); +#elif defined(sunos4) + long_return = proc_table[LowProcIndex].p_time; +#elif defined(cygwin) + { + DWORD n = lowproc.dwProcessId; + HANDLE h = + OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, n); + FILETIME ct, et, kt, ut; + + if (h) { + if (GetProcessTimes(h, &ct, &et, &kt, &ut)) + long_return = (to_msec(&kt) + to_msec(&ut)) / 10; + else { + snmp_log(LOG_INFO, "no process times for %lu (%lu)\n", + lowproc.pid, n); + long_return = 0; + } + CloseHandle(h); + } else { + snmp_log(LOG_INFO, "no process handle for %lu (%lu)\n", + lowproc.pid, n); + long_return = 0; + } + } +#elif defined(aix4) || defined(aix5) || defined(aix6) + long_return = proc_table[LowProcIndex].pi_ru.ru_utime.tv_sec * 100 + + proc_table[LowProcIndex].pi_ru.ru_utime.tv_usec / 10000000 + /* nanoseconds */ + proc_table[LowProcIndex].pi_ru.ru_stime.tv_sec * 100 + + proc_table[LowProcIndex].pi_ru.ru_stime.tv_usec / 10000000; /* nanoseconds */ +#else + long_return = proc_table[LowProcIndex].p_utime.tv_sec * 100 + + proc_table[LowProcIndex].p_utime.tv_usec / 10000 + + proc_table[LowProcIndex].p_stime.tv_sec * 100 + + proc_table[LowProcIndex].p_stime.tv_usec / 10000; +#endif + return (u_char *) & long_return; + case HRSWRUNPERF_MEM: +#ifdef HAVE_SYS_PSTAT_H +# ifdef PGSHIFT + long_return = (proc_buf.pst_rssize << PGSHIFT) / 1024; +# else + long_return = proc_buf.pst_rssize * getpagesize() / 1024; +# endif +#elif defined(dynix) + long_return = (lowpsinfo.pr_rssize * MMU_PAGESIZE) / 1024; +#elif defined(solaris2) +#if _SLASH_PROC_METHOD_ +#ifdef _ILP32 + if(NULL != proc_buf && 0 == proc_buf->pr_rssize) + { /* Odds on that we are looking with a 32 bit app at a 64 bit psinfo.*/ + netsnmp_memory_info *mem; + netsnmp_memory_load(); + mem = netsnmp_memory_get_byIdx( NETSNMP_MEM_TYPE_PHYSMEM, 0 ); + if (!mem) + { + snmp_log(LOG_INFO, "netsnmp_memory_get_byIdx returned NULL pointer\n"); + long_return = 0;/* Tried my best, giving up.*/ + } + else + {/* 0x8000 is the maximum range of pr_pctmem. devision of 1024 is to go from B to kB*/ + uint32_t pct_unit = (mem->size/0x8000) * (mem->units/1024); + long_return = proc_buf ? proc_buf->pr_pctmem * pct_unit : 0; + } + } + else + { + long_return = proc_buf ? proc_buf->pr_rssize : 0; + + } +#else /*_LP64*/ + long_return = proc_buf ? proc_buf->pr_rssize : 0; +#endif /*_LP64*/ + +#else + long_return = proc_buf->p_swrss; +#endif +#elif defined(aix4) || defined(aix5) || defined(aix6) + long_return = proc_table[LowProcIndex].pi_size * getpagesize() / 1024; +#elif HAVE_KVM_GETPROCS && !defined(darwin8) + #if defined(NOT_DEFINED) && defined(freebsd5) && __FreeBSD_version >= 500014 + /* XXX + long_return = proc_table[LowProcIndex].ki_vmspace->vm_tsize + + proc_table[LowProcIndex].ki_vmspace->vm_ssize + + proc_table[LowProcIndex].ki_vmspace->vm_dsize; + long_return = long_return * (getpagesize() / 1024); */ + long_return = 0; + #elif defined(freebsd3) && !defined(darwin) + long_return = + #if defined(freebsd5) + proc_table[LowProcIndex].ki_size / 1024; + #else + proc_table[LowProcIndex].kp_eproc.e_vm.vm_map.size / 1024; + #endif + #else + long_return = proc_table[LowProcIndex].kp_eproc.e_vm.vm_tsize + + proc_table[LowProcIndex].kp_eproc.e_vm.vm_ssize + + proc_table[LowProcIndex].kp_eproc.e_vm.vm_dsize; + long_return = long_return * (getpagesize() / 1024); + #endif +#elif defined(linux) + sprintf(string, "/proc/%d/stat", pid); + if ((fp = fopen(string, "r")) == NULL) { + long_return = 0; + return (u_char *) & long_return; + } + fgets(buf, sizeof(buf), fp); + cp = buf; + for (i = 0; i < 23; ++i) { /* skip 23 fields */ + while (*cp != ' ') + ++cp; + ++cp; + } + long_return = atoi(cp) * (getpagesize() / 1024); /* rss */ + fclose(fp); +#elif defined(cygwin) + { + DWORD n = lowproc.dwProcessId; + HANDLE h = + OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, n); + PROCESS_MEMORY_COUNTERS pmc; + + if (h) { + if (myGetProcessMemoryInfo + && myGetProcessMemoryInfo(h, &pmc, sizeof pmc)) + long_return = pmc.WorkingSetSize / 1024; + else { + snmp_log(LOG_INFO, "no process times for %lu (%lu)\n", + lowproc.pid, n); + long_return = 0; + } + CloseHandle(h); + } else { + snmp_log(LOG_INFO, "no process handle for %lu (%lu)\n", + lowproc.pid, n); + long_return = 0; + } + } +#else +#if NETSNMP_NO_DUMMY_VALUES + return NULL; +#endif + long_return = 16 * 1024; /* XXX - 16M! */ +#endif + return (u_char *) & long_return; + default: + DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrswrun\n", + vp->magic)); + } + return NULL; +} + + + /********************* + * + * Internal implementation functions + * + *********************/ + +#if defined(linux) + +DIR *procdir = NULL; +struct dirent *procentry_p; + +void +Init_HR_SWRun(void) +{ + if (procdir != NULL) + closedir(procdir); + procdir = opendir("/proc"); +} + +int +Get_Next_HR_SWRun(void) +{ + int pid; + if (procdir == NULL) + return -1; + procentry_p = readdir(procdir); + + if (procentry_p == NULL) + return -1; + + pid = atoi(procentry_p->d_name); + if (pid == 0) + return (Get_Next_HR_SWRun()); + return pid; +} + +void +End_HR_SWRun(void) +{ + if (procdir) + closedir(procdir); + procdir = NULL; +} + +#elif defined(cygwin) + +static pid_t curpid; + +void +Init_HR_SWRun(void) +{ + cygwin_internal(CW_LOCK_PINFO, 1000); + curpid = 0; +} + +int +Get_Next_HR_SWRun(void) +{ + curproc = + (struct external_pinfo *) cygwin_internal(query, + curpid | CW_NEXTPID); + if (curproc) + curpid = curproc->pid; + else { + curpid = -1; + } + return curpid; +} + +void +End_HR_SWRun(void) +{ + cygwin_internal(CW_UNLOCK_PINFO); +} + +#elif defined(dynix) + +void +Init_HR_SWRun(void) +{ + nextproc = 0; +} + +int +Get_Next_HR_SWRun(void) +{ + getprpsinfo_t *select = 0; + + DEBUGMSGTL(("host/hr_swrun::GetNextHR_SWRun", + "nextproc == %d... &nextproc = %u\n", nextproc, + &nextproc)); + if ((nextproc = getprpsinfo(nextproc, select, &mypsinfo)) < 0) { + return -1; + } else { + DEBUGMSGTL(("host/hr_swrun::GetNextHR_SWRun", + "getprpsinfo returned %d\n", nextproc)); + return mypsinfo.pr_pid; + } + +} + +void +End_HR_SWRun(void) +{ + /* + * just a stub... because it's declared + */ +} + +#else /* linux */ + +static int nproc; + +void +Init_HR_SWRun(void) +{ + size_t bytes; + static time_t iwhen = 0; + time_t now; + + time(&now); + if (now == iwhen) { + current_proc_entry = 0; + return; + } + iwhen = now; + +#if defined(hpux10) || defined(hpux11) + pstat_getdynamic(&pst_dyn, sizeof(struct pst_dynamic), 1, 0); + nproc = pst_dyn.psd_activeprocs; + bytes = nproc * sizeof(struct pst_status); + if ((proc_table = + (struct pst_status *) realloc(proc_table, bytes)) == NULL) { + current_proc_entry = nproc + 1; + return; + } + pstat_getproc(proc_table, sizeof(struct pst_status), nproc, 0); + +#elif defined(solaris2) + if (getKstatInt("unix", "system_misc", "nproc", &nproc)) { + current_proc_entry = nproc + 1; + return; + } + bytes = nproc * sizeof(int); + if ((proc_table = (int *) realloc(proc_table, bytes)) == NULL) { + current_proc_entry = nproc + 1; + return; + } + { + DIR *f; + struct dirent *dp; +#if _SLASH_PROC_METHOD_ == 0 + if (kd == NULL) { + current_proc_entry = nproc + 1; + return; + } +#endif + f = opendir("/proc"); + current_proc_entry = 0; + while ((dp = readdir(f)) != NULL && current_proc_entry < nproc) + if (dp->d_name[0] != '.') + proc_table[current_proc_entry++] = atoi(dp->d_name); + /* + * if we are in a Solaris zone, nproc > current_proc_entry ! + * but we only want the processes from the local zone + */ + if (current_proc_entry != nproc) + nproc = current_proc_entry; + closedir(f); + } +#elif defined(aix4) || defined(aix5) || defined(aix6) + { + pid_t proc_index = 0; + int avail = 1024; + if (proc_table) { + free(proc_table); + } + nproc = 0; + proc_table = malloc(sizeof(proc_table[0]) * avail); + for (;;) { + int got; + if (!proc_table) { + nproc = 0; + snmp_log_perror("Init_HR_SWRun-malloc"); + return; + } + got = getprocs(proc_table + nproc, sizeof(proc_table[0]), + 0, sizeof(struct fdsinfo), + &proc_index, avail - nproc); + nproc += got; + if (nproc < avail) { + break; + } + avail += 1024; + proc_table = realloc(proc_table, avail * sizeof(proc_table[0])); + } + } +#elif HAVE_KVM_GETPROCS + { + if (kd == NULL) { + nproc = 0; + return; + } + proc_table = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc); + } +#else + + current_proc_entry = 1; +#ifndef bsdi2 + nproc = 0; + + if (auto_nlist(NPROC_SYMBOL, (char *) &nproc, sizeof(int)) == 0) { + snmp_log_perror("Init_HR_SWRun-auto_nlist NPROC"); + return; + } +#endif + bytes = nproc * sizeof(struct proc); + + if (proc_table) + free((char *) proc_table); + if ((proc_table = (struct proc *) malloc(bytes)) == NULL) { + nproc = 0; + snmp_log_perror("Init_HR_SWRun-malloc"); + return; + } + + { + int proc_table_base; + if (auto_nlist + (PROC_SYMBOL, (char *) &proc_table_base, + sizeof(proc_table_base)) == 0) { + nproc = 0; + snmp_log_perror("Init_HR_SWRun-auto_nlist PROC"); + return; + } + if (NETSNMP_KLOOKUP(proc_table_base, (char *) proc_table, bytes) == 0) { + nproc = 0; + snmp_log_perror("Init_HR_SWRun-klookup"); + return; + } + } +#endif + current_proc_entry = 0; +} + +int +Get_Next_HR_SWRun(void) +{ + while (current_proc_entry < nproc) { +#if defined(hpux10) || defined(hpux11) + return proc_table[current_proc_entry++].pst_pid; +#elif defined(solaris2) + return proc_table[current_proc_entry++]; +#elif HAVE_KVM_GETPROCS + #if defined(freebsd5) && __FreeBSD_version >= 500014 + if (proc_table[current_proc_entry].ki_stat != 0) + return proc_table[current_proc_entry++].ki_pid; + #else + if (proc_table[current_proc_entry].kp_proc.p_stat != 0) + return proc_table[current_proc_entry++].kp_proc.p_pid; + #endif +#elif defined(aix4) || defined(aix5) || defined(aix6) + if (proc_table[current_proc_entry].pi_state != 0) + return proc_table[current_proc_entry++].pi_pid; + else + ++current_proc_entry; +#else + if (proc_table[current_proc_entry].p_stat != 0) + return proc_table[current_proc_entry++].p_pid; + else + ++current_proc_entry; +#endif + + } + return -1; +} + +void +End_HR_SWRun(void) +{ + current_proc_entry = nproc + 1; +} +#endif + +int +count_processes(void) +{ +#if !(defined(linux) || defined(cygwin) || defined(hpux10) || defined(hpux11) || defined(solaris2) || HAVE_KVM_GETPROCS || defined(dynix)) + int i; +#endif + int total = 0; + + Init_HR_SWRun(); +#if defined(hpux10) || defined(hpux11) || HAVE_KVM_GETPROCS || defined(solaris2) + total = nproc; +#else +#if defined(aix4) || defined(aix5) || defined(aix6) + for (i = 0; i < nproc; ++i) { + if (proc_table[i].pi_state != 0) +#elif !defined(linux) && !defined(cygwin) && !defined(dynix) + for (i = 0; i < nproc; ++i) { + if (proc_table[i].p_stat != 0) +#else + while (Get_Next_HR_SWRun() != -1) { +#endif + ++total; + } +#endif /* !hpux10 && !hpux11 && !HAVE_KVM_GETPROCS && !solaris2 */ + End_HR_SWRun(); + return total; +} |