| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #include <net-snmp/net-snmp-config.h> |
| |
| #if HAVE_STDLIB_H |
| #include <stdlib.h> |
| #endif |
| #if HAVE_UNISTD_H |
| #include <unistd.h> |
| #endif |
| #if HAVE_STRING_H |
| #include <string.h> |
| #else |
| #include <strings.h> |
| #endif |
| #include <sys/types.h> |
| #if HAVE_NETINET_IN_H |
| #include <netinet/in.h> |
| #endif |
| #include <stdio.h> |
| #include <ctype.h> |
| #if TIME_WITH_SYS_TIME |
| # include <sys/time.h> |
| # include <time.h> |
| #else |
| # if HAVE_SYS_TIME_H |
| # include <sys/time.h> |
| # else |
| # include <time.h> |
| # endif |
| #endif |
| #if HAVE_SYS_SELECT_H |
| #include <sys/select.h> |
| #endif |
| #if HAVE_NETDB_H |
| #include <netdb.h> |
| #endif |
| #if HAVE_ARPA_INET_H |
| #include <arpa/inet.h> |
| #endif |
| #if HAVE_NCURSES_CURSES_H |
| #include <ncurses/curses.h> |
| #elif HAVE_CURSES_H |
| #include <curses.h> |
| #endif |
| #include <signal.h> |
| |
| #include <net-snmp/net-snmp-includes.h> |
| |
| void |
| usage(void) |
| { |
| fprintf(stderr, "Usage: snmpps [-Cp] [-Ca] [-C m | n | t] AGENT"); |
| snmp_parse_args_usage(stderr); |
| fprintf(stderr, "\n\n"); |
| snmp_parse_args_descriptions(stderr); |
| fprintf(stderr, "\nsnmpps options:\n"); |
| fprintf(stderr, |
| "\t-Cp\tShow hrSWRunPath instead of hrSWRunName\n"); |
| fprintf(stderr, |
| "\t-Ca\tShow hrSWRunParameters in addition to hrSWRunName/Path\n"); |
| fprintf(stderr, |
| "\t-Ct\tSort processes according to CPU time used\n"); |
| fprintf(stderr, |
| "\t-Cm\tSort processes according to memory usage\n"); |
| fprintf(stderr, |
| "\t-Cn\tSort processes by PID number (default)\n"); |
| } |
| |
| int command_args = 0, |
| command_path = 0; |
| int topsort = 'c'; |
| char *progname; |
| |
| static void |
| optProc(int argc, char *const *argv, int opt) |
| { |
| switch (opt) { |
| case 'C': |
| while (*optarg) { |
| switch (*optarg++) { |
| case 'a': |
| command_args = 1; |
| break; |
| case 'p': |
| command_path = 1; |
| break; |
| case 'm': |
| topsort = 'm'; |
| break; |
| case 'n': |
| topsort = 'n'; |
| break; |
| case 't': |
| topsort = 't'; |
| break; |
| |
| default: |
| fprintf(stderr, |
| "Unknown flag passed to -C: %c\n", optarg[-1]); |
| exit(1); |
| } |
| } |
| } |
| } |
| |
| struct hrSWRunTable { |
| u_long hrSWRunIndex; |
| char *hrSWRunName; |
| char *hrSWRunPath; |
| char *hrSWRunParameters; |
| u_long hrSWRunID; |
| u_long hrSWRunType; |
| u_long hrSWRunStatus; |
| u_long hrSWRunPerfMem; |
| u_long hrSWRunPerfCPU; |
| u_long hrSWRunPerfCPUInc; |
| }; |
| |
| struct cpuStats { |
| u_long user; |
| u_long nice; |
| u_long system; |
| u_long idle; |
| u_long wait; |
| u_long kernel; |
| u_long intr; |
| u_long softintr; |
| u_long steal; |
| u_long guest; |
| u_long guestnice; |
| }; |
| |
| struct memStats { |
| u_long totalSwap; |
| u_long availSwap; |
| u_long totalReal; |
| u_long availReal; |
| u_long shared; |
| u_long buffer; |
| u_long cached; |
| }; |
| |
| struct laStats { |
| u_long la1; |
| u_long la5; |
| u_long la15; |
| }; |
| |
| |
| int |
| add(netsnmp_pdu *pdu, const char *mibnodename, |
| oid * index, size_t indexlen) |
| { |
| oid base[MAX_OID_LEN]; |
| size_t base_length = MAX_OID_LEN; |
| |
| memset(base, 0, MAX_OID_LEN * sizeof(oid)); |
| |
| if (!snmp_parse_oid(mibnodename, base, &base_length)) { |
| snmp_perror(mibnodename); |
| fprintf(stderr, "couldn't find mib node %s, giving up\n", |
| mibnodename); |
| #if HAVE_CURSES_H |
| endwin(); |
| #endif |
| exit(1); |
| } |
| |
| if (index && indexlen) { |
| memcpy(&(base[base_length]), index, indexlen * sizeof(oid)); |
| base_length += indexlen; |
| } |
| DEBUGMSGTL(("add", "created: ")); |
| DEBUGMSGOID(("add", base, base_length)); |
| DEBUGMSG(("add", "\n")); |
| snmp_add_null_var(pdu, base, base_length); |
| |
| return base_length; |
| } |
| |
| netsnmp_variable_list * |
| collect_procs(netsnmp_session *ss, netsnmp_pdu *pdu, |
| oid * base, size_t base_length) |
| { |
| netsnmp_pdu *response; |
| int running = 1; |
| netsnmp_variable_list *saved = NULL, **vlpp = &saved; |
| int status; |
| |
| while (running) { |
| |
| |
| |
| status = snmp_synch_response(ss, pdu, &response); |
| if (status != STAT_SUCCESS || !response) { |
| snmp_sess_perror(progname, ss); |
| #if HAVE_CURSES_H |
| endwin(); |
| #endif |
| exit(1); |
| } |
| if (response->errstat != SNMP_ERR_NOERROR) { |
| fprintf(stderr, "%s: Error in packet: %s\n", progname, |
| snmp_errstring(response->errstat)); |
| #if HAVE_CURSES_H |
| endwin(); |
| #endif |
| exit(1); |
| } |
| if (snmp_oid_compare(response->variables->name, |
| SNMP_MIN(base_length, |
| response->variables->name_length), |
| base, base_length) != 0) |
| running = 0; |
| else if (response->variables->type == SNMP_NOSUCHINSTANCE || |
| response->variables->type == SNMP_NOSUCHOBJECT || |
| response->variables->type == SNMP_ENDOFMIBVIEW) |
| running = 0; |
| else { |
| |
| |
| |
| *vlpp = response->variables; |
| (*vlpp)->next_variable = NULL; |
| |
| |
| |
| |
| pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); |
| snmp_add_null_var(pdu, (*vlpp)->name, (*vlpp)->name_length); |
| |
| |
| |
| |
| vlpp = &((*vlpp)->next_variable); |
| response->variables = NULL; |
| } |
| snmp_free_pdu(response); |
| } |
| return saved; |
| } |
| |
| |
| int |
| collect_perf(netsnmp_session *ss, struct hrSWRunTable **fproc) |
| { |
| netsnmp_pdu *pdu; |
| netsnmp_pdu *response; |
| netsnmp_variable_list *vlp; |
| oid base[MAX_OID_LEN]; |
| size_t base_length; |
| int status, count = 0; |
| struct hrSWRunTable *procs = malloc(sizeof(struct hrSWRunTable)); |
| |
| pdu = snmp_pdu_create(SNMP_MSG_GETNEXT); |
| base_length = |
| add(pdu, "HOST-RESOURCES-MIB:hrSWRunIndex", NULL, 0); |
| memcpy(base, pdu->variables->name, base_length * sizeof(oid)); |
| |
| vlp = collect_procs(ss, pdu, base, base_length); |
| |
| while (vlp) { |
| size_t len; |
| struct hrSWRunTable proc; |
| netsnmp_variable_list *vlp2; |
| |
| pdu = snmp_pdu_create(SNMP_MSG_GET); |
| |
| add(pdu, "HOST-RESOURCES-MIB:hrSWRunName", |
| &vlp->name[base_length], vlp->name_length - base_length); |
| add(pdu, "HOST-RESOURCES-MIB:hrSWRunID", |
| &vlp->name[base_length], vlp->name_length - base_length); |
| add(pdu, "HOST-RESOURCES-MIB:hrSWRunPath", |
| &vlp->name[base_length], vlp->name_length - base_length); |
| add(pdu, "HOST-RESOURCES-MIB:hrSWRunParameters", |
| &vlp->name[base_length], vlp->name_length - base_length); |
| add(pdu, "HOST-RESOURCES-MIB:hrSWRunType", |
| &vlp->name[base_length], vlp->name_length - base_length); |
| add(pdu, "HOST-RESOURCES-MIB:hrSWRunStatus", |
| &vlp->name[base_length], vlp->name_length - base_length); |
| add(pdu, "HOST-RESOURCES-MIB:hrSWRunPerfCPU", |
| &vlp->name[base_length], vlp->name_length - base_length); |
| add(pdu, "HOST-RESOURCES-MIB:hrSWRunPerfMem", |
| &vlp->name[base_length], vlp->name_length - base_length); |
| |
| response = NULL; |
| status = snmp_synch_response(ss, pdu, &response); |
| if (status != STAT_SUCCESS || !response) { |
| snmp_sess_perror(progname, ss); |
| #if HAVE_CURSES_H |
| endwin(); |
| #endif |
| exit(1); |
| } |
| if (response->errstat != SNMP_ERR_NOERROR) { |
| vlp = vlp->next_variable; |
| continue; |
| } |
| |
| memset(&proc, 0, sizeof(proc)); |
| |
| proc.hrSWRunIndex = vlp->name[base_length]; |
| |
| vlp2 = response->variables; |
| if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next; |
| len = vlp2->val_len; |
| proc.hrSWRunName = malloc(len+1); |
| memcpy(proc.hrSWRunName, vlp2->val.string, len); |
| proc.hrSWRunName[len] = '\0'; |
| |
| vlp2 = vlp2->next_variable; |
| if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next; |
| proc.hrSWRunID = *vlp2->val.integer; |
| |
| vlp2 = vlp2->next_variable; |
| if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next; |
| len = vlp2->val_len; |
| proc.hrSWRunPath = malloc(len+1); |
| memcpy(proc.hrSWRunPath, vlp2->val.string, len); |
| proc.hrSWRunPath[len] = '\0'; |
| |
| vlp2 = vlp2->next_variable; |
| if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next; |
| len = vlp2->val_len; |
| proc.hrSWRunParameters = malloc(len+1); |
| memcpy(proc.hrSWRunParameters, vlp2->val.string, len); |
| proc.hrSWRunParameters[len] = '\0'; |
| |
| vlp2 = vlp2->next_variable; |
| if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next; |
| proc.hrSWRunType = *vlp2->val.integer; |
| |
| vlp2 = vlp2->next_variable; |
| if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next; |
| proc.hrSWRunStatus = *vlp2->val.integer; |
| |
| vlp2 = vlp2->next_variable; |
| if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next; |
| proc.hrSWRunPerfCPU = *vlp2->val.integer; |
| |
| vlp2 = vlp2->next_variable; |
| if (vlp2->type == SNMP_NOSUCHINSTANCE) goto next; |
| proc.hrSWRunPerfMem = *vlp2->val.integer; |
| |
| count++; |
| procs = realloc(procs, count*sizeof(procs[0])); |
| procs[count-1] = proc; |
| |
| snmp_free_pdu(response); |
| vlp2 = vlp; |
| vlp = vlp->next_variable; |
| free(vlp2); |
| continue; |
| |
| next: |
| if (proc.hrSWRunName) free(proc.hrSWRunName); |
| if (proc.hrSWRunPath) free(proc.hrSWRunPath); |
| if (proc.hrSWRunParameters) free(proc.hrSWRunParameters); |
| snmp_free_pdu(response); |
| vlp2 = vlp; |
| vlp = vlp->next_variable; |
| free(vlp2); |
| } |
| *fproc = procs; |
| return count; |
| } |
| |
| |
| void free_perf(struct hrSWRunTable *procs, int nproc) |
| { |
| int i; |
| for (i = 0; i < nproc; i++) { |
| struct hrSWRunTable *proc = procs+i; |
| if (proc->hrSWRunName) free(proc->hrSWRunName); |
| if (proc->hrSWRunPath) free(proc->hrSWRunPath); |
| if (proc->hrSWRunParameters) free(proc->hrSWRunParameters); |
| } |
| free(procs); |
| } |
| |
| |
| int collect_cpu(netsnmp_session *ss, struct cpuStats *cpu) |
| { |
| netsnmp_pdu *pdu; |
| netsnmp_pdu *response; |
| int status; |
| int ret = 0; |
| |
| pdu = snmp_pdu_create(SNMP_MSG_GET); |
| add(pdu, "UCD-SNMP-MIB:ssCpuRawUser.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:ssCpuRawNice.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:ssCpuRawSystem.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:ssCpuRawIdle.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:ssCpuRawWait.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:ssCpuRawKernel.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:ssCpuRawInterrupt.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:ssCpuRawSoftIRQ.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:ssCpuRawSteal.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:ssCpuRawGuest.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:ssCpuRawGuestNice.0", NULL, 0); |
| |
| status = snmp_synch_response(ss, pdu, &response); |
| memset(cpu, 0, sizeof(*cpu)); |
| if (status != STAT_SUCCESS || !response || |
| response->errstat != SNMP_ERR_NOERROR) { |
| goto out; |
| } |
| else { |
| netsnmp_variable_list *vlp = response->variables; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| cpu->user = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| cpu->nice = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| cpu->system = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| cpu->idle = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| cpu->wait = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| cpu->kernel = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| |
| ret = 1; |
| |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| cpu->intr = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| cpu->softintr = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| cpu->steal = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| cpu->guest = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| cpu->guestnice = *vlp->val.integer; |
| } |
| out: |
| if (response) snmp_free_pdu(response); |
| return ret; |
| } |
| |
| |
| int collect_mem(netsnmp_session *ss, struct memStats *mem) |
| { |
| netsnmp_pdu *pdu; |
| netsnmp_pdu *response; |
| int status; |
| int ret = 0; |
| |
| pdu = snmp_pdu_create(SNMP_MSG_GET); |
| add(pdu, "UCD-SNMP-MIB:memTotalSwap.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:memAvailSwap.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:memTotalReal.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:memAvailReal.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:memShared.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:memBuffer.0", NULL, 0); |
| add(pdu, "UCD-SNMP-MIB:memCached.0", NULL, 0); |
| |
| status = snmp_synch_response(ss, pdu, &response); |
| memset(mem, 0, sizeof(*mem)); |
| if (status != STAT_SUCCESS || !response || |
| response->errstat != SNMP_ERR_NOERROR) { |
| goto out; |
| } |
| else { |
| netsnmp_variable_list *vlp = response->variables; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| mem->totalSwap = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| mem->availSwap = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| mem->totalReal = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| mem->availReal = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| |
| ret = 1; |
| |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| mem->shared = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| mem->buffer = *vlp->val.integer; |
| vlp = vlp->next_variable; |
| if (vlp->type == SNMP_NOSUCHOBJECT) goto out; |
| mem->cached = *vlp->val.integer; |
| } |
| out: |
| if (response) snmp_free_pdu(response); |
| return ret; |
| } |
| |
| |
| char *format_centisec(char *buf, size_t len, unsigned long csec) |
| { |
| long sec, min, hour, day; |
| |
| day = csec / 100 / 3600 / 24; |
| csec -= day * 100 * 3600 * 24; |
| hour = csec / 100 / 3600; |
| csec -= hour * 100 * 3600; |
| min = csec / 100 / 60; |
| csec -= min * 100 * 60; |
| sec = csec / 100; |
| csec -= sec * 100; |
| |
| if (day) |
| snprintf(buf, len, "%ldd%02ld:%02ld:%02ld.%02lu", day, hour, min, sec, csec); |
| else if (hour) |
| snprintf(buf, len, "%ld:%02ld:%02ld.%02lu", hour, min, sec, csec); |
| else if (min) |
| snprintf(buf, len, "%ld:%02ld.%02lu", min, sec, csec); |
| else |
| snprintf(buf, len, "%ld.%02lu", sec, csec); |
| return buf; |
| } |
| |
| |
| char *format_sec(char *buf, size_t len, unsigned long csec) |
| { |
| long sec, min, hour, day; |
| |
| day = csec / 100 / 3600 / 24; |
| csec -= day * 100 * 3600 * 24; |
| hour = csec / 100 / 3600; |
| csec -= hour * 100 * 3600; |
| min = csec / 100 / 60; |
| csec -= min * 100 * 60; |
| sec = csec / 100; |
| csec -= sec * 100; |
| |
| if (day) |
| snprintf(buf, len, "%ldd%02ld:%02ld:%02ld", day, hour, min, sec); |
| else if (hour) |
| snprintf(buf, len, "%ld:%02ld:%02ld.%02lu", hour, min, sec, csec); |
| else if (min) |
| snprintf(buf, len, "%ld:%02ld.%02lu", min, sec, csec); |
| else |
| snprintf(buf, len, "%ld.%02lu", sec, csec); |
| return buf; |
| } |
| |
| |
| char *format_humanmem(char *buf, size_t len, unsigned long mem) |
| { |
| if (mem >= 1024*1024) |
| snprintf(buf, len, "%4.2fGB", (float)mem/(1024*1024)); |
| else if (mem >= 1024) |
| snprintf(buf, len, "%4.2fMB", (float)mem/1024); |
| else |
| snprintf(buf, len, "%4.2fkB", (float)mem); |
| return buf; |
| } |
| |
| |
| int cpucomp(const void *v1, const void *v2) |
| { |
| const struct hrSWRunTable *p1 = v1, *p2 = v2; |
| return p2->hrSWRunPerfCPUInc - p1->hrSWRunPerfCPUInc; |
| } |
| |
| |
| int memcomp(const void *v1, const void *v2) |
| { |
| const struct hrSWRunTable *p1 = v1, *p2 = v2; |
| return p2->hrSWRunPerfMem - p1->hrSWRunPerfMem; |
| } |
| |
| |
| int totcomp(const void *v1, const void *v2) |
| { |
| const struct hrSWRunTable *p1 = v1, *p2 = v2; |
| return p2->hrSWRunPerfCPU - p1->hrSWRunPerfCPU; |
| } |
| |
| |
| int pidcomp(const void *v1, const void *v2) |
| { |
| const struct hrSWRunTable *p1 = v1, *p2 = v2; |
| return p1->hrSWRunIndex - p2->hrSWRunIndex; |
| } |
| |
| |
| int |
| snmpps(int argc, char *argv[]) |
| { |
| netsnmp_session session, *ss; |
| int arg; |
| struct hrSWRunTable *procs; |
| int count, pinx = 0; |
| |
| |
| |
| |
| switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) { |
| case NETSNMP_PARSE_ARGS_ERROR: |
| exit(1); |
| case NETSNMP_PARSE_ARGS_SUCCESS_EXIT: |
| exit(0); |
| case NETSNMP_PARSE_ARGS_ERROR_USAGE: |
| usage(); |
| exit(1); |
| default: |
| break; |
| } |
| |
| if (arg != argc) { |
| fprintf(stderr, "snmpps: extra argument: %s\n", argv[arg]); |
| exit(1); |
| } |
| |
| SOCK_STARTUP; |
| |
| |
| |
| |
| ss = snmp_open(&session); |
| if (ss == NULL) { |
| |
| |
| |
| snmp_sess_perror("snmpps", &session); |
| SOCK_CLEANUP; |
| exit(1); |
| } |
| |
| count = collect_perf(ss, &procs); |
| if (count == 0) { |
| fprintf(stderr, "snmpps: no processes found\n"); |
| exit(1); |
| } |
| |
| switch (topsort) { |
| case 'm': |
| qsort(procs, count, sizeof(procs[0]), memcomp); |
| break; |
| case 't': |
| qsort(procs, count, sizeof(procs[0]), totcomp); |
| break; |
| } |
| |
| printf("%7s %4s %6s %10s %11s %-10s\n", |
| "Index", "Type", "Status", "Memory", "CPU", "Command"); |
| |
| while (pinx < count) { |
| struct hrSWRunTable *proc = procs+pinx; |
| const char *hr_status, *hr_type; |
| char b1[15], b2[20]; |
| |
| switch (proc->hrSWRunType) { |
| case 1: hr_type = "Unkn"; break; |
| case 2: hr_type = "Os"; break; |
| case 3: hr_type = "Drvr"; break; |
| case 4: hr_type = "Appl"; break; |
| default: hr_type = "?"; break; |
| } |
| |
| switch (proc->hrSWRunStatus) { |
| case 1: hr_status = "Run"; break; |
| case 2: hr_status = "Wait"; break; |
| case 3: hr_status = "Event"; break; |
| case 4: hr_status = "Inval"; break; |
| default: hr_status = "?"; break; |
| } |
| |
| printf("%7lu %4s %6s %10s %11.11s %s %s\n", |
| proc->hrSWRunIndex, |
| hr_type, |
| hr_status, |
| format_humanmem(b1, sizeof b1, proc->hrSWRunPerfMem), |
| format_centisec(b2, sizeof b2, proc->hrSWRunPerfCPU), |
| command_path && proc->hrSWRunPath[0] ? proc->hrSWRunPath : proc->hrSWRunName, |
| command_args ? proc->hrSWRunParameters : ""); |
| |
| pinx++; |
| } |
| |
| snmp_close(ss); |
| SOCK_CLEANUP; |
| return 0; |
| } |
| |
| |
| #if HAVE_CURSES_H |
| static void endtop(int sig) |
| { |
| endwin(); |
| exit(1); |
| } |
| |
| |
| int snmptop(int argc, char **argv) |
| { |
| netsnmp_session session, *ss; |
| int arg; |
| struct hrSWRunTable *oproc; |
| int ocount = 0; |
| int show_idle = 1; |
| int show_os = 1; |
| char ch; |
| struct cpuStats oldCpu; |
| struct memStats mem; |
| int has_cpu, has_mem; |
| |
| |
| |
| |
| switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) { |
| case NETSNMP_PARSE_ARGS_ERROR: |
| exit(1); |
| case NETSNMP_PARSE_ARGS_SUCCESS_EXIT: |
| exit(0); |
| case NETSNMP_PARSE_ARGS_ERROR_USAGE: |
| usage(); |
| exit(1); |
| default: |
| break; |
| } |
| |
| if (arg != argc) { |
| fprintf(stderr, "snmptop: extra argument: %s\n", argv[arg]); |
| exit(1); |
| } |
| |
| SOCK_STARTUP; |
| |
| |
| |
| |
| ss = snmp_open(&session); |
| if (ss == NULL) { |
| |
| |
| |
| snmp_sess_perror("snmptop", &session); |
| SOCK_CLEANUP; |
| exit(1); |
| } |
| |
| ocount = collect_perf(ss, &oproc); |
| if (ocount == 0) { |
| fprintf(stderr, "snmptop: no processes found\n"); |
| exit(1); |
| } |
| |
| collect_cpu(ss, &oldCpu); |
| |
| signal(SIGINT, endtop); |
| initscr(); |
| cbreak(); |
| noecho(); |
| nonl(); |
| halfdelay(50); |
| |
| while ((ch = getch()) != 'q') { |
| int ncount; |
| struct hrSWRunTable *nproc; |
| int oinx = 0, ninx = 0, line = 0; |
| netsnmp_pdu *pdu; |
| netsnmp_pdu *response = NULL; |
| int status; |
| time_t clock; |
| struct tm *ptm; |
| char uptime[40]; |
| char timestr[40]; |
| char b1[15], b2[15], b3[15], b4[15]; |
| struct cpuStats newCpu; |
| |
| if (ch == 'c' || ch == 'm' || ch == 'n' || ch == 't') topsort = ch; |
| if (ch == 'i') show_idle = !show_idle; |
| if (ch == 'o') show_os = !show_os; |
| if (ch == 'a') command_args = !command_args; |
| if (ch == 'p') command_path = !command_path; |
| |
| ncount = collect_perf(ss, &nproc); |
| |
| while (oinx < ocount && ninx < ncount) { |
| if (oproc[oinx].hrSWRunIndex == nproc[ninx].hrSWRunIndex) { |
| nproc[ninx].hrSWRunPerfCPUInc = nproc[ninx].hrSWRunPerfCPU-oproc[oinx].hrSWRunPerfCPU; |
| ninx++; |
| oinx++; |
| } |
| else if (nproc[oinx].hrSWRunIndex < oproc[ninx].hrSWRunIndex) |
| oinx++; |
| else { |
| nproc[ninx].hrSWRunPerfCPUInc = nproc[ninx].hrSWRunPerfCPU; |
| ninx++; |
| } |
| } |
| while (ninx < ncount) { |
| nproc[ninx].hrSWRunPerfCPUInc = nproc[ninx].hrSWRunPerfCPU; |
| ninx++; |
| } |
| |
| switch (topsort) { |
| case 'c': |
| qsort(nproc, ncount, sizeof(nproc[0]), cpucomp); |
| break; |
| case 'm': |
| qsort(nproc, ncount, sizeof(nproc[0]), memcomp); |
| break; |
| case 't': |
| qsort(nproc, ncount, sizeof(nproc[0]), totcomp); |
| break; |
| } |
| |
| has_cpu = collect_cpu(ss, &newCpu); |
| has_mem = collect_mem(ss, &mem); |
| |
| pdu = snmp_pdu_create(SNMP_MSG_GET); |
| add(pdu, "HOST-RESOURCES-MIB:hrSystemUptime.0", NULL, 0); |
| status = snmp_synch_response(ss, pdu, &response); |
| if (status != STAT_SUCCESS || !response || |
| response->errstat != SNMP_ERR_NOERROR) { |
| uptime[0] = '\0'; |
| } |
| else { |
| netsnmp_variable_list *vlp = response->variables; |
| if (vlp->type == SNMP_NOSUCHINSTANCE) abort(); |
| uptime_string_n(*vlp->val.integer, uptime, sizeof(uptime)); |
| } |
| snmp_free_pdu(response); |
| |
| clock = time(NULL); |
| ptm = localtime(&clock); |
| strftime(timestr, sizeof(timestr), "%H:%M:%S", ptm); |
| |
| clear(); |
| move(0, 0); |
| printw("%s %s%s", session.peername, uptime[0] ? "up " : "", uptime); |
| move(0, COLS-strlen(timestr)-1); |
| printw("%s", timestr); |
| if (has_cpu) { |
| struct cpuStats deltaCpu; |
| u_long sumCpu; |
| |
| deltaCpu.user = newCpu.user - oldCpu.user; |
| deltaCpu.nice = newCpu.nice - oldCpu.nice; |
| deltaCpu.system = newCpu.system - oldCpu.system; |
| deltaCpu.idle = newCpu.idle - oldCpu.idle; |
| deltaCpu.wait = newCpu.wait - oldCpu.wait; |
| deltaCpu.kernel = newCpu.kernel - oldCpu.kernel; |
| deltaCpu.intr = newCpu.intr - oldCpu.intr; |
| deltaCpu.softintr = newCpu.softintr - oldCpu.softintr; |
| deltaCpu.steal = newCpu.steal - oldCpu.steal; |
| deltaCpu.guest = newCpu.guest - oldCpu.guest; |
| deltaCpu.guestnice = newCpu.guestnice - oldCpu.guestnice; |
| oldCpu = newCpu; |
| sumCpu = deltaCpu.user + deltaCpu.nice |
| + deltaCpu.system + deltaCpu.idle |
| + deltaCpu.wait + deltaCpu.kernel + deltaCpu.steal |
| + deltaCpu.intr + deltaCpu.softintr |
| + deltaCpu.guest + deltaCpu.guestnice; |
| |
| printw("\nCPU%%: %4.1fUs %4.1fSy %4.1fId %3.1fWa %3.1fNi %3.1fKe %3.1fHi %3.1fSi %3.1fSt %3.1fGu %3.1fGN", |
| (float)deltaCpu.user*100/sumCpu, |
| (float)deltaCpu.system*100/sumCpu, |
| (float)deltaCpu.idle*100/sumCpu, |
| (float)deltaCpu.wait*100/sumCpu, |
| (float)deltaCpu.nice*100/sumCpu, |
| (float)deltaCpu.kernel*100/sumCpu, |
| (float)deltaCpu.intr*100/sumCpu, |
| (float)deltaCpu.softintr*100/sumCpu, |
| (float)deltaCpu.steal*100/sumCpu, |
| (float)deltaCpu.guest*100/sumCpu, |
| (float)deltaCpu.guestnice*100/sumCpu); |
| line++; |
| } |
| |
| if (has_mem) { |
| printw("\nMem: %10s Total %10s Used %10s Free %10s Buffer", |
| format_humanmem(b1, sizeof b1, mem.totalReal), |
| format_humanmem(b2, sizeof b2, mem.totalReal-mem.availReal), |
| format_humanmem(b3, sizeof b3, mem.availReal), |
| format_humanmem(b4, sizeof b4, mem.buffer)); |
| line++; |
| printw("\nSwap: %10s Total %10s Used %10s Free %10s Cached", |
| format_humanmem(b1, sizeof b1, mem.totalSwap), |
| format_humanmem(b2, sizeof b2, mem.totalSwap-mem.availSwap), |
| format_humanmem(b3, sizeof b3, mem.availSwap), |
| format_humanmem(b4, sizeof b4, mem.cached)); |
| line++; |
| } |
| |
| printw("\n%7s %4s %6s %10s %11s %5s %-10s", |
| "Index", "Type", "Status", "Memory", "Total CPU", "%CPU", "Command"); |
| line++; |
| ninx = 0; |
| while (line < LINES && ninx < ncount) { |
| struct hrSWRunTable *proc = nproc+ninx; |
| const char *hr_status, *hr_type; |
| |
| ninx++; |
| if (proc->hrSWRunPerfCPUInc == 0 && !show_idle) |
| continue; |
| if (proc->hrSWRunType != 4 && !show_os) |
| continue; |
| |
| line++; |
| |
| switch (proc->hrSWRunType) { |
| case 1: hr_type = "Unkn"; break; |
| case 2: hr_type = "Os"; break; |
| case 3: hr_type = "Drvr"; break; |
| case 4: hr_type = "Appl"; break; |
| default: hr_type = "?"; break; |
| } |
| |
| switch (proc->hrSWRunStatus) { |
| case 1: hr_status = "Run"; break; |
| case 2: hr_status = "Wait"; break; |
| case 3: hr_status = "Event"; break; |
| case 4: hr_status = "Inval"; break; |
| default: hr_status = "?"; break; |
| } |
| |
| printw("\n%7lu %4s %6s %10s %11s %5.1f %s %s", |
| proc->hrSWRunIndex, |
| hr_type, |
| hr_status, |
| format_humanmem(b1, sizeof b1, proc->hrSWRunPerfMem), |
| format_sec(b2,sizeof b2, proc->hrSWRunPerfCPU), |
| (float)proc->hrSWRunPerfCPUInc/5, |
| command_path && proc->hrSWRunPath[0] ? proc->hrSWRunPath : proc->hrSWRunName, |
| command_args ? proc->hrSWRunParameters : ""); |
| } |
| refresh(); |
| |
| qsort(nproc, ncount, sizeof(nproc[0]), pidcomp); |
| free_perf(oproc, ocount); |
| oproc = nproc; |
| ocount = ncount; |
| } |
| endwin(); |
| |
| snmp_close(ss); |
| SOCK_CLEANUP; |
| return 0; |
| } |
| #else |
| int snmptop(int argc, char **argv) |
| { |
| fprintf(stderr, "%s: curses not detected during configure\n", progname); |
| return 1; |
| } |
| #endif |
| |
| |
| int main(int argc, char **argv) |
| { |
| progname = strrchr(argv[0], '/'); |
| if (progname) progname++; |
| else progname = argv[0]; |
| if (strncmp(progname, "lt-", 3) == 0) progname += 3; |
| |
| if (strcmp(progname, "snmpps") == 0) return snmpps(argc, argv); |
| if (strcmp(progname, "snmptop") == 0) return snmptop(argc, argv); |
| fprintf(stderr, "%s: unknown prognam name\n", progname); |
| exit(1); |
| } |