summaryrefslogtreecommitdiffstats
path: root/plugins-root/pst3.c
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-09-15 13:18:17 +0200
committerGitHub <noreply@github.com>2025-09-15 13:18:17 +0200
commit8ef825d85fb4d09c32ca44c545d6eb8d995ddea4 (patch)
tree5ab7b18797dfd5849dec7827c87ca3bb5fcb0993 /plugins-root/pst3.c
parenta3cf9041af810770daf5d9b83f1906fa9bb0dd11 (diff)
parent204cf956f0b3db90d079321ee957b3860da7e33f (diff)
downloadmonitoring-plugins-8ef825d85fb4d09c32ca44c545d6eb8d995ddea4.tar.gz
Merge pull request #2149 from RincewindsHat/clang-format
Clang format
Diffstat (limited to 'plugins-root/pst3.c')
-rw-r--r--plugins-root/pst3.c441
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
65static char * szProg; 65static char *szProg;
66 66
67/* 67/*
68 * Prototypes 68 * Prototypes
@@ -71,192 +71,179 @@ void usage();
71 71
72/*----------------------------------------------------------------------------*/ 72/*----------------------------------------------------------------------------*/
73 73
74int main (int argc, char **argv) 74int 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);
138try_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
245void usage() { 232void 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}