summaryrefslogtreecommitdiffstats
path: root/plugins-root/pst3.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins-root/pst3.c')
-rw-r--r--plugins-root/pst3.c354
1 files changed, 197 insertions, 157 deletions
diff --git a/plugins-root/pst3.c b/plugins-root/pst3.c
index 641a9b8..3954ec5 100644
--- a/plugins-root/pst3.c
+++ b/plugins-root/pst3.c
@@ -12,10 +12,19 @@
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 the kernel memory 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)
20* The rewrite was necessary as /dev/kmem is not available within
21* non-global zones on Solaris 10
22*
23* Details for rewrite came from
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
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
19* 28*
20* 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
21* 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
@@ -32,185 +41,216 @@
32* 41*
33*****************************************************************************/ 42*****************************************************************************/
34 43
35#define _KMEMUSER 1
36
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> 44#include <stdio.h>
45#include <stdlib.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> 46#include <dirent.h>
51#include <errno.h> 47#include <errno.h>
52 48#include <fcntl.h>
53 49#include <procfs.h>
54/* 50#include <errno.h>
55 * Constants 51#include <sys/types32.h>
56 */
57
58#define PROC_DIR "/proc"
59#define MAX_PATH 1024
60#define OK 0
61#define FAIL NULL
62
63 52
64/* 53/*
65 * Structures 54 * Constants
66 */ 55 */
67 56
57#define PROC_DIR "/proc"
58#define ARGS 30
68 59
69/* 60/*
70 * Globals 61 * Globals
71 */ 62 */
72 63
73static char * szProg; 64static char * szProg;
74static kvm_t * kd;
75static struct proc * pProc;
76static struct user * pUser;
77static char ** myArgv;
78
79 65
80/* 66/*
81 * Prototypes 67 * Prototypes
82 */ 68 */
83 69void usage();
84static void output_info(struct proc *proc_kvm,char **proc_argv);
85static void HandleProc(struct proc *proc);
86 70
87/*----------------------------------------------------------------------------*/ 71/*----------------------------------------------------------------------------*/
88 72
89int main (int argc, char **argv) 73int main (int argc, char **argv)
90{ 74{
91 DIR *pDir; 75 DIR *procdir;
92 struct dirent *pDent; 76 struct dirent *proc;
93 int retcode = 0; 77 char ps_name[ARGS];
94 struct proc *proc; 78 char as_name[ARGS];
95 struct pid pid; 79 psinfo_t psinfo;
96 80
97 /* Set our program name global */ 81 /* Set our program name global */
98 if ((szProg = strrchr(argv[0], '/')) != NULL) 82 if ((szProg = strrchr(argv[0], '/')) != NULL)
99 szProg++; 83 szProg++;
100 else 84 else
101 szProg = argv[0]; 85 szProg = argv[0];
102 86
103 /* Make sure that our euid is root */ 87 /* if given any parameters, print out help */
104 if (geteuid() != 0) 88 if(argc > 1) {
105 { 89 (void)usage();
106 fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg); 90 exit(1);
107 exit(1); 91 }
108 } 92
109 93 /* Make sure that our euid is root */
110 /* Get a handle to the running kernel image */ 94 if (geteuid() != 0)
111 if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, argv[0])) == NULL) 95 {
112 { 96 fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg);
113 fprintf(stderr, "%s: Failed to open kernel memory: %s\n", szProg, strerror(errno)); 97 exit(1);
114 exit(2); 98 }
115 } 99
116 100 if ((procdir = opendir(PROC_DIR)) == NULL) {
117 /* reset to first proc in list */ 101 fprintf(stderr, "%s: cannot open PROC directory %s\n", szProg, PROC_DIR);
118 if(kvm_setproc(kd) == -1) { 102 exit(1);
119 perror("kvm_setproc"); 103 }
120 exit(2); 104
121 } 105 /* Display column headings */
122 106 printf("%c %5s %5s %5s %6s %6s %4s %s %s\n",
123 /* Display column headings */ 107 'S',
124 printf("%c %5s %5s %5s %6s %6s %4s %s %s\n", 108 "UID",
125 'S', 109 "PID",
126 "UID", 110 "PPID",
127 "PID", 111 "VSZ",
128 "PPID", 112 "RSS",
129 "VSZ", 113 "%CPU",
130 "RSS", 114 "COMMAND",
131 "%CPU", 115 "ARGS"
132 "COMMAND", 116 );
133 "ARGS" 117
134 ); 118 /* Zip through all of the process entries */
135 119 while((proc = readdir(procdir))) {
136 /* Zip through all of the process entries */ 120 int ps_fd;
137 while((proc = kvm_nextproc(kd)) != 0) { 121 int as_fd;
138 HandleProc(proc); 122 off_t argoff;
139 } 123 int i;
140 124 char *args;
141 /* Close the handle to the running kernel image */ 125 char *procname;
142 kvm_close(kd); 126 char *ptr;
143 127 int argslen;
144 return retcode; 128 uintptr_t args_addr;;
129 uintptr_t *args_vecs;;
130 int args_count;
131
132 if(proc->d_name[0] == '.')
133 continue;
134
135 sprintf(ps_name,"%s/%s/%s",PROC_DIR,proc->d_name,"psinfo");
136 sprintf(as_name,"%s/%s/%s",PROC_DIR,proc->d_name,"as");
137try_again:
138 if((ps_fd = open(ps_name, O_RDONLY)) == -1)
139 continue;
140
141 if((as_fd = open(as_name, O_RDONLY)) == -1)
142 continue;
143
144 if(read(ps_fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo)) {
145 int err = errno;
146 close(ps_fd);
147 close(as_fd);
148 if(err == EAGAIN) goto try_again;
149 if(err != ENOENT)
150 fprintf(stderr, "%s: read() on %s: %s\n", szProg,
151 ps_name, strerror(err));
152 continue;
153 }
154 close(ps_fd);
155
156 /* system process, ignore since the previous version did */
157 if(
158 psinfo.pr_nlwp == 0 ||
159 strcmp(psinfo.pr_lwp.pr_clname, "SYS") == 0
160 ) {
161 continue;
162 }
163
164 /* get the procname to match previous versions */
165 procname = strdup(psinfo.pr_psargs);
166 if((ptr = strchr(procname, ' ')) != NULL)
167 *ptr = '\0';
168 if((ptr = strrchr(procname, '/')) != NULL)
169 ptr++;
170 else
171 ptr = procname;
172
173 /*
174 * print out what we currently know
175 */
176 printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ",
177 psinfo.pr_lwp.pr_sname,
178 psinfo.pr_euid,
179 psinfo.pr_pid,
180 psinfo.pr_ppid,
181 psinfo.pr_size,
182 psinfo.pr_rssize,
183 ((float)(psinfo.pr_pctcpu) / 0x8000 * 100.0),
184 ptr
185 );
186 free(procname);
187
188 /*
189 * and now for the command line stuff
190 */
191
192 args_addr = psinfo.pr_argv;
193 args_count = psinfo.pr_argc;
194 args_vecs = malloc(args_count * sizeof(uintptr_t));
195
196 if(psinfo.pr_dmodel == PR_MODEL_NATIVE) {
197 /* this process matches target process */
198 pread(as_fd,args_vecs, args_count * sizeof(uintptr_t),
199 args_addr);
200 } else {
201 /* this process is 64bit, target process is 32 bit*/
202 caddr32_t *args_vecs32 = (caddr32_t *)args_vecs;
203 pread(as_fd,args_vecs32,args_count * sizeof(caddr32_t),
204 args_addr);
205 for (i=args_count-1;i>=0;--i)
206 args_vecs[i]=args_vecs32[i];
207 }
208
209 /*
210 * now read in the args - if what we read in fills buffer
211 * resize buffer and reread that bit again
212 */
213 argslen=ARGS;
214 args=malloc(argslen+1);
215 for(i=0;i<args_count;i++) {
216 memset(args,'\0',argslen+1);
217 if(pread(as_fd, args, argslen, args_vecs[i]) <= 0) {
218 break;
219 }
220 args[argslen]='\0';
221 if(strlen(args) == argslen){
222 argslen += ARGS;
223 args = realloc(args, argslen + 1);
224 i--;
225 continue;
226 }
227 printf(" %s", args);
228 }
229 free(args_vecs);
230 free(args);
231 printf("\n");
232 }
233
234 return (0);
145} 235}
146 236
147/*----------------------------------------------------------------------------*/ 237/*----------------------------------------------------------------------------*/
148 238
149static void HandleProc(struct proc *proc) 239void usage() {
150{ 240 printf("%s: Help output\n\n", szProg);
151 struct pid pid; 241 printf("If this program is given any arguments, this help is displayed.\n");
152 struct user *user; 242 printf("This command is used to print out the full command line for all\n");
153 char **proc_argv = NULL; 243 printf("running processes because /usr/bin/ps is limited to 80 chars and\n");
154 244 printf("/usr/ucb/ps can merge columns together.\n\n");
155 if(kvm_kread(kd, (unsigned long) proc->p_pidp, (char *) &pid, sizeof pid) == -1) { 245 printf("Columns are:\n");
156 perror("kvm_read error"); 246 printf("\tS - State of process - see 'ps' man page\n");
157 exit(2); 247 printf("\tUID - UID of the process owner\n");
158 } 248 printf("\tPID - PID of the process\n");
159 proc->p_pidp = &pid; 249 printf("\tPPID - PID of the parent process\n");
160 user = kvm_getu(kd, proc); 250 printf("\tVSZ - Virtual memory usage (kilobytes)\n");
161 251 printf("\tRSS - Real memory usage (kilobytes)\n");
162 if(kvm_getcmd(kd, proc, user, &proc_argv, NULL) == -1) { 252 printf("\t%%CPU - CPU usage\n");
163 return; 253 printf("\tCOMMAND - Command being run\n");
164 } 254 printf("\tARGS - Full command line with arguements\n");
165 255 return;
166 if(proc_argv == NULL) {
167 return;
168 }
169
170 output_info(proc, proc_argv);
171 free(proc_argv);
172} 256}
173
174static void output_info(struct proc *proc_kvm, char **proc_argv)
175{
176 char procpath[MAX_PATH];
177 psinfo_t procinfo;
178 int fd, len;
179 char *procname;
180 int i;
181
182 sprintf(procpath, "/proc/%d/psinfo", proc_kvm->p_pidp->pid_id);
183
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 }
193
194 if((procname = strrchr(proc_argv[0], '/')) != NULL)
195 procname++;
196 else
197 procname = proc_argv[0];
198
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 );
209
210 for(i=0;proc_argv[i];i++) {
211 printf(" %s", proc_argv[i]);
212 }
213
214 printf("\n");
215}
216