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 | |||
168 | Chester Hosey | 168 | Chester Hosey |
169 | Pascal Larisch | 169 | Pascal Larisch |
170 | David Sullivan | 170 | David Sullivan |
171 | 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 | |||
598 | AC_PATH_PROG(PATH_TO_PS,ps) | 598 | AC_PATH_PROG(PATH_TO_PS,ps) |
599 | 599 | ||
600 | AC_MSG_CHECKING(for ps syntax) | 600 | AC_MSG_CHECKING(for ps syntax) |
601 | |||
602 | dnl Now using the pst3/kmem hack for solaris systems to avoid truncation | ||
603 | if [ "$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 | |||
601 | dnl Some gnu/linux systems (debian for one) don't like -axwo and need axwo. | 610 | dnl Some gnu/linux systems (debian for one) don't like -axwo and need axwo. |
602 | dnl so test for this first... | 611 | dnl so test for this first... |
603 | if ps axwo 'stat comm vsz rss user uid pid ppid args' 2>/dev/null | \ | 612 | elif 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 |
605 | then | 614 | then |
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 | |||
51 | static char * szProg; | ||
52 | static kvm_t * kd; | ||
53 | static struct proc * pProc; | ||
54 | static struct user * pUser; | ||
55 | static char ** myArgv; | ||
56 | |||
57 | |||
58 | /* | ||
59 | * Prototypes | ||
60 | */ | ||
61 | |||
62 | static int HandleFile (struct dirent *pDent); | ||
63 | static int HandlePsInfo (char *szPath, psinfo_t *pPsInfo); | ||
64 | static int GetArgVectors (pid_t pid); | ||
65 | static void ShowArgVectors (void); | ||
66 | static void ReleaseArgVectors(); | ||
67 | |||
68 | |||
69 | /*----------------------------------------------------------------------------*/ | ||
70 | |||
71 | int 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 | |||
128 | static 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 | |||
170 | static 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 | |||
211 | static 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 | |||
234 | static 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 | |||
247 | static void ReleaseArgVectors() | ||
248 | { | ||
249 | /* NOOP */ | ||
250 | } | ||
251 | |||
252 | /*----------------------------------------------------------------------------*/ | ||