summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--THANKS.in1
-rw-r--r--configure.in11
-rw-r--r--plugins-root/pst3.c252
3 files changed, 263 insertions, 1 deletions
diff --git a/THANKS.in b/THANKS.in
index c83997ec..fb73b141 100644
--- a/THANKS.in
+++ b/THANKS.in
@@ -168,3 +168,4 @@ Ronald Tin
168Chester Hosey 168Chester Hosey
169Pascal Larisch 169Pascal Larisch
170David Sullivan 170David Sullivan
171Bob 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
598AC_PATH_PROG(PATH_TO_PS,ps) 598AC_PATH_PROG(PATH_TO_PS,ps)
599 599
600AC_MSG_CHECKING(for ps syntax) 600AC_MSG_CHECKING(for ps syntax)
601
602dnl Now using the pst3/kmem hack for solaris systems to avoid truncation
603if [ "$ac_cv_uname_s" = "SunOS" ]; then
604 ac_cv_ps_command="$prefix/pst3"
605 ac_cv_ps_format="%s %d %d %d %d %f %s %n"
606 ac_cv_ps_varlist="[procstat,&procuid,&procppid,&procvsz,&procrss,&procpcpu,procprog,&pos]"
607 ac_cv_ps_cols=8
608 AC_MSG_RESULT([using nagios-plugins internal ps for solaris])
609
601dnl Some gnu/linux systems (debian for one) don't like -axwo and need axwo. 610dnl Some gnu/linux systems (debian for one) don't like -axwo and need axwo.
602dnl so test for this first... 611dnl so test for this first...
603if ps axwo 'stat comm vsz rss user uid pid ppid args' 2>/dev/null | \ 612elif ps axwo 'stat comm vsz rss user uid pid ppid args' 2>/dev/null | \
604 egrep -i ["^ *STAT +[UCOMAND]+ +VSZ +RSS +USER +UID +PID +PPID +COMMAND"] > /dev/null 613 egrep -i ["^ *STAT +[UCOMAND]+ +VSZ +RSS +USER +UID +PID +PPID +COMMAND"] > /dev/null
605then 614then
606 ac_cv_ps_varlist="[procstat,&procuid,&procpid,&procppid,&procvsz,&procrss,&procpcpu,procprog,&pos]" 615 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 @@
1/* pst3.c
2 *
3 * Third version to get process arg info; this time by using
4 * a combination of reading the /proc/<pid>/psinfo structures
5 * and reading the complete arg vector from kernel memory structures.
6 *
7 * Developed and tested under Solaris 5.8 (both 32 and 64 bit modes).
8 *
9 * NOTE: This program must be setuid-root (or run by root) to work!
10 *
11 * Written: 2005-04-28 R.W.Ingraham
12 */
13
14
15#define _KMEMUSER 1
16
17#include <kvm.h>
18#include <sys/param.h>
19#include <sys/user.h>
20#include <sys/time.h>
21#include <sys/proc.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <unistd.h>
27#include <string.h>
28#include <procfs.h>
29#include <fcntl.h>
30#include <dirent.h>
31#include <errno.h>
32
33
34/*
35 * Constants
36 */
37
38#define PROC_DIR "/proc"
39#define MAX_PATH 1024
40
41
42/*
43 * Structures
44 */
45
46
47/*
48 * Globals
49 */
50
51static char * szProg;
52static kvm_t * kd;
53static struct proc * pProc;
54static struct user * pUser;
55static char ** myArgv;
56
57
58/*
59 * Prototypes
60 */
61
62static int HandleFile (struct dirent *pDent);
63static int HandlePsInfo (char *szPath, psinfo_t *pPsInfo);
64static int GetArgVectors (pid_t pid);
65static void ShowArgVectors (void);
66static void ReleaseArgVectors();
67
68
69/*----------------------------------------------------------------------------*/
70
71int main (int argc, char **argv)
72{
73 DIR *pDir;
74 struct dirent *pDent;
75 int retcode = 0;
76
77
78 /* Set our program name global */
79 if ((szProg = strrchr(argv[0], '/')) != NULL)
80 szProg++;
81 else
82 szProg = argv[0];
83
84 /* Make sure that our euid is root */
85 if (geteuid() != 0)
86 {
87 fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg);
88 exit(1);
89 }
90
91 /* Get a handle to the running kernel image */
92 if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, argv[0])) == NULL)
93 {
94 fprintf(stderr, "%s: Failed to open kernel memory: %s\n", szProg, strerror(errno));
95 exit(2);
96 }
97
98 /* Open the /proc directory */
99 if ((pDir = opendir(PROC_DIR)) != NULL)
100 {
101 /* Display column headings */
102 printf("S UID PPID VSZ RSS %%CPU COMMAND ARGS\n");
103
104 /* Zip through all of the process entries */
105 while ((pDent = readdir(pDir)) != NULL)
106 {
107 /* Handle each pid sub-directory */
108 HandleFile(pDent);
109 }
110
111 /* Close the directory */
112 closedir(pDir);
113 }
114 else /* ERROR: Failure to open PROC_DIR */
115 {
116 fprintf(stderr, "%s: Failed to open \"%s\": %s\n", szProg, PROC_DIR, strerror(errno));
117 retcode = 3;
118 }
119
120 /* Close the handle to the running kernel image */
121 kvm_close(kd);
122
123 return retcode;
124}
125
126/*----------------------------------------------------------------------------*/
127
128static int HandleFile (struct dirent *pDent)
129{
130 char szPath[MAX_PATH];
131 psinfo_t sPsInfo;
132 int fd, len;
133 int rc = 0;
134
135 /* Skip files beginning with a "." */
136 if (pDent->d_name[0] == '.')
137 return 0;
138
139 /* Cosntruct the path to the psinfo file */
140 len = sprintf(szPath, "%s/%s/psinfo", PROC_DIR, pDent->d_name);
141
142 /* Open the psinfo file for this pid and print out its arg vectors */
143 if ((fd = open(szPath, O_RDONLY)) >= 0)
144 {
145 /* Read the psinfo struct */
146 if ((len = read(fd, &sPsInfo, sizeof(sPsInfo))) != sizeof(sPsInfo))
147 {
148 rc = errno;
149 fprintf(stderr, "%s: Read error of psinfo structure (%d)\n", szPath, len);
150 return rc;
151 }
152
153 /* Close the psinfo file */
154 close(fd);
155
156 /* Pass psinfo struct to reporting function */
157 HandlePsInfo(szPath, &sPsInfo);
158 }
159 else if (errno != ENOENT)
160 {
161 rc = errno;
162 fprintf(stderr, "%s: %s\n", szPath, strerror(errno));
163 }
164
165 return 0;
166}
167
168/*----------------------------------------------------------------------------*/
169
170static int HandlePsInfo (char *szPath, psinfo_t *pPsInfo)
171{
172 int retcode;
173 char *thisProg;
174
175 /* Make sure that the process is still there */
176 if ((retcode = GetArgVectors(pPsInfo->pr_pid)) == 0)
177 {
178 /* We use the program name from the kvm argv[0] instead
179 * of pr_fname from the psinfo struct because pr_fname
180 * may be truncated.
181 *
182 * Also, strip-off leading path information.
183 */
184 if ((thisProg = strrchr(myArgv[0], '/')) != NULL)
185 thisProg++;
186 else
187 thisProg = myArgv[0];
188
189 /* Display the ps columns (except for argv) */
190 printf("%c %5d %5d %6lu %6lu %4.1f %s ",
191 pPsInfo->pr_lwp.pr_sname,
192 (int)(pPsInfo->pr_euid),
193 (int)(pPsInfo->pr_ppid),
194 (unsigned long)(pPsInfo->pr_size),
195 (unsigned long)(pPsInfo->pr_rssize),
196 ((float)(pPsInfo->pr_pctcpu) / 0x8000 * 100.0),
197 thisProg);
198
199 /* Display the arg vectors associated with this pid */
200 ShowArgVectors();
201
202 /* Release the arg vector buffer memory */
203 ReleaseArgVectors();
204 }
205
206 return retcode;
207}
208
209/*----------------------------------------------------------------------------*/
210
211static int GetArgVectors (pid_t pid)
212{
213 int retcode = 1;
214
215 /* Get the proc structure for the specified PID */
216 if ((pProc = kvm_getproc(kd, pid)) != NULL)
217 {
218 /* Save a copy of the process' u-area */
219 if ((pUser = kvm_getu(kd, pProc)) != NULL)
220 {
221 /* Reconstruct the process' argv vector array */
222 if (kvm_getcmd(kd, pProc, pUser, &myArgv, NULL) == 0)
223 {
224 retcode = 0;
225 }
226 }
227 }
228
229 return retcode;
230}
231
232/*----------------------------------------------------------------------------*/
233
234static void ShowArgVectors (void)
235{
236 int i;
237
238 for (i=0; myArgv[i]; i++)
239 {
240 printf(" %s", myArgv[i]);
241 }
242 printf("\n");
243}
244
245/*----------------------------------------------------------------------------*/
246
247static void ReleaseArgVectors()
248{
249 /* NOOP */
250}
251
252/*----------------------------------------------------------------------------*/