diff options
-rw-r--r-- | THANKS.in | 1 | ||||
-rw-r--r-- | configure.in | 11 | ||||
-rw-r--r-- | plugins-root/pst3.c | 252 |
3 files changed, 263 insertions, 1 deletions
@@ -168,3 +168,4 @@ Ronald Tin Chester Hosey Pascal Larisch David Sullivan +Bob Ingraham diff --git a/configure.in b/configure.in index ee5fb906..176a8e22 100644 --- a/configure.in +++ b/configure.in @@ -598,9 +598,18 @@ dnl #### Process table test AC_PATH_PROG(PATH_TO_PS,ps) AC_MSG_CHECKING(for ps syntax) + +dnl Now using the pst3/kmem hack for solaris systems to avoid truncation +if [ "$ac_cv_uname_s" = "SunOS" ]; then + ac_cv_ps_command="$prefix/pst3" + ac_cv_ps_format="%s %d %d %d %d %f %s %n" + ac_cv_ps_varlist="[procstat,&procuid,&procppid,&procvsz,&procrss,&procpcpu,procprog,&pos]" + ac_cv_ps_cols=8 + AC_MSG_RESULT([using nagios-plugins internal ps for solaris]) + dnl Some gnu/linux systems (debian for one) don't like -axwo and need axwo. dnl so test for this first... -if ps axwo 'stat comm vsz rss user uid pid ppid args' 2>/dev/null | \ +elif ps axwo 'stat comm vsz rss user uid pid ppid args' 2>/dev/null | \ egrep -i ["^ *STAT +[UCOMAND]+ +VSZ +RSS +USER +UID +PID +PPID +COMMAND"] > /dev/null then ac_cv_ps_varlist="[procstat,&procuid,&procpid,&procppid,&procvsz,&procrss,&procpcpu,procprog,&pos]" diff --git a/plugins-root/pst3.c b/plugins-root/pst3.c new file mode 100644 index 00000000..ace3113c --- /dev/null +++ b/plugins-root/pst3.c @@ -0,0 +1,252 @@ +/* pst3.c + * + * Third version to get process arg info; this time by using + * a combination of reading the /proc/<pid>/psinfo structures + * and reading the complete arg vector from kernel memory structures. + * + * Developed and tested under Solaris 5.8 (both 32 and 64 bit modes). + * + * NOTE: This program must be setuid-root (or run by root) to work! + * + * Written: 2005-04-28 R.W.Ingraham + */ + + +#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> + + +/* + * Constants + */ + +#define PROC_DIR "/proc" +#define MAX_PATH 1024 + + +/* + * Structures + */ + + +/* + * Globals + */ + +static char * szProg; +static kvm_t * kd; +static struct proc * pProc; +static struct user * pUser; +static char ** myArgv; + + +/* + * Prototypes + */ + +static int HandleFile (struct dirent *pDent); +static int HandlePsInfo (char *szPath, psinfo_t *pPsInfo); +static int GetArgVectors (pid_t pid); +static void ShowArgVectors (void); +static void ReleaseArgVectors(); + + +/*----------------------------------------------------------------------------*/ + +int main (int argc, char **argv) +{ + DIR *pDir; + struct dirent *pDent; + int retcode = 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); + } + + /* 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); + } + + /* Open the /proc directory */ + if ((pDir = opendir(PROC_DIR)) != NULL) + { + /* Display column headings */ + printf("S UID PPID VSZ RSS %%CPU COMMAND ARGS\n"); + + /* Zip through all of the process entries */ + while ((pDent = readdir(pDir)) != NULL) + { + /* Handle each pid sub-directory */ + HandleFile(pDent); + } + + /* Close the directory */ + closedir(pDir); + } + else /* ERROR: Failure to open PROC_DIR */ + { + fprintf(stderr, "%s: Failed to open \"%s\": %s\n", szProg, PROC_DIR, strerror(errno)); + retcode = 3; + } + + /* Close the handle to the running kernel image */ + kvm_close(kd); + + return retcode; +} + +/*----------------------------------------------------------------------------*/ + +static int HandleFile (struct dirent *pDent) +{ + char szPath[MAX_PATH]; + psinfo_t sPsInfo; + int fd, len; + int rc = 0; + + /* Skip files beginning with a "." */ + if (pDent->d_name[0] == '.') + return 0; + + /* Cosntruct the path to the psinfo file */ + len = sprintf(szPath, "%s/%s/psinfo", PROC_DIR, pDent->d_name); + + /* Open the psinfo file for this pid and print out its arg vectors */ + if ((fd = open(szPath, O_RDONLY)) >= 0) + { + /* Read the psinfo struct */ + if ((len = read(fd, &sPsInfo, sizeof(sPsInfo))) != sizeof(sPsInfo)) + { + rc = errno; + fprintf(stderr, "%s: Read error of psinfo structure (%d)\n", szPath, len); + return rc; + } + + /* Close the psinfo file */ + close(fd); + + /* Pass psinfo struct to reporting function */ + HandlePsInfo(szPath, &sPsInfo); + } + else if (errno != ENOENT) + { + rc = errno; + fprintf(stderr, "%s: %s\n", szPath, strerror(errno)); + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ + +static int HandlePsInfo (char *szPath, psinfo_t *pPsInfo) +{ + int retcode; + char *thisProg; + + /* Make sure that the process is still there */ + if ((retcode = GetArgVectors(pPsInfo->pr_pid)) == 0) + { + /* We use the program name from the kvm argv[0] instead + * of pr_fname from the psinfo struct because pr_fname + * may be truncated. + * + * Also, strip-off leading path information. + */ + if ((thisProg = strrchr(myArgv[0], '/')) != NULL) + thisProg++; + else + thisProg = myArgv[0]; + + /* Display the ps columns (except for argv) */ + printf("%c %5d %5d %6lu %6lu %4.1f %s ", + pPsInfo->pr_lwp.pr_sname, + (int)(pPsInfo->pr_euid), + (int)(pPsInfo->pr_ppid), + (unsigned long)(pPsInfo->pr_size), + (unsigned long)(pPsInfo->pr_rssize), + ((float)(pPsInfo->pr_pctcpu) / 0x8000 * 100.0), + thisProg); + + /* Display the arg vectors associated with this pid */ + ShowArgVectors(); + + /* Release the arg vector buffer memory */ + ReleaseArgVectors(); + } + + return retcode; +} + +/*----------------------------------------------------------------------------*/ + +static int GetArgVectors (pid_t pid) +{ + int retcode = 1; + + /* Get the proc structure for the specified PID */ + if ((pProc = kvm_getproc(kd, pid)) != NULL) + { + /* Save a copy of the process' u-area */ + if ((pUser = kvm_getu(kd, pProc)) != NULL) + { + /* Reconstruct the process' argv vector array */ + if (kvm_getcmd(kd, pProc, pUser, &myArgv, NULL) == 0) + { + retcode = 0; + } + } + } + + return retcode; +} + +/*----------------------------------------------------------------------------*/ + +static void ShowArgVectors (void) +{ + int i; + + for (i=0; myArgv[i]; i++) + { + printf(" %s", myArgv[i]); + } + printf("\n"); +} + +/*----------------------------------------------------------------------------*/ + +static void ReleaseArgVectors() +{ + /* NOOP */ +} + +/*----------------------------------------------------------------------------*/ |