Add socket support to check_mysql*
[monitoring-plugins.git] / plugins-root / pst3.c
blob87340062d30c8da35b1ae8cd871480b3eec942bb
1 /* pst3.c
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.
7 * Developed and tested under Solaris 5.8 (both 32 and 64 bit modes).
9 * NOTE: This program must be setuid-root (or run by root) to work!
11 * Written: 2005-04-28 R.W.Ingraham
15 #define _KMEMUSER 1
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>
35 * Constants
38 #define PROC_DIR "/proc"
39 #define MAX_PATH 1024
43 * Structures
48 * Globals
51 static char * szProg;
52 static kvm_t * kd;
53 static struct proc * pProc;
54 static struct user * pUser;
55 static char ** myArgv;
59 * Prototypes
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();
69 /*----------------------------------------------------------------------------*/
71 int main (int argc, char **argv)
73 DIR *pDir;
74 struct dirent *pDent;
75 int retcode = 0;
78 /* Set our program name global */
79 if ((szProg = strrchr(argv[0], '/')) != NULL)
80 szProg++;
81 else
82 szProg = argv[0];
84 /* Make sure that our euid is root */
85 if (geteuid() != 0)
87 fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg);
88 exit(1);
91 /* Get a handle to the running kernel image */
92 if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, argv[0])) == NULL)
94 fprintf(stderr, "%s: Failed to open kernel memory: %s\n", szProg, strerror(errno));
95 exit(2);
98 /* Open the /proc directory */
99 if ((pDir = opendir(PROC_DIR)) != NULL)
101 /* Display column headings */
102 printf("S UID PPID VSZ RSS %%CPU COMMAND ARGS\n");
104 /* Zip through all of the process entries */
105 while ((pDent = readdir(pDir)) != NULL)
107 /* Handle each pid sub-directory */
108 HandleFile(pDent);
111 /* Close the directory */
112 closedir(pDir);
114 else /* ERROR: Failure to open PROC_DIR */
116 fprintf(stderr, "%s: Failed to open \"%s\": %s\n", szProg, PROC_DIR, strerror(errno));
117 retcode = 3;
120 /* Close the handle to the running kernel image */
121 kvm_close(kd);
123 return retcode;
126 /*----------------------------------------------------------------------------*/
128 static int HandleFile (struct dirent *pDent)
130 char szPath[MAX_PATH];
131 psinfo_t sPsInfo;
132 int fd, len;
133 int rc = 0;
135 /* Skip files beginning with a "." */
136 if (pDent->d_name[0] == '.')
137 return 0;
139 /* Cosntruct the path to the psinfo file */
140 len = sprintf(szPath, "%s/%s/psinfo", PROC_DIR, pDent->d_name);
142 /* Open the psinfo file for this pid and print out its arg vectors */
143 if ((fd = open(szPath, O_RDONLY)) >= 0)
145 /* Read the psinfo struct */
146 if ((len = read(fd, &sPsInfo, sizeof(sPsInfo))) != sizeof(sPsInfo))
148 rc = errno;
149 fprintf(stderr, "%s: Read error of psinfo structure (%d)\n", szPath, len);
150 return rc;
153 /* Close the psinfo file */
154 close(fd);
156 /* Pass psinfo struct to reporting function */
157 HandlePsInfo(szPath, &sPsInfo);
159 else if (errno != ENOENT)
161 rc = errno;
162 fprintf(stderr, "%s: %s\n", szPath, strerror(errno));
165 return 0;
168 /*----------------------------------------------------------------------------*/
170 static int HandlePsInfo (char *szPath, psinfo_t *pPsInfo)
172 int retcode;
173 char *thisProg;
175 /* Make sure that the process is still there */
176 if ((retcode = GetArgVectors(pPsInfo->pr_pid)) == 0)
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.
182 * Also, strip-off leading path information.
184 if ((thisProg = strrchr(myArgv[0], '/')) != NULL)
185 thisProg++;
186 else
187 thisProg = myArgv[0];
189 /* Display the ps columns (except for argv) */
190 printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ",
191 pPsInfo->pr_lwp.pr_sname,
192 (int)(pPsInfo->pr_euid),
193 (int)(pPsInfo->pr_pid),
194 (int)(pPsInfo->pr_ppid),
195 (unsigned long)(pPsInfo->pr_size),
196 (unsigned long)(pPsInfo->pr_rssize),
197 ((float)(pPsInfo->pr_pctcpu) / 0x8000 * 100.0),
198 thisProg);
200 /* Display the arg vectors associated with this pid */
201 ShowArgVectors();
203 /* Release the arg vector buffer memory */
204 ReleaseArgVectors();
207 return retcode;
210 /*----------------------------------------------------------------------------*/
212 static int GetArgVectors (pid_t pid)
214 int retcode = 1;
216 /* Get the proc structure for the specified PID */
217 if ((pProc = kvm_getproc(kd, pid)) != NULL)
219 /* Save a copy of the process' u-area */
220 if ((pUser = kvm_getu(kd, pProc)) != NULL)
222 /* Reconstruct the process' argv vector array */
223 if (kvm_getcmd(kd, pProc, pUser, &myArgv, NULL) == 0)
225 retcode = 0;
230 return retcode;
233 /*----------------------------------------------------------------------------*/
235 static void ShowArgVectors (void)
237 int i;
239 for (i=0; myArgv[i]; i++)
241 printf(" %s", myArgv[i]);
243 printf("\n");
246 /*----------------------------------------------------------------------------*/
248 static void ReleaseArgVectors()
250 /* NOOP */
253 /*----------------------------------------------------------------------------*/