Revision: 2016
http://nagiosplug.svn.sourceforge.net/nagiosplug/?rev=2016&view=rev
Author: tonvoon
Date: 2008-07-02 13:00:08 -0700 (Wed, 02 Jul 2008)
Log Message:
-----------
Change pst3 again, this time to remove use of kvm which is not
available in Solaris 10 non-global zones. Uses /proc, which is not
available in older versions of Solaris.
Modified Paths:
--------------
nagiosplug/trunk/plugins-root/Makefile.am
nagiosplug/trunk/plugins-root/pst3.c
Modified: nagiosplug/trunk/plugins-root/Makefile.am
===================================================================
--- nagiosplug/trunk/plugins-root/Makefile.am 2008-06-30 14:32:53 UTC (rev 2015)
+++ nagiosplug/trunk/plugins-root/Makefile.am 2008-07-02 20:00:08 UTC (rev 2016)
@@ -71,7 +71,6 @@
# -m64 needed at compiler and linker phase
pst3_CFLAGS = @PST3CFLAGS@
pst3_LDFLAGS = @PST3CFLAGS@
-pst3_LDADD = -lkvm
check_dhcp_DEPENDENCIES = check_dhcp.c $(NETOBJS) $(DEPLIBS)
check_icmp_DEPENDENCIES = check_icmp.c $(NETOBJS)
Modified: nagiosplug/trunk/plugins-root/pst3.c
===================================================================
--- nagiosplug/trunk/plugins-root/pst3.c 2008-06-30 14:32:53 UTC (rev 2015)
+++ nagiosplug/trunk/plugins-root/pst3.c 2008-07-02 20:00:08 UTC (rev 2016)
@@ -12,10 +12,19 @@
* is not possible with the standard ps command (due to truncation). /usr/ucb/ps
* also has issues where some fields run into each other.
*
-* This executable works by reading the kernel memory structures, so needs
+* This executable works by reading process address structures, so needs
* to be executed as root
*
* Originally written by R.W.Ingraham
+* Rewritten by Duncan Ferguson (Altinity Ltd, June 2008)
+* The rewrite was necessary as /dev/kmem is not available within
+* non-global zones on Solaris 10
+*
+* Details for rewrite came from
+* source of /usr/ucb/ps on Solaris:
+* http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/ucbcmd/ps/ps.c#argvoff
+* usenet group posting
+* http://groups.google.com/group/comp.unix.solaris/tree/browse_frm/month/2001-09/bfa40c08bac819a2?rnum=141&_done=%2Fgroup%2Fcomp.unix.solaris%2Fbrowse_frm%2Fmonth%2F2001-09%3F
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,185 +41,216 @@
*
*****************************************************************************/
-#define _KMEMUSER 1
-
-#include <kvm.h>
-#include <sys/param.h>
-#include <sys/user.h>
-#include <sys/time.h>
-#include <sys/proc.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <procfs.h>
-#include <fcntl.h>
#include <dirent.h>
#include <errno.h>
+#include <fcntl.h>
+#include <procfs.h>
+#include <errno.h>
+#include <sys/types32.h>
-
/*
- * Constants
+ * Constants
*/
-#define PROC_DIR "/proc"
-#define MAX_PATH 1024
-#define OK 0
-#define FAIL NULL
+#define PROC_DIR "/proc"
+#define ARGS 30
-
/*
- * Structures
+ * Globals
*/
-
-/*
- * Globals
- */
-
static char * szProg;
-static kvm_t * kd;
-static struct proc * pProc;
-static struct user * pUser;
-static char ** myArgv;
-
/*
- * Prototypes
+ * Prototypes
*/
+void usage();
-static void output_info(struct proc *proc_kvm,char **proc_argv);
-static void HandleProc(struct proc *proc);
-
/*----------------------------------------------------------------------------*/
int main (int argc, char **argv)
{
- DIR *pDir;
- struct dirent *pDent;
- int retcode = 0;
- struct proc *proc;
- struct pid pid;
+ DIR *procdir;
+ struct dirent *proc;
+ char ps_name[ARGS];
+ char as_name[ARGS];
+ psinfo_t psinfo;
- /* Set our program name global */
- if ((szProg = strrchr(argv[0], '/')) != NULL)
- szProg++;
- else
- szProg = argv[0];
+ /* Set our program name global */
+ if ((szProg = strrchr(argv[0], '/')) != NULL)
+ szProg++;
+ else
+ szProg = argv[0];
- /* Make sure that our euid is root */
- if (geteuid() != 0)
- {
- fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg);
- exit(1);
- }
+ /* if given any parameters, print out help */
+ if(argc > 1) {
+ (void)usage();
+ exit(1);
+ }
- /* Get a handle to the running kernel image */
- if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, argv[0])) == NULL)
- {
- fprintf(stderr, "%s: Failed to open kernel memory: %s\n", szProg, strerror(errno));
- exit(2);
- }
+ /* Make sure that our euid is root */
+ if (geteuid() != 0)
+ {
+ fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg);
+ exit(1);
+ }
- /* reset to first proc in list */
- if(kvm_setproc(kd) == -1) {
- perror("kvm_setproc");
- exit(2);
- }
+ if ((procdir = opendir(PROC_DIR)) == NULL) {
+ fprintf(stderr, "%s: cannot open PROC directory %s\n", szProg, PROC_DIR);
+ exit(1);
+ }
- /* Display column headings */
- printf("%c %5s %5s %5s %6s %6s %4s %s %s\n",
- 'S',
- "UID",
- "PID",
- "PPID",
- "VSZ",
- "RSS",
- "%CPU",
- "COMMAND",
- "ARGS"
- );
+ /* Display column headings */
+ printf("%c %5s %5s %5s %6s %6s %4s %s %s\n",
+ 'S',
+ "UID",
+ "PID",
+ "PPID",
+ "VSZ",
+ "RSS",
+ "%CPU",
+ "COMMAND",
+ "ARGS"
+ );
- /* Zip through all of the process entries */
- while((proc = kvm_nextproc(kd)) != 0) {
- HandleProc(proc);
- }
+ /* Zip through all of the process entries */
+ while((proc = readdir(procdir))) {
+ int ps_fd;
+ int as_fd;
+ off_t argoff;
+ int i;
+ char *args;
+ char *procname;
+ char *ptr;
+ int argslen;
+ uintptr_t args_addr;;
+ uintptr_t *args_vecs;;
+ int args_count;
- /* Close the handle to the running kernel image */
- kvm_close(kd);
+ if(proc->d_name[0] == '.')
+ continue;
- return retcode;
-}
+ sprintf(ps_name,"%s/%s/%s",PROC_DIR,proc->d_name,"psinfo");
+ sprintf(as_name,"%s/%s/%s",PROC_DIR,proc->d_name,"as");
+try_again:
+ if((ps_fd = open(ps_name, O_RDONLY)) == -1)
+ continue;
-/*----------------------------------------------------------------------------*/
+ if((as_fd = open(as_name, O_RDONLY)) == -1)
+ continue;
-static void HandleProc(struct proc *proc)
-{
- struct pid pid;
- struct user *user;
- char **proc_argv = NULL;
+ if(read(ps_fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) {
+ int err = errno;
+ close(ps_fd);
+ close(as_fd);
+ if(err == EAGAIN) goto try_again;
+ if(err != ENOENT)
+ fprintf(stderr, "%s: read() on %s: %s\n", szProg,
+ ps_name, strerror(err));
+ continue;
+ }
+ close(ps_fd);
- if(kvm_kread(kd, (unsigned long) proc->p_pidp, (char *) &pid, sizeof pid) == -1) {
- perror("kvm_read error");
- exit(2);
- }
- proc->p_pidp = &pid;
- user = kvm_getu(kd, proc);
+ /* system process, ignore since the previous version did */
+ if(
+ psinfo.pr_nlwp == 0 ||
+ strcmp(psinfo.pr_lwp.pr_clname, "SYS") == 0
+ ) {
+ continue;
+ }
- if(kvm_getcmd(kd, proc, user, &proc_argv, NULL) == -1) {
- return;
- }
+ /* get the procname to match previous versions */
+ procname = strdup(psinfo.pr_psargs);
+ if((ptr = strchr(procname, ' ')) != NULL)
+ *ptr = '\0';
+ if((ptr = strrchr(procname, '/')) != NULL)
+ ptr++;
+ else
+ ptr = procname;
- if(proc_argv == NULL) {
- return;
- }
+ /*
+ * print out what we currently know
+ */
+ printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ",
+ psinfo.pr_lwp.pr_sname,
+ psinfo.pr_euid,
+ psinfo.pr_pid,
+ psinfo.pr_ppid,
+ psinfo.pr_size,
+ psinfo.pr_rssize,
+ ((float)(psinfo.pr_pctcpu) / 0x8000 * 100.0),
+ ptr
+ );
+ free(procname);
- output_info(proc, proc_argv);
- free(proc_argv);
-}
+ /*
+ * and now for the command line stuff
+ */
-static void output_info(struct proc *proc_kvm, char **proc_argv)
-{
- char procpath[MAX_PATH];
- psinfo_t procinfo;
- int fd, len;
- char *procname;
- int i;
+ args_addr = psinfo.pr_argv;
+ args_count = psinfo.pr_argc;
+ args_vecs = malloc(args_count * sizeof(uintptr_t));
- sprintf(procpath, "/proc/%d/psinfo", proc_kvm->p_pidp->pid_id);
+ if(psinfo.pr_dmodel == PR_MODEL_NATIVE) {
+ /* this process matches target process */
+ pread(as_fd,args_vecs, args_count * sizeof(uintptr_t),
+ args_addr);
+ } else {
+ /* this process is 64bit, target process is 32 bit*/
+ caddr32_t *args_vecs32 = (caddr32_t *)args_vecs;
+ pread(as_fd,args_vecs32,args_count * sizeof(caddr32_t),
+ args_addr);
+ for (i=args_count-1;i>=0;--i)
+ args_vecs[i]=args_vecs32[i];
+ }
- if ((fd = open(procpath, O_RDONLY)) >= 0)
- {
- if ((len = read(fd, &procinfo, sizeof(procinfo))) != sizeof(procinfo))
- {
- fprintf(stderr,"%s: Read error of psinfo structure (%d)\n", procpath, len);
- exit(2);
- }
- close(fd);
- }
+ /*
+ * now read in the args - if what we read in fills buffer
+ * resize buffer and reread that bit again
+ */
+ argslen=ARGS;
+ args=malloc(argslen+1);
+ for(i=0;i<args_count;i++) {
+ memset(args,'\0',argslen+1);
+ if(pread(as_fd, args, argslen, args_vecs[i]) <= 0) {
+ break;
+ }
+ args[argslen]='\0';
+ if(strlen(args) == argslen){
+ argslen += ARGS;
+ args = realloc(args, argslen + 1);
+ i--;
+ continue;
+ }
+ printf(" %s", args);
+ }
+ free(args_vecs);
+ free(args);
+ printf("\n");
+ }
- if((procname = strrchr(proc_argv[0], '/')) != NULL)
- procname++;
- else
- procname = proc_argv[0];
+ return (0);
+}
- printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ",
- procinfo.pr_lwp.pr_sname,
- (int)(procinfo.pr_euid),
- (int)proc_kvm->p_pidp->pid_id,
- (int)proc_kvm->p_ppid,
- (unsigned long)(procinfo.pr_size),
- (unsigned long)(procinfo.pr_rssize),
- ((float)(procinfo.pr_pctcpu) / 0x8000 * 100.0),
- procname
- );
+/*----------------------------------------------------------------------------*/
- for(i=0;proc_argv[i];i++) {
- printf(" %s", proc_argv[i]);
- }
-
- printf("\n");
+void usage() {
+ printf("%s: Help output\n\n", szProg);
+ printf("If this program is given any arguments, this help is displayed.\n");
+ printf("This command is used to print out the full command line for all\n");
+ printf("running processes because /usr/bin/ps is limited to 80 chars and\n");
+ printf("/usr/ucb/ps can merge columns together.\n\n");
+ printf("Columns are:\n");
+ printf("\tS - State of process - see 'ps' man page\n");
+ printf("\tUID - UID of the process owner\n");
+ printf("\tPID - PID of the process\n");
+ printf("\tPPID - PID of the parent process\n");
+ printf("\tVSZ - Virtual memory usage (kilobytes)\n");
+ printf("\tRSS - Real memory usage (kilobytes)\n");
+ printf("\t%%CPU - CPU usage\n");
+ printf("\tCOMMAND - Command being run\n");
+ printf("\tARGS - Full command line with arguements\n");
+ return;
}
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.