Code

Reverted check_procs for solaris back to using pst3 due to truncation
[nagiosplug.git] / plugins-root / pst3.c
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 */
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>
34 /*
35  *      Constants
36  */
38 #define PROC_DIR        "/proc"
39 #define MAX_PATH        1024
42 /*
43  *      Structures
44  */
47 /*
48  *      Globals
49  */
51 static char *        szProg;
52 static kvm_t *       kd;
53 static struct proc * pProc;
54 static struct user * pUser;
55 static char **       myArgv;
58 /*
59  *      Prototypes
60  */
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)
72 {
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)
86         {
87                 fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg);
88                 exit(1);
89         }
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         }
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");
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                 }
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         }
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)
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                 }
153                 /* Close the psinfo file */
154                 close(fd);
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         }
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)
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 %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();
205         }
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)
218         {
219                 /* Save a copy of the process' u-area */
220                 if ((pUser = kvm_getu(kd, pProc)) != NULL)
221                 {
222                         /* Reconstruct the process' argv vector array */
223                         if (kvm_getcmd(kd, pProc, pUser, &myArgv, NULL) == 0)
224                         {
225                                 retcode = 0;
226                         }
227                 }
228         }
230         return retcode;
233 /*----------------------------------------------------------------------------*/
235 static void ShowArgVectors (void)
237         int i;
239         for (i=0; myArgv[i]; i++)
240         {
241                 printf(" %s", myArgv[i]);
242         }
243         printf("\n");
246 /*----------------------------------------------------------------------------*/
248 static void ReleaseArgVectors()
250         /* NOOP */
253 /*----------------------------------------------------------------------------*/