int netsnmp_arch_swrun_container_load( netsnmp_container *container, u_int flags) { int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL}; size_t buf_size, mib_size = sizeof(mib)/sizeof(mib[0]); struct kinfo_proc *processes = NULL; struct proc_taskallinfo taskinfo; netsnmp_swrun_entry *entry; int rc, num_entries, i; DEBUGMSGTL(("swrun:load:arch"," load\n")); /* * get size to allocate. This introduces a bit of a race condition, * as the size could change between this call and the next... */ rc = sysctl(mib, mib_size, NULL, &buf_size, NULL, 0); if (rc < 0) { snmp_log(LOG_ERR, "KERN_PROC_ALL size sysctl failed: %d\n", rc); return -1; } processes = (struct kinfo_proc*) malloc(buf_size); if (NULL == processes) { snmp_log(LOG_ERR, "malloc failed\n"); return -1; } rc = sysctl(mib, mib_size, processes, &buf_size, NULL, 0); if (rc < 0) { snmp_log(LOG_ERR, "KERN_PROC_ALL sysctl failed: %d\n", rc); free(processes); return -1; } num_entries = buf_size / sizeof(struct kinfo_proc); for (i = 0; i < num_entries; i++) { /* * skip empty names. * p_stat = (SIDL|SRUN|SSLEEP|SSTOP|SZOMB) */ if (('\0' == processes[i].kp_proc.p_comm[0]) || (0 == processes[i].kp_proc.p_pid)) { DEBUGMSGTL(("swrun:load:arch", " skipping p_comm '%s', pid %5d, p_pstat %d\n", processes[i].kp_proc.p_comm ? processes[i].kp_proc.p_comm : "NULL", processes[i].kp_proc.p_pid, processes[i].kp_proc.p_stat)); continue; } DEBUGMSGTL(("swrun:load:arch"," %s pid %5d\n", processes[i].kp_proc.p_comm, processes[i].kp_proc.p_pid)); entry = netsnmp_swrun_entry_create(processes[i].kp_proc.p_pid); if (NULL == entry) continue; /* error already logged by function */ rc = CONTAINER_INSERT(container, entry); /* * p_comm is a partial name, but it is all we have at this point. */ entry->hrSWRunName_len = snprintf(entry->hrSWRunName, sizeof(entry->hrSWRunName)-1, "%s", processes[i].kp_proc.p_comm); /** sysctl for name, path, params */ rc = _set_command_name(entry); /* * map p_stat to RunStatus. Odd that there is no 'running' status. */ switch(processes[i].kp_proc.p_stat) { case SRUN: entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNABLE; break; case SSLEEP: case SSTOP: entry->hrSWRunStatus = HRSWRUNSTATUS_NOTRUNNABLE; break; case SIDL: case SZOMB: default: entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID; break; } /* * check for system processes */ if (P_SYSTEM & processes[i].kp_proc.p_flag) { entry->hrSWRunType = HRSWRUNTYPE_OPERATINGSYSTEM; DEBUGMSGTL(("swrun:load:arch", SWRUNINDENT "SYSTEM\n")); } else entry->hrSWRunType = HRSWRUNTYPE_APPLICATION; /* * get mem size, run time */ rc = proc_pidinfo( processes[i].kp_proc.p_pid, PROC_PIDTASKALLINFO, 0, &taskinfo, sizeof(taskinfo)); if (sizeof(taskinfo) != rc) { DEBUGMSGTL(("swrun:load:arch", " proc_pidinfo returned %d\n", rc)); } else { uint64_t task_mem = taskinfo.ptinfo.pti_resident_size / 1024; union { u_quad_t uq; /* u_int64_t */ UnsignedWide uw; /* struct u_int32_t hi/lo */ } at, ns; at.uq = taskinfo.ptinfo.pti_total_user + taskinfo.ptinfo.pti_total_system; ns = at; ns.uq = ns.uq / 10000000LL; /* nano to deci */ if (task_mem > INT32_MAX) { DEBUGMSGTL(("swrun:load:arch", SWRUNINDENT "mem overflow\n")); task_mem = INT32_MAX; } if (ns.uq > INT32_MAX) { DEBUGMSGTL(("swrun:load:arch", SWRUNINDENT "time overflow\n")); ns.uq = INT32_MAX; } entry->hrSWRunPerfMem = task_mem; entry->hrSWRunPerfCPU = ns.uq; } } free(processes); DEBUGMSGTL(("swrun:load:arch"," loaded %d entries\n", (int)CONTAINER_SIZE(container))); return 0; }
/* --------------------------------------------------------------------- */ int netsnmp_arch_swrun_container_load( netsnmp_container *container, u_int flags) { DIR *procdir = NULL; struct dirent *procentry_p; FILE *fp; int pid, i; char buf[BUFSIZ], buf2[BUFSIZ], *cp; netsnmp_swrun_entry *entry; procdir = opendir("/proc"); if ( NULL == procdir ) { snmp_log( LOG_ERR, "Failed to open /proc" ); return -1; } /* * Walk through the list of processes in the /proc tree */ while ( NULL != (procentry_p = readdir( procdir ))) { pid = atoi( procentry_p->d_name ); if ( 0 == pid ) continue; /* Presumably '.' or '..' */ entry = netsnmp_swrun_entry_create(pid); if (NULL == entry) continue; /* error already logged by function */ /* * Now extract the interesting information * from the various /proc{PID}/ interface files */ /* * Name: process name */ snprintf( buf2, BUFSIZ, "/proc/%d/status", pid ); fp = fopen( buf2, "r" ); if (!fp) { netsnmp_swrun_entry_free(entry); continue; /* file (process) probably went away */ } memset(buf, 0, sizeof(buf)); if (fgets( buf, BUFSIZ-1, fp ) == NULL) { fclose(fp); netsnmp_swrun_entry_free(entry); continue; } fclose(fp); for ( cp = buf; *cp != ':'; cp++ ) ; while (isspace(*(++cp))) /* Skip ':' and following spaces */ ; entry->hrSWRunName_len = snprintf(entry->hrSWRunName, sizeof(entry->hrSWRunName)-1, "%s", cp); if ( '\n' == entry->hrSWRunName[ entry->hrSWRunName_len-1 ]) { entry->hrSWRunName[ entry->hrSWRunName_len-1 ] = '\0'; entry->hrSWRunName_len--; /* Stamp on trailing newline */ } /* * Command Line: * argv[0] '\0' argv[1] '\0' .... */ snprintf( buf2, BUFSIZ, "/proc/%d/cmdline", pid ); fp = fopen( buf2, "r" ); if (!fp) { netsnmp_swrun_entry_free(entry); continue; /* file (process) probably went away */ } memset(buf, 0, sizeof(buf)); if ((cp = fgets( buf, BUFSIZ-1, fp )) == NULL) { fclose(fp); netsnmp_swrun_entry_free(entry); continue; } fclose(fp); if ( cp ) { /* * argv[0] is hrSWRunPath */ entry->hrSWRunPath_len = snprintf(entry->hrSWRunPath, sizeof(entry->hrSWRunPath)-1, "%s", buf); /* * Stitch together argv[1..] to construct hrSWRunParameters */ cp = buf + entry->hrSWRunPath_len+1; while ( 1 ) { while (*cp) cp++; if ( '\0' == *(cp+1)) break; /* '\0''\0' => End of command line */ *cp = ' '; } entry->hrSWRunParameters_len = sprintf(entry->hrSWRunParameters, "%.*s", (int)sizeof(entry->hrSWRunParameters) - 1, buf + entry->hrSWRunPath_len + 1); } else { memcpy(entry->hrSWRunPath, entry->hrSWRunName, entry->hrSWRunName_len); entry->hrSWRunPath_len = entry->hrSWRunName_len; entry->hrSWRunParameters_len = 0; } /* * XXX - No information regarding system processes vs applications */ entry->hrSWRunType = HRSWRUNTYPE_APPLICATION; /* * {xxx} {xxx} STATUS {xxx}*10 UTIME STIME {xxx}*8 RSS */ snprintf( buf, BUFSIZ, "/proc/%d/stat", pid ); fp = fopen( buf, "r" ); if (!fp) { netsnmp_swrun_entry_free(entry); continue; /* file (process) probably went away */ } if (fgets( buf, BUFSIZ-1, fp ) == NULL) { fclose(fp); netsnmp_swrun_entry_free(entry); continue; } fclose(fp); cp = buf; while ( ' ' != *(cp++)) /* Skip first field */ ; while ( ' ' != *(cp++)) /* Skip second field */ ; switch (*cp) { case 'R': entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNING; break; case 'S': entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNABLE; break; case 'D': case 'T': entry->hrSWRunStatus = HRSWRUNSTATUS_NOTRUNNABLE; break; case 'Z': default: entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID; break; } for (i=10; i; i--) { /* Skip STATUS + 10 fields */ while (' ' != *(cp++)) ; cp++; } entry->hrSWRunPerfCPU = atoi( cp ); /* utime */ while ( ' ' != *(cp++)) ; cp++; /* Skip utime */ entry->hrSWRunPerfCPU += atoi( cp ); /* +stime */ for (i=8; i; i--) { /* Skip stime + 8 fields */ while (' ' != *(cp++)) ; cp++; } entry->hrSWRunPerfMem = atoi( cp ); /* rss */ entry->hrSWRunPerfMem *= (getpagesize()/1024); /* in kB */ CONTAINER_INSERT(container, entry); } closedir( procdir ); DEBUGMSGTL(("swrun:load:arch"," loaded %" NETSNMP_PRIz "d entries\n", CONTAINER_SIZE(container))); return 0; }
/* --------------------------------------------------------------------- */ int netsnmp_arch_swrun_container_load( netsnmp_container *container, u_int flags) { struct kinfo_proc *proc_table; int nprocs, i, rc; char buf[BUFSIZ], **argv, *cp; char *name, *path; netsnmp_swrun_entry *entry; if ( 0 == kd ) { DEBUGMSGTL(("swrun:load:arch"," Can't query kvm info\n")); return 1; /* No handle for retrieving process table */ } proc_table = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nprocs ); for ( i=0 ; i<nprocs; i++ ) { if ( 0 == proc_table[i].SWRUN_K_STAT ) continue; entry = netsnmp_swrun_entry_create(proc_table[i].SWRUN_K_PID); if (NULL == entry) continue; /* error already logged by function */ rc = CONTAINER_INSERT(container, entry); /* * There are two possible sources for the command being run: * - SWRUN_K_COMM (from the proc_table entry directly) * - running kvm_getargv on the process entry. * * We'll use argv[0] (if set) for hrSWRunPath, * since that might potentially contain the * absolute path to the running binary. * We'll use SWRUN_K_COMM for hrSWRunName, * and as an alternative for hrSWRunPath */ argv = kvm_getargv( kd, &(proc_table[i]), 0); entry->hrSWRunName_len = snprintf(entry->hrSWRunName, sizeof(entry->hrSWRunName)-1, "%s", proc_table[i].SWRUN_K_COMM); if ( argv && *argv) entry->hrSWRunPath_len = snprintf(entry->hrSWRunPath, sizeof(entry->hrSWRunPath)-1, "%s", argv[0]); else { memcpy( entry->hrSWRunPath, entry->hrSWRunName, entry->hrSWRunName_len ); entry->hrSWRunPath_len = entry->hrSWRunName_len; } /* * Stitch together the rest of argv[] to build hrSWRunParameters * * Note: * We add a separating space before each argv[] parameter, * *including* the first one. So we need to skip this * leading space (buf[0]) when setting hrSWRunParameters. * This is also why we cleared the first *two* characters * in the buffer initially. If there were no command-line * arguments, then buf[1] would still be a null string. */ buf[0] = '\0'; buf[1] = '\0'; if (argv) argv++; /* Skip argv[0] */ while ( argv && *argv ) { strcat(buf, " "); strcat(buf, *argv); argv++; } entry->hrSWRunParameters_len = snprintf(entry->hrSWRunParameters, sizeof(entry->hrSWRunParameters)-1, "%s", buf+1); entry->hrSWRunType = (P_SYSTEM & proc_table[i].SWRUN_K_FLAG) #ifdef SWRUN_K_CLASS ? ((PRI_ITHD == proc_table[i].SWRUN_K_CLASS) ? 3 /* device driver */ : 2 /* operating system */ ) #else ? 2 /* operating system */ #endif : 4 /* application */ ; switch (proc_table[i].SWRUN_K_STAT) { case SRUN: entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNING; break; case SSLEEP: case SWAIT: entry->hrSWRunStatus = HRSWRUNSTATUS_RUNNABLE; break; case SSTOP: case SLOCK: entry->hrSWRunStatus = HRSWRUNSTATUS_NOTRUNNABLE; break; case SIDL: case SZOMB: default: entry->hrSWRunStatus = HRSWRUNSTATUS_INVALID; break; } #if defined(freebsd5) && __FreeBSD_version >= 500014 # ifdef NOT_DEFINED Apparently following these pointers triggers a SIG10 error entry->hrSWRunPerfCPU = proc_table[i].ki_paddr->p_uticks; entry->hrSWRunPerfCPU += proc_table[i].ki_paddr->p_sticks; entry->hrSWRunPerfCPU += proc_table[i].ki_paddr->p_iticks; entry->hrSWRunPerfMem = proc_table[i].ki_vmspace->vm_tsize; entry->hrSWRunPerfMem += proc_table[i].ki_vmspace->vm_ssize; entry->hrSWRunPerfMem += proc_table[i].ki_vmspace->vm_dsize; entry->hrSWRunPerfMem *= (getpagesize()/1024); /* in kB */ # endif entry->hrSWRunPerfCPU = proc_table[i].ki_runtime / 100000; entry->hrSWRunPerfMem = proc_table[i].ki_size / 1024;; #else /* * early FreeBSD, NetBSD, OpenBSD */ entry->hrSWRunPerfCPU = proc_table[i].kp_proc.p_uticks; entry->hrSWRunPerfCPU += proc_table[i].kp_proc.p_sticks; entry->hrSWRunPerfCPU += proc_table[i].kp_proc.p_iticks; entry->hrSWRunPerfMem = proc_table[i].kp_eproc.e_vm.vm_tsize; entry->hrSWRunPerfMem += proc_table[i].kp_eproc.e_vm.vm_ssize; entry->hrSWRunPerfMem += proc_table[i].kp_eproc.e_vm.vm_dsize; entry->hrSWRunPerfMem *= (getpagesize() / 1024); #endif } /* * 'proc_table' is owned by the kvm library, * so shouldn't be freed here. */ DEBUGMSGTL(("swrun:load:arch"," loaded %d entries\n", CONTAINER_SIZE(container))); return 0; }