diff options
Diffstat (limited to 'plugins-root')
| -rw-r--r-- | plugins-root/Makefile.am | 1 | ||||
| -rw-r--r-- | plugins-root/pst3.c | 354 |
2 files changed, 197 insertions, 158 deletions
diff --git a/plugins-root/Makefile.am b/plugins-root/Makefile.am index bca3ceb5..107d9933 100644 --- a/plugins-root/Makefile.am +++ b/plugins-root/Makefile.am | |||
| @@ -71,7 +71,6 @@ check_icmp_LDADD = @LTLIBINTL@ $(NETLIBS) $(SOCKETLIBS) | |||
| 71 | # -m64 needed at compiler and linker phase | 71 | # -m64 needed at compiler and linker phase |
| 72 | pst3_CFLAGS = @PST3CFLAGS@ | 72 | pst3_CFLAGS = @PST3CFLAGS@ |
| 73 | pst3_LDFLAGS = @PST3CFLAGS@ | 73 | pst3_LDFLAGS = @PST3CFLAGS@ |
| 74 | pst3_LDADD = -lkvm | ||
| 75 | 74 | ||
| 76 | check_dhcp_DEPENDENCIES = check_dhcp.c $(NETOBJS) $(DEPLIBS) | 75 | check_dhcp_DEPENDENCIES = check_dhcp.c $(NETOBJS) $(DEPLIBS) |
| 77 | check_icmp_DEPENDENCIES = check_icmp.c $(NETOBJS) | 76 | check_icmp_DEPENDENCIES = check_icmp.c $(NETOBJS) |
diff --git a/plugins-root/pst3.c b/plugins-root/pst3.c index 641a9b86..3954ec5f 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 | ||
| 73 | static char * szProg; | 64 | static char * szProg; |
| 74 | static kvm_t * kd; | ||
| 75 | static struct proc * pProc; | ||
| 76 | static struct user * pUser; | ||
| 77 | static char ** myArgv; | ||
| 78 | |||
| 79 | 65 | ||
| 80 | /* | 66 | /* |
| 81 | * Prototypes | 67 | * Prototypes |
| 82 | */ | 68 | */ |
| 83 | 69 | void usage(); | |
| 84 | static void output_info(struct proc *proc_kvm,char **proc_argv); | ||
| 85 | static void HandleProc(struct proc *proc); | ||
| 86 | 70 | ||
| 87 | /*----------------------------------------------------------------------------*/ | 71 | /*----------------------------------------------------------------------------*/ |
| 88 | 72 | ||
| 89 | int main (int argc, char **argv) | 73 | int 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"); | ||
| 137 | try_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 | ||
| 149 | static void HandleProc(struct proc *proc) | 239 | void 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 | |||
| 174 | static 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 | |||
