Code

Fixed possible coredump. Removed one level of subroutines (Duncan Ferguson)
[nagiosplug.git] / plugins-root / pst3.c
1 /*****************************************************************************
2
3 * pst3
4
5 * License: GPL
6 * Copyright (c) 2008 Nagios Plugin Development Team
7
8 * Description:
9
10 * This file contains the pst3 executable. This is a replacement ps command
11 * for Solaris to get output which provides a long argument listing, which 
12 * is not possible with the standard ps command (due to truncation). /usr/ucb/ps
13 * also has issues where some fields run into each other.
14
15 * This executable works by reading the kernel memory structures, so needs
16 * to be executed as root
17 *
18 * Originally written by R.W.Ingraham
19
20 * This program is free software: you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation, either version 3 of the License, or
23 * (at your option) any later version.
24
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28 * GNU General Public License for more details.
29
30 * You should have received a copy of the GNU General Public License
31 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
32
33 *****************************************************************************/
35 #define _KMEMUSER       1
37 #include <kvm.h>
38 #include <sys/param.h>
39 #include <sys/user.h>
40 #include <sys/time.h>
41 #include <sys/proc.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <string.h>
48 #include <procfs.h>
49 #include <fcntl.h>
50 #include <dirent.h>
51 #include <errno.h>
54 /*
55  *      Constants
56  */
58 #define PROC_DIR        "/proc"
59 #define MAX_PATH        1024
60 #define OK 0
61 #define FAIL NULL
64 /*
65  *      Structures
66  */
69 /*
70  *      Globals
71  */
73 static char *        szProg;
74 static kvm_t *       kd;
75 static struct proc * pProc;
76 static struct user * pUser;
77 static char **       myArgv;
80 /*
81  *      Prototypes
82  */
84 static void output_info(struct proc *proc_kvm,char **proc_argv);
85 static void HandleProc(struct proc *proc);
87 /*----------------------------------------------------------------------------*/
89 int main (int argc, char **argv)
90 {
91         DIR *pDir;
92         struct dirent *pDent;
93         int retcode = 0;
94         struct proc *proc;
95         struct pid pid;
97         /* Set our program name global */
98         if ((szProg = strrchr(argv[0], '/')) != NULL)
99                 szProg++;
100         else
101                 szProg = argv[0];
103         /* Make sure that our euid is root */
104         if (geteuid() != 0)
105         {
106                 fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg);
107                 exit(1);
108         }
110         /* Get a handle to the running kernel image */
111         if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, argv[0])) == NULL)
112         {
113                 fprintf(stderr, "%s: Failed to open kernel memory: %s\n", szProg, strerror(errno));
114                 exit(2);
115         }
117         /* reset to first proc in list */
118         if(kvm_setproc(kd) == -1) {
119                 perror("kvm_setproc");
120                 exit(2);
121         }
123         /* Display column headings */
124         printf("%c %5s %5s %5s %6s %6s %4s %s %s\n",
125                 'S',
126                 "UID",
127                 "PID",
128                 "PPID",
129                 "VSZ",
130                 "RSS",
131                 "%CPU",
132                 "COMMAND",
133                 "ARGS"
134         );
136         /* Zip through all of the process entries */
137         while((proc = kvm_nextproc(kd)) != 0) {
138                 HandleProc(proc);
139         }
141         /* Close the handle to the running kernel image */
142         kvm_close(kd);
144         return retcode;
147 /*----------------------------------------------------------------------------*/
149 static void HandleProc(struct proc *proc)
151         struct pid pid;
152         struct user *user;
153         char **proc_argv = NULL;
155         if(kvm_kread(kd, (unsigned long) proc->p_pidp, (char *) &pid, sizeof pid) == -1) {
156                 perror("kvm_read error");
157                 exit(2);
158         }
159         proc->p_pidp = &pid;
160         user = kvm_getu(kd, proc);
162         if(kvm_getcmd(kd, proc, user, &proc_argv, NULL) == -1) {
163                 return;
164         }
166         if(proc_argv == NULL) {
167                 return;
168         }
170         output_info(proc, proc_argv);
171         free(proc_argv);
174 static void output_info(struct proc *proc_kvm, char **proc_argv)
176         char procpath[MAX_PATH];
177         psinfo_t procinfo;
178         int fd, len;
179         char *procname;
180         int i;
182         sprintf(procpath, "/proc/%d/psinfo", proc_kvm->p_pidp->pid_id);
184         if ((fd = open(procpath, O_RDONLY)) >= 0)
185         {
186                 if ((len = read(fd, &procinfo, sizeof(procinfo))) != sizeof(procinfo))
187                 {
188                         fprintf(stderr,"%s: Read error of psinfo structure (%d)\n", procpath, len);
189                         exit(2);
190                 }
191                 close(fd);
192         }
194         if((procname = strrchr(proc_argv[0], '/')) != NULL)
195                 procname++;
196         else
197                 procname = proc_argv[0];
199         printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ",
200                 procinfo.pr_lwp.pr_sname,
201                 (int)(procinfo.pr_euid),
202                 (int)proc_kvm->p_pidp->pid_id,
203                 (int)proc_kvm->p_ppid,
204                 (unsigned long)(procinfo.pr_size),
205                 (unsigned long)(procinfo.pr_rssize),
206                 ((float)(procinfo.pr_pctcpu) / 0x8000 * 100.0),
207                 procname
208         );
210         for(i=0;proc_argv[i];i++) {
211                 printf(" %s", proc_argv[i]);
212         }
214         printf("\n");