diff options
Diffstat (limited to 'plugins-root/pst3.c')
-rw-r--r-- | plugins-root/pst3.c | 441 |
1 files changed, 214 insertions, 227 deletions
diff --git a/plugins-root/pst3.c b/plugins-root/pst3.c index 1f69f3a6..1bfe3d35 100644 --- a/plugins-root/pst3.c +++ b/plugins-root/pst3.c | |||
@@ -1,45 +1,45 @@ | |||
1 | /***************************************************************************** | 1 | /***************************************************************************** |
2 | * | 2 | * |
3 | * pst3 | 3 | * pst3 |
4 | * | 4 | * |
5 | * License: GPL | 5 | * License: GPL |
6 | * Copyright (c) 2008 Monitoring Plugins Development Team | 6 | * Copyright (c) 2008 Monitoring Plugins Development Team |
7 | * | 7 | * |
8 | * Description: | 8 | * Description: |
9 | * | 9 | * |
10 | * This file contains the pst3 executable. This is a replacement ps command | 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 | 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 | 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. | 13 | * also has issues where some fields run into each other. |
14 | * | 14 | * |
15 | * This executable works by reading process address structures, so needs | 15 | * This executable works by reading process address structures, so needs |
16 | * to be executed as root | 16 | * to be executed as root |
17 | * | 17 | * |
18 | * Originally written by R.W.Ingraham | 18 | * Originally written by R.W.Ingraham |
19 | * Rewritten by Duncan Ferguson (Altinity Ltd, June 2008) | 19 | * Rewritten by Duncan Ferguson (Altinity Ltd, June 2008) |
20 | * The rewrite was necessary as /dev/kmem is not available within | 20 | * The rewrite was necessary as /dev/kmem is not available within |
21 | * non-global zones on Solaris 10 | 21 | * non-global zones on Solaris 10 |
22 | * | 22 | * |
23 | * Details for rewrite came from | 23 | * Details for rewrite came from |
24 | * source of /usr/ucb/ps on Solaris: | 24 | * source of /usr/ucb/ps on Solaris: |
25 | * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/ucbcmd/ps/ps.c#argvoff | 25 | * http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/ucbcmd/ps/ps.c#argvoff |
26 | * usenet group posting | 26 | * usenet group posting |
27 | * http://groups.google.com/group/comp.unix.solaris/tree/browse_frm/month/2001-09/bfa40c08bac819a2?rnum=141&_done=%2Fgroup%2Fcomp.unix.solaris%2Fbrowse_frm%2Fmonth%2F2001-09%3F | 27 | * http://groups.google.com/group/comp.unix.solaris/tree/browse_frm/month/2001-09/bfa40c08bac819a2?rnum=141&_done=%2Fgroup%2Fcomp.unix.solaris%2Fbrowse_frm%2Fmonth%2F2001-09%3F |
28 | * | 28 | * |
29 | * This program is free software: you can redistribute it and/or modify | 29 | * This program is free software: you can redistribute it and/or modify |
30 | * it under the terms of the GNU General Public License as published by | 30 | * it under the terms of the GNU General Public License as published by |
31 | * the Free Software Foundation, either version 3 of the License, or | 31 | * the Free Software Foundation, either version 3 of the License, or |
32 | * (at your option) any later version. | 32 | * (at your option) any later version. |
33 | * | 33 | * |
34 | * This program is distributed in the hope that it will be useful, | 34 | * This program is distributed in the hope that it will be useful, |
35 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 35 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
36 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 36 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
37 | * GNU General Public License for more details. | 37 | * GNU General Public License for more details. |
38 | * | 38 | * |
39 | * You should have received a copy of the GNU General Public License | 39 | * You should have received a copy of the GNU General Public License |
40 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 40 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
41 | * | 41 | * |
42 | *****************************************************************************/ | 42 | *****************************************************************************/ |
43 | 43 | ||
44 | #include <stdio.h> | 44 | #include <stdio.h> |
45 | #include <stdlib.h> | 45 | #include <stdlib.h> |
@@ -55,14 +55,14 @@ | |||
55 | * Constants | 55 | * Constants |
56 | */ | 56 | */ |
57 | 57 | ||
58 | #define PROC_DIR "/proc" | 58 | #define PROC_DIR "/proc" |
59 | #define ARGS 30 | 59 | #define ARGS 30 |
60 | 60 | ||
61 | /* | 61 | /* |
62 | * Globals | 62 | * Globals |
63 | */ | 63 | */ |
64 | 64 | ||
65 | static char * szProg; | 65 | static char *szProg; |
66 | 66 | ||
67 | /* | 67 | /* |
68 | * Prototypes | 68 | * Prototypes |
@@ -71,192 +71,179 @@ void usage(); | |||
71 | 71 | ||
72 | /*----------------------------------------------------------------------------*/ | 72 | /*----------------------------------------------------------------------------*/ |
73 | 73 | ||
74 | int main (int argc, char **argv) | 74 | int main(int argc, char **argv) { |
75 | { | 75 | DIR *procdir; |
76 | DIR *procdir; | 76 | struct dirent *proc; |
77 | struct dirent *proc; | 77 | char ps_name[ARGS]; |
78 | char ps_name[ARGS]; | 78 | char as_name[ARGS]; |
79 | char as_name[ARGS]; | 79 | psinfo_t psinfo; |
80 | psinfo_t psinfo; | 80 | |
81 | 81 | /* Set our program name global */ | |
82 | /* Set our program name global */ | 82 | if ((szProg = strrchr(argv[0], '/')) != NULL) { |
83 | if ((szProg = strrchr(argv[0], '/')) != NULL) | 83 | szProg++; |
84 | szProg++; | 84 | } else { |
85 | else | 85 | szProg = argv[0]; |
86 | szProg = argv[0]; | 86 | } |
87 | 87 | ||
88 | /* if given any parameters, print out help */ | 88 | /* if given any parameters, print out help */ |
89 | if(argc > 1) { | 89 | if (argc > 1) { |
90 | (void)usage(); | 90 | (void)usage(); |
91 | exit(1); | 91 | exit(1); |
92 | } | 92 | } |
93 | 93 | ||
94 | /* Make sure that our euid is root */ | 94 | /* Make sure that our euid is root */ |
95 | if (geteuid() != 0) | 95 | if (geteuid() != 0) { |
96 | { | 96 | fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg); |
97 | fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg); | 97 | exit(1); |
98 | exit(1); | 98 | } |
99 | } | 99 | |
100 | 100 | if ((procdir = opendir(PROC_DIR)) == NULL) { | |
101 | if ((procdir = opendir(PROC_DIR)) == NULL) { | 101 | fprintf(stderr, "%s: cannot open PROC directory %s\n", szProg, PROC_DIR); |
102 | fprintf(stderr, "%s: cannot open PROC directory %s\n", szProg, PROC_DIR); | 102 | exit(1); |
103 | exit(1); | 103 | } |
104 | } | 104 | |
105 | 105 | /* Display column headings */ | |
106 | /* Display column headings */ | 106 | printf("%c %5s %5s %5s %6s %6s %4s %s %s\n", 'S', "UID", "PID", "PPID", "VSZ", "RSS", "%CPU", |
107 | printf("%c %5s %5s %5s %6s %6s %4s %s %s\n", | 107 | "COMMAND", "ARGS"); |
108 | 'S', | 108 | |
109 | "UID", | 109 | /* Zip through all of the process entries */ |
110 | "PID", | 110 | while ((proc = readdir(procdir))) { |
111 | "PPID", | 111 | int ps_fd; |
112 | "VSZ", | 112 | int as_fd; |
113 | "RSS", | 113 | off_t argoff; |
114 | "%CPU", | 114 | int i; |
115 | "COMMAND", | 115 | char *args; |
116 | "ARGS" | 116 | char *procname; |
117 | ); | 117 | char *ptr; |
118 | 118 | int argslen; | |
119 | /* Zip through all of the process entries */ | 119 | uintptr_t args_addr; |
120 | while((proc = readdir(procdir))) { | 120 | ; |
121 | int ps_fd; | 121 | uintptr_t *args_vecs; |
122 | int as_fd; | 122 | ; |
123 | off_t argoff; | 123 | int args_count; |
124 | int i; | 124 | |
125 | char *args; | 125 | if (proc->d_name[0] == '.') { |
126 | char *procname; | 126 | continue; |
127 | char *ptr; | 127 | } |
128 | int argslen; | 128 | |
129 | uintptr_t args_addr;; | 129 | sprintf(ps_name, "%s/%s/%s", PROC_DIR, proc->d_name, "psinfo"); |
130 | uintptr_t *args_vecs;; | 130 | sprintf(as_name, "%s/%s/%s", PROC_DIR, proc->d_name, "as"); |
131 | int args_count; | 131 | try_again: |
132 | 132 | if ((ps_fd = open(ps_name, O_RDONLY)) == -1) { | |
133 | if(proc->d_name[0] == '.') | 133 | continue; |
134 | continue; | 134 | } |
135 | 135 | ||
136 | sprintf(ps_name,"%s/%s/%s",PROC_DIR,proc->d_name,"psinfo"); | 136 | if ((as_fd = open(as_name, O_RDONLY)) == -1) { |
137 | sprintf(as_name,"%s/%s/%s",PROC_DIR,proc->d_name,"as"); | 137 | close(ps_fd); |
138 | try_again: | 138 | continue; |
139 | if((ps_fd = open(ps_name, O_RDONLY)) == -1) | 139 | } |
140 | continue; | 140 | |
141 | 141 | if (read(ps_fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) { | |
142 | if((as_fd = open(as_name, O_RDONLY)) == -1) { | 142 | int err = errno; |
143 | close(ps_fd); | 143 | close(ps_fd); |
144 | continue; | 144 | close(as_fd); |
145 | } | 145 | if (err == EAGAIN) { |
146 | 146 | goto try_again; | |
147 | if(read(ps_fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) { | 147 | } |
148 | int err = errno; | 148 | if (err != ENOENT) { |
149 | close(ps_fd); | 149 | fprintf(stderr, "%s: read() on %s: %s\n", szProg, ps_name, strerror(err)); |
150 | close(as_fd); | 150 | } |
151 | if(err == EAGAIN) goto try_again; | 151 | continue; |
152 | if(err != ENOENT) | 152 | } |
153 | fprintf(stderr, "%s: read() on %s: %s\n", szProg, | 153 | close(ps_fd); |
154 | ps_name, strerror(err)); | 154 | |
155 | continue; | 155 | /* system process, ignore since the previous version did */ |
156 | } | 156 | if (psinfo.pr_nlwp == 0 || strcmp(psinfo.pr_lwp.pr_clname, "SYS") == 0) { |
157 | close(ps_fd); | 157 | continue; |
158 | 158 | } | |
159 | /* system process, ignore since the previous version did */ | 159 | |
160 | if( | 160 | /* get the procname to match previous versions */ |
161 | psinfo.pr_nlwp == 0 || | 161 | procname = strdup(psinfo.pr_psargs); |
162 | strcmp(psinfo.pr_lwp.pr_clname, "SYS") == 0 | 162 | if ((ptr = strchr(procname, ' ')) != NULL) { |
163 | ) { | 163 | *ptr = '\0'; |
164 | continue; | 164 | } |
165 | } | 165 | if ((ptr = strrchr(procname, '/')) != NULL) { |
166 | 166 | ptr++; | |
167 | /* get the procname to match previous versions */ | 167 | } else { |
168 | procname = strdup(psinfo.pr_psargs); | 168 | ptr = procname; |
169 | if((ptr = strchr(procname, ' ')) != NULL) | 169 | } |
170 | *ptr = '\0'; | 170 | |
171 | if((ptr = strrchr(procname, '/')) != NULL) | 171 | /* |
172 | ptr++; | 172 | * print out what we currently know |
173 | else | 173 | */ |
174 | ptr = procname; | 174 | printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ", psinfo.pr_lwp.pr_sname, psinfo.pr_euid, |
175 | 175 | psinfo.pr_pid, psinfo.pr_ppid, psinfo.pr_size, psinfo.pr_rssize, | |
176 | /* | 176 | ((float)(psinfo.pr_pctcpu) / 0x8000 * 100.0), ptr); |
177 | * print out what we currently know | 177 | free(procname); |
178 | */ | 178 | |
179 | printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ", | 179 | /* |
180 | psinfo.pr_lwp.pr_sname, | 180 | * and now for the command line stuff |
181 | psinfo.pr_euid, | 181 | */ |
182 | psinfo.pr_pid, | 182 | |
183 | psinfo.pr_ppid, | 183 | args_addr = psinfo.pr_argv; |
184 | psinfo.pr_size, | 184 | args_count = psinfo.pr_argc; |
185 | psinfo.pr_rssize, | 185 | args_vecs = malloc(args_count * sizeof(uintptr_t)); |
186 | ((float)(psinfo.pr_pctcpu) / 0x8000 * 100.0), | 186 | |
187 | ptr | 187 | if (psinfo.pr_dmodel == PR_MODEL_NATIVE) { |
188 | ); | 188 | /* this process matches target process */ |
189 | free(procname); | 189 | pread(as_fd, args_vecs, args_count * sizeof(uintptr_t), args_addr); |
190 | 190 | } else { | |
191 | /* | 191 | /* this process is 64bit, target process is 32 bit*/ |
192 | * and now for the command line stuff | 192 | caddr32_t *args_vecs32 = (caddr32_t *)args_vecs; |
193 | */ | 193 | pread(as_fd, args_vecs32, args_count * sizeof(caddr32_t), args_addr); |
194 | 194 | for (i = args_count - 1; i >= 0; --i) { | |
195 | args_addr = psinfo.pr_argv; | 195 | args_vecs[i] = args_vecs32[i]; |
196 | args_count = psinfo.pr_argc; | 196 | } |
197 | args_vecs = malloc(args_count * sizeof(uintptr_t)); | 197 | } |
198 | 198 | ||
199 | if(psinfo.pr_dmodel == PR_MODEL_NATIVE) { | 199 | /* |
200 | /* this process matches target process */ | 200 | * now read in the args - if what we read in fills buffer |
201 | pread(as_fd,args_vecs, args_count * sizeof(uintptr_t), | 201 | * resize buffer and reread that bit again |
202 | args_addr); | 202 | */ |
203 | } else { | 203 | argslen = ARGS; |
204 | /* this process is 64bit, target process is 32 bit*/ | 204 | args = malloc(argslen + 1); |
205 | caddr32_t *args_vecs32 = (caddr32_t *)args_vecs; | 205 | for (i = 0; i < args_count; i++) { |
206 | pread(as_fd,args_vecs32,args_count * sizeof(caddr32_t), | 206 | memset(args, '\0', argslen + 1); |
207 | args_addr); | 207 | if (pread(as_fd, args, argslen, args_vecs[i]) <= 0) { |
208 | for (i=args_count-1;i>=0;--i) | 208 | break; |
209 | args_vecs[i]=args_vecs32[i]; | 209 | } |
210 | } | 210 | args[argslen] = '\0'; |
211 | 211 | if (strlen(args) == argslen) { | |
212 | /* | 212 | argslen += ARGS; |
213 | * now read in the args - if what we read in fills buffer | 213 | args = realloc(args, argslen + 1); |
214 | * resize buffer and reread that bit again | 214 | i--; |
215 | */ | 215 | continue; |
216 | argslen=ARGS; | 216 | } |
217 | args=malloc(argslen+1); | 217 | printf(" %s", args); |
218 | for(i=0;i<args_count;i++) { | 218 | } |
219 | memset(args,'\0',argslen+1); | 219 | free(args_vecs); |
220 | if(pread(as_fd, args, argslen, args_vecs[i]) <= 0) { | 220 | free(args); |
221 | break; | 221 | close(as_fd); |
222 | } | 222 | printf("\n"); |
223 | args[argslen]='\0'; | 223 | } |
224 | if(strlen(args) == argslen){ | 224 | |
225 | argslen += ARGS; | 225 | (void)closedir(procdir); |
226 | args = realloc(args, argslen + 1); | 226 | |
227 | i--; | 227 | return (0); |
228 | continue; | ||
229 | } | ||
230 | printf(" %s", args); | ||
231 | } | ||
232 | free(args_vecs); | ||
233 | free(args); | ||
234 | close(as_fd); | ||
235 | printf("\n"); | ||
236 | } | ||
237 | |||
238 | (void) closedir(procdir); | ||
239 | |||
240 | return (0); | ||
241 | } | 228 | } |
242 | 229 | ||
243 | /*----------------------------------------------------------------------------*/ | 230 | /*----------------------------------------------------------------------------*/ |
244 | 231 | ||
245 | void usage() { | 232 | void usage() { |
246 | printf("%s: Help output\n\n", szProg); | 233 | printf("%s: Help output\n\n", szProg); |
247 | printf("If this program is given any arguments, this help is displayed.\n"); | 234 | printf("If this program is given any arguments, this help is displayed.\n"); |
248 | printf("This command is used to print out the full command line for all\n"); | 235 | printf("This command is used to print out the full command line for all\n"); |
249 | printf("running processes because /usr/bin/ps is limited to 80 chars and\n"); | 236 | printf("running processes because /usr/bin/ps is limited to 80 chars and\n"); |
250 | printf("/usr/ucb/ps can merge columns together.\n\n"); | 237 | printf("/usr/ucb/ps can merge columns together.\n\n"); |
251 | printf("Columns are:\n"); | 238 | printf("Columns are:\n"); |
252 | printf("\tS - State of process - see 'ps' man page\n"); | 239 | printf("\tS - State of process - see 'ps' man page\n"); |
253 | printf("\tUID - UID of the process owner\n"); | 240 | printf("\tUID - UID of the process owner\n"); |
254 | printf("\tPID - PID of the process\n"); | 241 | printf("\tPID - PID of the process\n"); |
255 | printf("\tPPID - PID of the parent process\n"); | 242 | printf("\tPPID - PID of the parent process\n"); |
256 | printf("\tVSZ - Virtual memory usage (kilobytes)\n"); | 243 | printf("\tVSZ - Virtual memory usage (kilobytes)\n"); |
257 | printf("\tRSS - Real memory usage (kilobytes)\n"); | 244 | printf("\tRSS - Real memory usage (kilobytes)\n"); |
258 | printf("\t%%CPU - CPU usage\n"); | 245 | printf("\t%%CPU - CPU usage\n"); |
259 | printf("\tCOMMAND - Command being run\n"); | 246 | printf("\tCOMMAND - Command being run\n"); |
260 | printf("\tARGS - Full command line with arguments\n"); | 247 | printf("\tARGS - Full command line with arguments\n"); |
261 | return; | 248 | return; |
262 | } | 249 | } |