1 /*
2 * snmpps.c - display process table on a network entity via SNMP.
3 *
4 */
5
6 /* Portions of this file are subject to the following copyright(s). See
7 * the Net-SNMP's COPYING file for more details and other copyrights
8 * that may apply:
9 */
10 /***********************************************************************
11 Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
12
13 All Rights Reserved
14
15 Permission to use, copy, modify, and distribute this software and its
16 documentation for any purpose and without fee is hereby granted,
17 provided that the above copyright notice appear in all copies and that
18 both that copyright notice and this permission notice appear in
19 supporting documentation, and that the name of CMU not be
20 used in advertising or publicity pertaining to distribution of the
21 software without specific, written prior permission.
22
23 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
29 SOFTWARE.
30 ******************************************************************/
31
32 #include <net-snmp/net-snmp-config.h>
33
34 #if HAVE_STDLIB_H
35 #include <stdlib.h>
36 #endif
37 #if HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 #if HAVE_STRING_H
41 #include <string.h>
42 #else
43 #include <strings.h>
44 #endif
45 #include <sys/types.h>
46 #if HAVE_NETINET_IN_H
47 #include <netinet/in.h>
48 #endif
49 #include <stdio.h>
50 #include <ctype.h>
51 #if TIME_WITH_SYS_TIME
52 # include <sys/time.h>
53 # include <time.h>
54 #else
55 # if HAVE_SYS_TIME_H
56 # include <sys/time.h>
57 # else
58 # include <time.h>
59 # endif
60 #endif
61 #if HAVE_SYS_SELECT_H
62 #include <sys/select.h>
63 #endif
64 #if HAVE_NETDB_H
65 #include <netdb.h>
66 #endif
67 #if HAVE_ARPA_INET_H
68 #include <arpa/inet.h>
69 #endif
70 #if HAVE_NCURSES_CURSES_H
71 #include <ncurses/curses.h>
72 #elif HAVE_CURSES_H
73 #include <curses.h>
74 #endif
75 #include <signal.h>
76
77 #include <net-snmp/net-snmp-includes.h>
78
79 void
usage(void)80 usage(void)
81 {
82 fprintf(stderr, "Usage: snmpps [-Cp] [-Ca] [-C m | n | t] AGENT");
83 snmp_parse_args_usage(stderr);
84 fprintf(stderr, "\n\n");
85 snmp_parse_args_descriptions(stderr);
86 fprintf(stderr, "\nsnmpps options:\n");
87 fprintf(stderr,
88 "\t-Cp\tShow hrSWRunPath instead of hrSWRunName\n");
89 fprintf(stderr,
90 "\t-Ca\tShow hrSWRunParameters in addition to hrSWRunName/Path\n");
91 fprintf(stderr,
92 "\t-Ct\tSort processes according to CPU time used\n");
93 fprintf(stderr,
94 "\t-Cm\tSort processes according to memory usage\n");
95 fprintf(stderr,
96 "\t-Cn\tSort processes by PID number (default)\n");
97 }
98
99 int command_args = 0,
100 command_path = 0;
101 int topsort = 'c';
102 char *progname;
103
104 static void
optProc(int argc,char * const * argv,int opt)105 optProc(int argc, char *const *argv, int opt)
106 {
107 switch (opt) {
108 case 'C':
109 while (*optarg) {
110 switch (*optarg++) {
111 case 'a':
112 command_args = 1;
113 break;
114 case 'p':
115 command_path = 1;
116 break;
117 case 'm':
118 topsort = 'm';
119 break;
120 case 'n':
121 topsort = 'n';
122 break;
123 case 't':
124 topsort = 't';
125 break;
126
127 default:
128 fprintf(stderr,
129 "Unknown flag passed to -C: %c\n", optarg[-1]);
130 exit(1);
131 }
132 }
133 }
134 }
135
136 struct hrSWRunTable {
137 u_long hrSWRunIndex;
138 char *hrSWRunName;
139 char *hrSWRunPath;
140 char *hrSWRunParameters;
141 u_long hrSWRunID;
142 u_long hrSWRunType;
143 u_long hrSWRunStatus;
144 u_long hrSWRunPerfMem;
145 u_long hrSWRunPerfCPU;
146 u_long hrSWRunPerfCPUInc;
147 };
148
149 struct cpuStats {
150 u_long user;
151 u_long nice;
152 u_long system;
153 u_long idle;
154 u_long wait;
155 u_long kernel;
156 u_long intr;
157 u_long softintr;
158 u_long steal;
159 u_long guest;
160 u_long guestnice;
161 };
162
163 struct memStats {
164 u_long totalSwap;
165 u_long availSwap;
166 u_long totalReal;
167 u_long availReal;
168 u_long shared;
169 u_long buffer;
170 u_long cached;
171 };
172
173 struct laStats {
174 u_long la1;
175 u_long la5;
176 u_long la15;
177 };
178
179
180 int
add(netsnmp_pdu * pdu,const char * mibnodename,oid * index,size_t indexlen)181 add(netsnmp_pdu *pdu, const char *mibnodename,
182 oid * index, size_t indexlen)
183 {
184 oid base[MAX_OID_LEN];
185 size_t base_length = MAX_OID_LEN;
186
187 memset(base, 0, MAX_OID_LEN * sizeof(oid));
188
189 if (!snmp_parse_oid(mibnodename, base, &base_length)) {
190 snmp_perror(mibnodename);
191 fprintf(stderr, "couldn't find mib node %s, giving up\n",
192 mibnodename);
193 #if HAVE_CURSES_H
194 endwin();
195 #endif
196 exit(1);
197 }
198
199 if (base_length + indexlen > sizeof(base) / sizeof(base[0])) {
200 fprintf(stderr, "internal error for %s, giving up\n", mibnodename);
201 exit(1);
202 }
203
204 if (index && indexlen) {
205 memcpy(&(base[base_length]), index, indexlen * sizeof(oid));
206 base_length += indexlen;
207 }
208 DEBUGMSGTL(("add", "created: "));
209 DEBUGMSGOID(("add", base, base_length));
210 DEBUGMSG(("add", "\n"));
211 snmp_add_null_var(pdu, base, base_length);
212
213 return base_length;
214 }
215
216 netsnmp_variable_list *
collect_procs(netsnmp_session * ss,netsnmp_pdu * pdu,oid * base,size_t base_length)217 collect_procs(netsnmp_session *ss, netsnmp_pdu *pdu,
218 oid * base, size_t base_length)
219 {
220 netsnmp_pdu *response;
221 int running = 1;
222 netsnmp_variable_list *saved = NULL, **vlpp = &saved;
223 int status;
224
225 while (running) {
226 /*
227 * gotta catch em all, gotta catch em all!
228 */
229 status = snmp_synch_response(ss, pdu, &response);
230 if (status != STAT_SUCCESS || !response) {
231 snmp_sess_perror(progname, ss);
232 #if HAVE_CURSES_H
233 endwin();
234 #endif
235 exit(1);
236 }
237 if (response->errstat != SNMP_ERR_NOERROR) {
238 fprintf(stderr, "%s: Error in packet: %s\n", progname,
239 snmp_errstring(response->errstat));
240 #if HAVE_CURSES_H
241 endwin();
242 #endif
243 exit(1);
244 }
245 if (snmp_oid_compare(response->variables->name,
246 SNMP_MIN(base_length,
247 response->variables->name_length),
248 base, base_length) != 0)
249 running = 0;
250 else if (response->variables->type == SNMP_NOSUCHINSTANCE ||
251 response->variables->type == SNMP_NOSUCHOBJECT ||
252 response->variables->type == SNMP_ENDOFMIBVIEW)
253 running = 0;
254 else {
255 /*
256 * get response
257 */
258 *vlpp = response->variables;
259 (*vlpp)->next_variable = NULL; /* shouldn't be any, but just in case */
260
261 /*
262 * create the next request
263 */
264 pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
265 snmp_add_null_var(pdu, (*vlpp)->name, (*vlpp)->name_length);
266
267 /*
268 * finish loop setup
269 */
270 vlpp = &((*vlpp)->next_variable);
271 response->variables = NULL; /* ahh, forget about it */
272 }
273 snmp_free_pdu(response);
274 }
275 return saved;
276 }
277
278
279 int
collect_perf(netsnmp_session * ss,struct hrSWRunTable ** fproc)280 collect_perf(netsnmp_session *ss, struct hrSWRunTable **fproc)
281 {
282 netsnmp_pdu *pdu;
283 netsnmp_pdu *response;
284 netsnmp_variable_list *vlp;
285 oid base[MAX_OID_LEN];
286 size_t base_length;
287 int status, count = 0;
288 struct hrSWRunTable *procs = malloc(sizeof(struct hrSWRunTable));
289
290 pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
291 base_length =
292 add(pdu, "HOST-RESOURCES-MIB:hrSWRunIndex", NULL, 0);
293 memcpy(base, pdu->variables->name, base_length * sizeof(oid));
294
295 vlp = collect_procs(ss, pdu, base, base_length);
296
297 while (vlp) {
298 size_t len;
299 struct hrSWRunTable proc;
300 netsnmp_variable_list *vlp2;
301
302 pdu = snmp_pdu_create(SNMP_MSG_GET);
303
304 add(pdu, "HOST-RESOURCES-MIB:hrSWRunName",
305 &vlp->name[base_length], vlp->name_length - base_length);
306 add(pdu, "HOST-RESOURCES-MIB:hrSWRunID",
307 &vlp->name[base_length], vlp->name_length - base_length);
308 add(pdu, "HOST-RESOURCES-MIB:hrSWRunPath",
309 &vlp->name[base_length], vlp->name_length - base_length);
310 add(pdu, "HOST-RESOURCES-MIB:hrSWRunParameters",
311 &vlp->name[base_length], vlp->name_length - base_length);
312 add(pdu, "HOST-RESOURCES-MIB:hrSWRunType",
313 &vlp->name[base_length], vlp->name_length - base_length);
314 add(pdu, "HOST-RESOURCES-MIB:hrSWRunStatus",
315 &vlp->name[base_length], vlp->name_length - base_length);
316 add(pdu, "HOST-RESOURCES-MIB:hrSWRunPerfCPU",
317 &vlp->name[base_length], vlp->name_length - base_length);
318 add(pdu, "HOST-RESOURCES-MIB:hrSWRunPerfMem",
319 &vlp->name[base_length], vlp->name_length - base_length);
320
321 response = NULL;
322 status = snmp_synch_response(ss, pdu, &response);
323 if (status != STAT_SUCCESS || !response) {
324 snmp_sess_perror(progname, ss);
325 #if HAVE_CURSES_H
326 endwin();
327 #endif
328 exit(1);
329 }
330 if (response->errstat != SNMP_ERR_NOERROR) {
331 vlp = vlp->next_variable;
332 continue;
333 }
334
335 memset(&proc, 0, sizeof(proc));
336
337 proc.hrSWRunIndex = vlp->name[base_length];
338
339 vlp2 = response->variables;
340 if (vlp2->type == SNMP_NOSUCHINSTANCE ||
341 vlp2->type == SNMP_NOSUCHOBJECT) goto next;
342 len = vlp2->val_len;
343 proc.hrSWRunName = malloc(len+1);
344 memcpy(proc.hrSWRunName, vlp2->val.string, len);
345 proc.hrSWRunName[len] = '\0';
346
347 vlp2 = vlp2->next_variable;
348 if (vlp2->type == SNMP_NOSUCHINSTANCE ||
349 vlp2->type == SNMP_NOSUCHOBJECT) goto next;
350 proc.hrSWRunID = *vlp2->val.integer;
351
352 vlp2 = vlp2->next_variable;
353 if (vlp2->type == SNMP_NOSUCHINSTANCE ||
354 vlp2->type == SNMP_NOSUCHOBJECT) goto next;
355 len = vlp2->val_len;
356 proc.hrSWRunPath = malloc(len+1);
357 memcpy(proc.hrSWRunPath, vlp2->val.string, len);
358 proc.hrSWRunPath[len] = '\0';
359
360 vlp2 = vlp2->next_variable;
361 if (vlp2->type == SNMP_NOSUCHINSTANCE ||
362 vlp2->type == SNMP_NOSUCHOBJECT) goto next;
363 len = vlp2->val_len;
364 proc.hrSWRunParameters = malloc(len+1);
365 memcpy(proc.hrSWRunParameters, vlp2->val.string, len);
366 proc.hrSWRunParameters[len] = '\0';
367
368 vlp2 = vlp2->next_variable;
369 if (vlp2->type == SNMP_NOSUCHINSTANCE ||
370 vlp2->type == SNMP_NOSUCHOBJECT) goto next;
371 proc.hrSWRunType = *vlp2->val.integer;
372
373 vlp2 = vlp2->next_variable;
374 if (vlp2->type == SNMP_NOSUCHINSTANCE ||
375 vlp2->type == SNMP_NOSUCHOBJECT) goto next;
376 proc.hrSWRunStatus = *vlp2->val.integer;
377
378 vlp2 = vlp2->next_variable;
379 if (vlp2->type == SNMP_NOSUCHINSTANCE ||
380 vlp2->type == SNMP_NOSUCHOBJECT) goto next;
381 proc.hrSWRunPerfCPU = *vlp2->val.integer;
382
383 vlp2 = vlp2->next_variable;
384 if (vlp2->type == SNMP_NOSUCHINSTANCE ||
385 vlp2->type == SNMP_NOSUCHOBJECT) goto next;
386 proc.hrSWRunPerfMem = *vlp2->val.integer;
387
388 count++;
389 procs = realloc(procs, count*sizeof(procs[0]));
390 procs[count-1] = proc;
391
392 snmp_free_pdu(response);
393 vlp2 = vlp;
394 vlp = vlp->next_variable;
395 free(vlp2);
396 continue;
397
398 next:
399 if (proc.hrSWRunName) free(proc.hrSWRunName);
400 if (proc.hrSWRunPath) free(proc.hrSWRunPath);
401 if (proc.hrSWRunParameters) free(proc.hrSWRunParameters);
402 snmp_free_pdu(response);
403 vlp2 = vlp;
404 vlp = vlp->next_variable;
405 free(vlp2);
406 }
407 *fproc = procs;
408 return count;
409 }
410
411
free_perf(struct hrSWRunTable * procs,int nproc)412 void free_perf(struct hrSWRunTable *procs, int nproc)
413 {
414 int i;
415 for (i = 0; i < nproc; i++) {
416 struct hrSWRunTable *proc = procs+i;
417 if (proc->hrSWRunName) free(proc->hrSWRunName);
418 if (proc->hrSWRunPath) free(proc->hrSWRunPath);
419 if (proc->hrSWRunParameters) free(proc->hrSWRunParameters);
420 }
421 free(procs);
422 }
423
424
collect_cpu(netsnmp_session * ss,struct cpuStats * cpu)425 int collect_cpu(netsnmp_session *ss, struct cpuStats *cpu)
426 {
427 netsnmp_pdu *pdu;
428 netsnmp_pdu *response;
429 int status;
430 int ret = 0;
431
432 pdu = snmp_pdu_create(SNMP_MSG_GET);
433 add(pdu, "UCD-SNMP-MIB:ssCpuRawUser.0", NULL, 0);
434 add(pdu, "UCD-SNMP-MIB:ssCpuRawNice.0", NULL, 0);
435 add(pdu, "UCD-SNMP-MIB:ssCpuRawSystem.0", NULL, 0);
436 add(pdu, "UCD-SNMP-MIB:ssCpuRawIdle.0", NULL, 0);
437 add(pdu, "UCD-SNMP-MIB:ssCpuRawWait.0", NULL, 0);
438 add(pdu, "UCD-SNMP-MIB:ssCpuRawKernel.0", NULL, 0);
439 add(pdu, "UCD-SNMP-MIB:ssCpuRawInterrupt.0", NULL, 0);
440 add(pdu, "UCD-SNMP-MIB:ssCpuRawSoftIRQ.0", NULL, 0);
441 add(pdu, "UCD-SNMP-MIB:ssCpuRawSteal.0", NULL, 0);
442 add(pdu, "UCD-SNMP-MIB:ssCpuRawGuest.0", NULL, 0);
443 add(pdu, "UCD-SNMP-MIB:ssCpuRawGuestNice.0", NULL, 0);
444
445 status = snmp_synch_response(ss, pdu, &response);
446 memset(cpu, 0, sizeof(*cpu));
447 if (status != STAT_SUCCESS || !response ||
448 response->errstat != SNMP_ERR_NOERROR) {
449 goto out;
450 }
451 else {
452 netsnmp_variable_list *vlp = response->variables;
453 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
454 cpu->user = *vlp->val.integer;
455 vlp = vlp->next_variable;
456 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
457 cpu->nice = *vlp->val.integer;
458 vlp = vlp->next_variable;
459 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
460 cpu->system = *vlp->val.integer;
461 vlp = vlp->next_variable;
462 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
463 cpu->idle = *vlp->val.integer;
464 vlp = vlp->next_variable;
465 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
466 cpu->wait = *vlp->val.integer;
467 vlp = vlp->next_variable;
468 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
469 cpu->kernel = *vlp->val.integer;
470 vlp = vlp->next_variable;
471
472 ret = 1;
473
474 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
475 cpu->intr = *vlp->val.integer;
476 vlp = vlp->next_variable;
477 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
478 cpu->softintr = *vlp->val.integer;
479 vlp = vlp->next_variable;
480 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
481 cpu->steal = *vlp->val.integer;
482 vlp = vlp->next_variable;
483 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
484 cpu->guest = *vlp->val.integer;
485 vlp = vlp->next_variable;
486 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
487 cpu->guestnice = *vlp->val.integer;
488 }
489 out:
490 if (response) snmp_free_pdu(response);
491 return ret;
492 }
493
494
collect_mem(netsnmp_session * ss,struct memStats * mem)495 int collect_mem(netsnmp_session *ss, struct memStats *mem)
496 {
497 netsnmp_pdu *pdu;
498 netsnmp_pdu *response;
499 int status;
500 int ret = 0;
501
502 pdu = snmp_pdu_create(SNMP_MSG_GET);
503 add(pdu, "UCD-SNMP-MIB:memTotalSwap.0", NULL, 0);
504 add(pdu, "UCD-SNMP-MIB:memAvailSwap.0", NULL, 0);
505 add(pdu, "UCD-SNMP-MIB:memTotalReal.0", NULL, 0);
506 add(pdu, "UCD-SNMP-MIB:memAvailReal.0", NULL, 0);
507 add(pdu, "UCD-SNMP-MIB:memShared.0", NULL, 0);
508 add(pdu, "UCD-SNMP-MIB:memBuffer.0", NULL, 0);
509 add(pdu, "UCD-SNMP-MIB:memCached.0", NULL, 0);
510
511 status = snmp_synch_response(ss, pdu, &response);
512 memset(mem, 0, sizeof(*mem));
513 if (status != STAT_SUCCESS || !response ||
514 response->errstat != SNMP_ERR_NOERROR) {
515 goto out;
516 }
517 else {
518 netsnmp_variable_list *vlp = response->variables;
519 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
520 mem->totalSwap = *vlp->val.integer;
521 vlp = vlp->next_variable;
522 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
523 mem->availSwap = *vlp->val.integer;
524 vlp = vlp->next_variable;
525 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
526 mem->totalReal = *vlp->val.integer;
527 vlp = vlp->next_variable;
528 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
529 mem->availReal = *vlp->val.integer;
530 vlp = vlp->next_variable;
531
532 ret = 1;
533
534 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
535 mem->shared = *vlp->val.integer;
536 vlp = vlp->next_variable;
537 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
538 mem->buffer = *vlp->val.integer;
539 vlp = vlp->next_variable;
540 if (vlp->type == SNMP_NOSUCHOBJECT) goto out;
541 mem->cached = *vlp->val.integer;
542 }
543 out:
544 if (response) snmp_free_pdu(response);
545 return ret;
546 }
547
548
format_centisec(char * buf,size_t len,unsigned long csec)549 char *format_centisec(char *buf, size_t len, unsigned long csec)
550 {
551 long sec, min, hour, day;
552
553 day = csec / 100 / 3600 / 24;
554 csec -= day * 100 * 3600 * 24;
555 hour = csec / 100 / 3600;
556 csec -= hour * 100 * 3600;
557 min = csec / 100 / 60;
558 csec -= min * 100 * 60;
559 sec = csec / 100;
560 csec -= sec * 100;
561
562 if (day)
563 snprintf(buf, len, "%ldd%02ld:%02ld:%02ld.%02lu", day, hour, min, sec, csec);
564 else if (hour)
565 snprintf(buf, len, "%ld:%02ld:%02ld.%02lu", hour, min, sec, csec);
566 else if (min)
567 snprintf(buf, len, "%ld:%02ld.%02lu", min, sec, csec);
568 else
569 snprintf(buf, len, "%ld.%02lu", sec, csec);
570 return buf;
571 }
572
573
format_sec(char * buf,size_t len,unsigned long csec)574 char *format_sec(char *buf, size_t len, unsigned long csec)
575 {
576 long sec, min, hour, day;
577
578 day = csec / 100 / 3600 / 24;
579 csec -= day * 100 * 3600 * 24;
580 hour = csec / 100 / 3600;
581 csec -= hour * 100 * 3600;
582 min = csec / 100 / 60;
583 csec -= min * 100 * 60;
584 sec = csec / 100;
585 csec -= sec * 100;
586
587 if (day)
588 snprintf(buf, len, "%ldd%02ld:%02ld:%02ld", day, hour, min, sec);
589 else if (hour)
590 snprintf(buf, len, "%ld:%02ld:%02ld.%02lu", hour, min, sec, csec);
591 else if (min)
592 snprintf(buf, len, "%ld:%02ld.%02lu", min, sec, csec);
593 else
594 snprintf(buf, len, "%ld.%02lu", sec, csec);
595 return buf;
596 }
597
598
format_humanmem(char * buf,size_t len,unsigned long mem)599 char *format_humanmem(char *buf, size_t len, unsigned long mem)
600 {
601 if (mem >= 1024*1024)
602 snprintf(buf, len, "%4.2fGB", (float)mem/(1024*1024));
603 else if (mem >= 1024)
604 snprintf(buf, len, "%4.2fMB", (float)mem/1024);
605 else
606 snprintf(buf, len, "%4.2fkB", (float)mem);
607 return buf;
608 }
609
610
cpucomp(const void * v1,const void * v2)611 int cpucomp(const void *v1, const void *v2)
612 {
613 const struct hrSWRunTable *p1 = v1, *p2 = v2;
614 return p2->hrSWRunPerfCPUInc - p1->hrSWRunPerfCPUInc;
615 }
616
617
memcomp(const void * v1,const void * v2)618 int memcomp(const void *v1, const void *v2)
619 {
620 const struct hrSWRunTable *p1 = v1, *p2 = v2;
621 return p2->hrSWRunPerfMem - p1->hrSWRunPerfMem;
622 }
623
624
totcomp(const void * v1,const void * v2)625 int totcomp(const void *v1, const void *v2)
626 {
627 const struct hrSWRunTable *p1 = v1, *p2 = v2;
628 return p2->hrSWRunPerfCPU - p1->hrSWRunPerfCPU;
629 }
630
631
pidcomp(const void * v1,const void * v2)632 int pidcomp(const void *v1, const void *v2)
633 {
634 const struct hrSWRunTable *p1 = v1, *p2 = v2;
635 return p1->hrSWRunIndex - p2->hrSWRunIndex;
636 }
637
638
639 int
snmpps(int argc,char * argv[])640 snmpps(int argc, char *argv[])
641 {
642 netsnmp_session session, *ss;
643 int arg;
644 struct hrSWRunTable *procs;
645 int count, pinx = 0;
646
647 /*
648 * get the common command line arguments
649 */
650 switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) {
651 case NETSNMP_PARSE_ARGS_ERROR:
652 exit(1);
653 case NETSNMP_PARSE_ARGS_SUCCESS_EXIT:
654 exit(0);
655 case NETSNMP_PARSE_ARGS_ERROR_USAGE:
656 usage();
657 exit(1);
658 default:
659 break;
660 }
661
662 if (arg != argc) {
663 fprintf(stderr, "snmpps: extra argument: %s\n", argv[arg]);
664 exit(1);
665 }
666
667 SOCK_STARTUP;
668
669 /*
670 * Open an SNMP session.
671 */
672 ss = snmp_open(&session);
673 if (ss == NULL) {
674 /*
675 * diagnose snmp_open errors with the input netsnmp_session pointer
676 */
677 snmp_sess_perror("snmpps", &session);
678 SOCK_CLEANUP;
679 exit(1);
680 }
681
682 count = collect_perf(ss, &procs);
683 if (count == 0) {
684 fprintf(stderr, "snmpps: no processes found\n");
685 exit(1);
686 }
687
688 switch (topsort) {
689 case 'm':
690 qsort(procs, count, sizeof(procs[0]), memcomp);
691 break;
692 case 't':
693 qsort(procs, count, sizeof(procs[0]), totcomp);
694 break;
695 }
696
697 printf("%7s %4s %6s %10s %11s %-10s\n",
698 "Index", "Type", "Status", "Memory", "CPU", "Command");
699
700 while (pinx < count) {
701 struct hrSWRunTable *proc = procs+pinx;
702 const char *hr_status, *hr_type;
703 char b1[15], b2[20];
704
705 switch (proc->hrSWRunType) {
706 case 1: hr_type = "Unkn"; break;
707 case 2: hr_type = "Os"; break;
708 case 3: hr_type = "Drvr"; break;
709 case 4: hr_type = "Appl"; break;
710 default: hr_type = "?"; break;
711 }
712
713 switch (proc->hrSWRunStatus) {
714 case 1: hr_status = "Run"; break;
715 case 2: hr_status = "Wait"; break;
716 case 3: hr_status = "Event"; break;
717 case 4: hr_status = "Inval"; break;
718 default: hr_status = "?"; break;
719 }
720
721 printf("%7lu %4s %6s %10s %11.11s %s %s\n",
722 proc->hrSWRunIndex,
723 hr_type,
724 hr_status,
725 format_humanmem(b1, sizeof b1, proc->hrSWRunPerfMem),
726 format_centisec(b2, sizeof b2, proc->hrSWRunPerfCPU),
727 command_path && proc->hrSWRunPath[0] ? proc->hrSWRunPath : proc->hrSWRunName,
728 command_args ? proc->hrSWRunParameters : "");
729
730 pinx++;
731 }
732
733 snmp_close(ss);
734 SOCK_CLEANUP;
735 return 0;
736 }
737
738
739 #if HAVE_CURSES_H
endtop(int sig)740 static void endtop(int sig)
741 {
742 endwin();
743 exit(1);
744 }
745
746
snmptop(int argc,char ** argv)747 int snmptop(int argc, char **argv)
748 {
749 netsnmp_session session, *ss;
750 int arg;
751 struct hrSWRunTable *oproc;
752 int ocount = 0;
753 int show_idle = 1;
754 int show_os = 1;
755 char ch;
756 struct cpuStats oldCpu;
757 struct memStats mem;
758 int has_cpu, has_mem;
759
760 /*
761 * get the common command line arguments
762 */
763 switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) {
764 case NETSNMP_PARSE_ARGS_ERROR:
765 exit(1);
766 case NETSNMP_PARSE_ARGS_SUCCESS_EXIT:
767 exit(0);
768 case NETSNMP_PARSE_ARGS_ERROR_USAGE:
769 usage();
770 exit(1);
771 default:
772 break;
773 }
774
775 if (arg != argc) {
776 fprintf(stderr, "snmptop: extra argument: %s\n", argv[arg]);
777 exit(1);
778 }
779
780 SOCK_STARTUP;
781
782 /*
783 * Open an SNMP session.
784 */
785 ss = snmp_open(&session);
786 if (ss == NULL) {
787 /*
788 * diagnose snmp_open errors with the input netsnmp_session pointer
789 */
790 snmp_sess_perror("snmptop", &session);
791 SOCK_CLEANUP;
792 exit(1);
793 }
794
795 ocount = collect_perf(ss, &oproc);
796 if (ocount == 0) {
797 fprintf(stderr, "snmptop: no processes found\n");
798 exit(1);
799 }
800
801 collect_cpu(ss, &oldCpu);
802
803 signal(SIGINT, endtop);
804 initscr();
805 cbreak();
806 noecho();
807 nonl();
808 halfdelay(50);
809
810 while ((ch = getch()) != 'q') {
811 int ncount;
812 struct hrSWRunTable *nproc;
813 int oinx = 0, ninx = 0, line = 0;
814 netsnmp_pdu *pdu;
815 netsnmp_pdu *response = NULL;
816 int status;
817 time_t clock;
818 struct tm *ptm;
819 char uptime[40];
820 char timestr[40];
821 char b1[15], b2[15], b3[15], b4[15];
822 struct cpuStats newCpu;
823
824 if (ch == 'c' || ch == 'm' || ch == 'n' || ch == 't') topsort = ch;
825 if (ch == 'i') show_idle = !show_idle;
826 if (ch == 'o') show_os = !show_os;
827 if (ch == 'a') command_args = !command_args;
828 if (ch == 'p') command_path = !command_path;
829
830 ncount = collect_perf(ss, &nproc);
831
832 while (oinx < ocount && ninx < ncount) {
833 if (oproc[oinx].hrSWRunIndex == nproc[ninx].hrSWRunIndex) {
834 nproc[ninx].hrSWRunPerfCPUInc = nproc[ninx].hrSWRunPerfCPU-oproc[oinx].hrSWRunPerfCPU;
835 ninx++;
836 oinx++;
837 }
838 else if (nproc[oinx].hrSWRunIndex < oproc[ninx].hrSWRunIndex)
839 oinx++;
840 else {
841 nproc[ninx].hrSWRunPerfCPUInc = nproc[ninx].hrSWRunPerfCPU;
842 ninx++;
843 }
844 }
845 while (ninx < ncount) {
846 nproc[ninx].hrSWRunPerfCPUInc = nproc[ninx].hrSWRunPerfCPU;
847 ninx++;
848 }
849
850 switch (topsort) {
851 case 'c':
852 qsort(nproc, ncount, sizeof(nproc[0]), cpucomp);
853 break;
854 case 'm':
855 qsort(nproc, ncount, sizeof(nproc[0]), memcomp);
856 break;
857 case 't':
858 qsort(nproc, ncount, sizeof(nproc[0]), totcomp);
859 break;
860 }
861
862 has_cpu = collect_cpu(ss, &newCpu);
863 has_mem = collect_mem(ss, &mem);
864
865 pdu = snmp_pdu_create(SNMP_MSG_GET);
866 add(pdu, "HOST-RESOURCES-MIB:hrSystemUptime.0", NULL, 0);
867 status = snmp_synch_response(ss, pdu, &response);
868 if (status != STAT_SUCCESS || !response ||
869 response->errstat != SNMP_ERR_NOERROR) {
870 uptime[0] = '\0';
871 }
872 else {
873 netsnmp_variable_list *vlp = response->variables;
874 if (vlp->type == SNMP_NOSUCHINSTANCE) abort();
875 uptime_string_n(*vlp->val.integer, uptime, sizeof(uptime));
876 }
877 snmp_free_pdu(response);
878
879 clock = time(NULL);
880 ptm = localtime(&clock);
881 strftime(timestr, sizeof(timestr), "%H:%M:%S", ptm);
882
883 clear();
884 move(0, 0);
885 printw("%s %s%s", session.peername, uptime[0] ? "up " : "", uptime);
886 move(0, COLS-strlen(timestr)-1);
887 printw("%s", timestr);
888 if (has_cpu) {
889 struct cpuStats deltaCpu;
890 u_long sumCpu;
891
892 deltaCpu.user = newCpu.user - oldCpu.user;
893 deltaCpu.nice = newCpu.nice - oldCpu.nice;
894 deltaCpu.system = newCpu.system - oldCpu.system;
895 deltaCpu.idle = newCpu.idle - oldCpu.idle;
896 deltaCpu.wait = newCpu.wait - oldCpu.wait;
897 deltaCpu.kernel = newCpu.kernel - oldCpu.kernel;
898 deltaCpu.intr = newCpu.intr - oldCpu.intr;
899 deltaCpu.softintr = newCpu.softintr - oldCpu.softintr;
900 deltaCpu.steal = newCpu.steal - oldCpu.steal;
901 deltaCpu.guest = newCpu.guest - oldCpu.guest;
902 deltaCpu.guestnice = newCpu.guestnice - oldCpu.guestnice;
903 oldCpu = newCpu;
904 sumCpu = deltaCpu.user + deltaCpu.nice
905 + deltaCpu.system + deltaCpu.idle
906 + deltaCpu.wait + deltaCpu.kernel + deltaCpu.steal
907 + deltaCpu.intr + deltaCpu.softintr
908 + deltaCpu.guest + deltaCpu.guestnice;
909
910 printw("\nCPU%%: %4.1fUs %4.1fSy %4.1fId %3.1fWa %3.1fNi %3.1fKe %3.1fHi %3.1fSi %3.1fSt %3.1fGu %3.1fGN",
911 (float)deltaCpu.user*100/sumCpu,
912 (float)deltaCpu.system*100/sumCpu,
913 (float)deltaCpu.idle*100/sumCpu,
914 (float)deltaCpu.wait*100/sumCpu,
915 (float)deltaCpu.nice*100/sumCpu,
916 (float)deltaCpu.kernel*100/sumCpu,
917 (float)deltaCpu.intr*100/sumCpu,
918 (float)deltaCpu.softintr*100/sumCpu,
919 (float)deltaCpu.steal*100/sumCpu,
920 (float)deltaCpu.guest*100/sumCpu,
921 (float)deltaCpu.guestnice*100/sumCpu);
922 line++;
923 }
924
925 if (has_mem) {
926 printw("\nMem: %10s Total %10s Used %10s Free %10s Buffer",
927 format_humanmem(b1, sizeof b1, mem.totalReal),
928 format_humanmem(b2, sizeof b2, mem.totalReal-mem.availReal),
929 format_humanmem(b3, sizeof b3, mem.availReal),
930 format_humanmem(b4, sizeof b4, mem.buffer));
931 line++;
932 printw("\nSwap: %10s Total %10s Used %10s Free %10s Cached",
933 format_humanmem(b1, sizeof b1, mem.totalSwap),
934 format_humanmem(b2, sizeof b2, mem.totalSwap-mem.availSwap),
935 format_humanmem(b3, sizeof b3, mem.availSwap),
936 format_humanmem(b4, sizeof b4, mem.cached));
937 line++;
938 }
939
940 printw("\n%7s %4s %6s %10s %11s %5s %-10s",
941 "Index", "Type", "Status", "Memory", "Total CPU", "%CPU", "Command");
942 line++;
943 ninx = 0;
944 while (line < LINES && ninx < ncount) {
945 struct hrSWRunTable *proc = nproc+ninx;
946 const char *hr_status, *hr_type;
947
948 ninx++;
949 if (proc->hrSWRunPerfCPUInc == 0 && !show_idle)
950 continue;
951 if (proc->hrSWRunType != 4 && !show_os)
952 continue;
953
954 line++;
955
956 switch (proc->hrSWRunType) {
957 case 1: hr_type = "Unkn"; break;
958 case 2: hr_type = "Os"; break;
959 case 3: hr_type = "Drvr"; break;
960 case 4: hr_type = "Appl"; break;
961 default: hr_type = "?"; break;
962 }
963
964 switch (proc->hrSWRunStatus) {
965 case 1: hr_status = "Run"; break;
966 case 2: hr_status = "Wait"; break;
967 case 3: hr_status = "Event"; break;
968 case 4: hr_status = "Inval"; break;
969 default: hr_status = "?"; break;
970 }
971
972 printw("\n%7lu %4s %6s %10s %11s %5.1f %s %s",
973 proc->hrSWRunIndex,
974 hr_type,
975 hr_status,
976 format_humanmem(b1, sizeof b1, proc->hrSWRunPerfMem),
977 format_sec(b2,sizeof b2, proc->hrSWRunPerfCPU),
978 (float)proc->hrSWRunPerfCPUInc/5,
979 command_path && proc->hrSWRunPath[0] ? proc->hrSWRunPath : proc->hrSWRunName,
980 command_args ? proc->hrSWRunParameters : "");
981 }
982 refresh();
983
984 qsort(nproc, ncount, sizeof(nproc[0]), pidcomp);
985 free_perf(oproc, ocount);
986 oproc = nproc;
987 ocount = ncount;
988 }
989 endwin();
990
991 free_perf(oproc, ocount);
992
993 snmp_close(ss);
994 SOCK_CLEANUP;
995 return 0;
996 }
997 #else
snmptop(int argc,char ** argv)998 int snmptop(int argc, char **argv)
999 {
1000 fprintf(stderr, "%s: curses not detected during configure\n", progname);
1001 return 1;
1002 }
1003 #endif
1004
1005
main(int argc,char ** argv)1006 int main(int argc, char **argv)
1007 {
1008 progname = strrchr(argv[0], '/');
1009 if (progname) progname++;
1010 else progname = argv[0];
1011 if (strncmp(progname, "lt-", 3) == 0) progname += 3;
1012
1013 if (strcmp(progname, "snmpps") == 0) return snmpps(argc, argv);
1014 if (strcmp(progname, "snmptop") == 0) return snmptop(argc, argv);
1015 fprintf(stderr, "%s: unknown prognam name\n", progname);
1016 exit(1);
1017 }
1018