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 | } |
