1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1914 casper * Common Development and Distribution License (the "License"). 6 1914 casper * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 9123 john * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 9966 Menno * 25 9966 Menno * Portions Copyright 2009 Chad Mynhier 26 0 stevel */ 27 0 stevel 28 0 stevel #include <sys/types.h> 29 0 stevel #include <sys/param.h> 30 0 stevel #include <sys/resource.h> 31 0 stevel #include <sys/priocntl.h> 32 0 stevel #include <sys/rtpriocntl.h> 33 0 stevel #include <sys/tspriocntl.h> 34 0 stevel #include <zone.h> 35 0 stevel 36 0 stevel #include <libintl.h> 37 0 stevel #include <limits.h> 38 0 stevel #include <wchar.h> 39 0 stevel #include <unistd.h> 40 0 stevel #include <string.h> 41 0 stevel #include <stdlib.h> 42 0 stevel #include <stdarg.h> 43 0 stevel #include <stdio.h> 44 1914 casper #include <stdio_ext.h> 45 0 stevel #include <errno.h> 46 0 stevel #include <ctype.h> 47 0 stevel #include <poll.h> 48 0 stevel #include <project.h> 49 0 stevel 50 0 stevel #include "prfile.h" 51 0 stevel #include "prstat.h" 52 0 stevel #include "prutil.h" 53 0 stevel 54 0 stevel static char PRG_FMT[] = "%s: "; 55 0 stevel static char ERR_FMT[] = ": %s\n"; 56 0 stevel static char *progname; 57 0 stevel static char projbuf[PROJECT_BUFSZ]; 58 0 stevel 59 0 stevel #define RLIMIT_NOFILE_MAX 32767 60 0 stevel 61 0 stevel /*PRINTFLIKE1*/ 62 0 stevel void 63 0 stevel Warn(char *format, ...) 64 0 stevel { 65 0 stevel int err = errno; 66 0 stevel va_list alist; 67 0 stevel 68 0 stevel if (progname != NULL) 69 0 stevel (void) fprintf(stderr, PRG_FMT, progname); 70 0 stevel va_start(alist, format); 71 0 stevel (void) vfprintf(stderr, format, alist); 72 0 stevel va_end(alist); 73 0 stevel if (strchr(format, '\n') == NULL) 74 0 stevel (void) fprintf(stderr, gettext(ERR_FMT), strerror(err)); 75 0 stevel } 76 0 stevel 77 0 stevel /*PRINTFLIKE1*/ 78 0 stevel void 79 0 stevel Die(char *format, ...) 80 0 stevel { 81 0 stevel int err = errno; 82 0 stevel va_list alist; 83 0 stevel 84 0 stevel if (progname != NULL) 85 0 stevel (void) fprintf(stderr, PRG_FMT, progname); 86 0 stevel va_start(alist, format); 87 0 stevel (void) vfprintf(stderr, format, alist); 88 0 stevel va_end(alist); 89 0 stevel if (strchr(format, '\n') == NULL) 90 0 stevel (void) fprintf(stderr, gettext(ERR_FMT), strerror(err)); 91 0 stevel exit(1); 92 0 stevel } 93 0 stevel 94 0 stevel void 95 0 stevel Progname(char *arg0) 96 0 stevel { 97 0 stevel char *p = strrchr(arg0, '/'); 98 0 stevel if (p == NULL) 99 0 stevel p = arg0; 100 0 stevel else 101 0 stevel p++; 102 0 stevel progname = p; 103 0 stevel } 104 0 stevel 105 0 stevel void 106 0 stevel Usage() 107 0 stevel { 108 0 stevel (void) fprintf(stderr, gettext( 109 9966 Menno "Usage:\tprstat [-acHJLmrRtTvZ] [-u euidlist] [-U uidlist]\n" 110 2685 akolb "\t[-p pidlist] [-P cpulist] [-C psrsetlist] [-h lgrouplist]\n" 111 0 stevel "\t[-j projidlist] [-k taskidlist] [-z zoneidlist]\n" 112 9123 john "\t[-s key | -S key] [-n nprocs[,nusers]] [-d d|u]\n" 113 0 stevel "\t[interval [counter]]\n")); 114 0 stevel exit(1); 115 0 stevel } 116 0 stevel 117 0 stevel int 118 0 stevel Atoi(char *p) 119 0 stevel { 120 0 stevel int i; 121 0 stevel char *q; 122 0 stevel errno = 0; 123 0 stevel i = (int)strtol(p, &q, 10); 124 0 stevel if (errno != 0 || q == p || i < 0 || *q != '\0') 125 0 stevel Die(gettext("illegal argument -- %s\n"), p); 126 0 stevel /*NOTREACHED*/ 127 0 stevel else 128 0 stevel return (i); 129 0 stevel return (0); /* keep gcc happy */ 130 0 stevel } 131 0 stevel 132 0 stevel void 133 0 stevel Format_size(char *str, size_t size, int length) 134 0 stevel { 135 0 stevel char tag = 'K'; 136 0 stevel if (size >= 10000) { 137 0 stevel size = (size + 512) / 1024; 138 0 stevel tag = 'M'; 139 0 stevel if (size >= 10000) { 140 0 stevel size = (size + 512) / 1024; 141 0 stevel tag = 'G'; 142 0 stevel } 143 0 stevel } 144 0 stevel (void) snprintf(str, length, "%4d%c", (int)size, tag); 145 0 stevel } 146 0 stevel 147 0 stevel void 148 0 stevel Format_time(char *str, ulong_t time, int length) 149 0 stevel { 150 0 stevel (void) snprintf(str, length, gettext("%3d:%2.2d:%2.2d"), /* hr:mm:ss */ 151 0 stevel (int)time/3600, (int)(time % 3600)/60, (int)time % 60); 152 0 stevel } 153 0 stevel 154 0 stevel void 155 0 stevel Format_pct(char *str, float val, int length) 156 0 stevel { 157 0 stevel if (val > (float)100) 158 0 stevel val = 100; 159 0 stevel if (val < 0) 160 0 stevel val = 0; 161 0 stevel 162 0 stevel if (val < (float)9.95) 163 0 stevel (void) snprintf(str, length, "%1.1f", val); 164 0 stevel else 165 0 stevel (void) snprintf(str, length, "%.0f", val); 166 0 stevel } 167 0 stevel 168 0 stevel void 169 0 stevel Format_num(char *str, int num, int length) 170 0 stevel { 171 0 stevel if (num >= 100000) { 172 0 stevel (void) snprintf(str, length, ".%1dM", num/100000); 173 0 stevel } else { 174 0 stevel if (num >= 1000) 175 0 stevel (void) snprintf(str, length, "%2dK", num/1000); 176 0 stevel else 177 0 stevel (void) snprintf(str, length, "%3d", num); 178 0 stevel } 179 0 stevel } 180 0 stevel 181 0 stevel void 182 0 stevel Format_state(char *str, char state, processorid_t pr_id, int length) 183 0 stevel { 184 0 stevel switch (state) { 185 0 stevel case 'S': 186 0 stevel (void) strncpy(str, "sleep", length); 187 0 stevel break; 188 0 stevel case 'R': 189 0 stevel (void) strncpy(str, "run", length); 190 0 stevel break; 191 0 stevel case 'Z': 192 0 stevel (void) strncpy(str, "zombie", length); 193 0 stevel break; 194 0 stevel case 'T': 195 0 stevel (void) strncpy(str, "stop", length); 196 0 stevel break; 197 0 stevel case 'I': 198 0 stevel (void) strncpy(str, "idle", length); 199 0 stevel break; 200 3792 akolb case 'W': 201 3792 akolb (void) strncpy(str, "wait", length); 202 0 stevel break; 203 0 stevel case 'O': 204 0 stevel (void) snprintf(str, length, "cpu%-3d", (int)pr_id); 205 0 stevel break; 206 0 stevel default: 207 0 stevel (void) strncpy(str, "?", length); 208 0 stevel break; 209 0 stevel } 210 0 stevel } 211 0 stevel 212 0 stevel void * 213 0 stevel Realloc(void *ptr, size_t size) 214 0 stevel { 215 0 stevel int cnt = 0; 216 0 stevel void *sav = ptr; 217 0 stevel 218 0 stevel eagain: if ((ptr = realloc(ptr, size))) 219 0 stevel return (ptr); 220 0 stevel 221 0 stevel if ((++cnt <= 3) && (errno == EAGAIN)) { 222 0 stevel Warn(gettext("realloc() failed, attempt %d"), cnt); 223 0 stevel (void) poll(NULL, 0, 5000); /* wait for 5 seconds */ 224 0 stevel ptr = sav; 225 0 stevel goto eagain; 226 0 stevel } 227 0 stevel ptr = sav; 228 0 stevel Die(gettext("not enough memory")); 229 0 stevel /*NOTREACHED*/ 230 0 stevel return (NULL); /* keep gcc happy */ 231 0 stevel } 232 0 stevel 233 0 stevel void * 234 0 stevel Malloc(size_t size) 235 0 stevel { 236 0 stevel return (Realloc(NULL, size)); 237 0 stevel } 238 0 stevel 239 0 stevel void * 240 0 stevel Zalloc(size_t size) 241 0 stevel { 242 0 stevel return (memset(Realloc(NULL, size), 0, size)); 243 0 stevel } 244 0 stevel 245 0 stevel int 246 0 stevel Setrlimit() 247 0 stevel { 248 0 stevel struct rlimit rlim; 249 0 stevel int fd_limit; 250 0 stevel if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) 251 0 stevel Die(gettext("getrlimit failed")); 252 0 stevel fd_limit = rlim.rlim_cur; 253 0 stevel rlim.rlim_max = MIN(rlim.rlim_max, RLIMIT_NOFILE_MAX); 254 0 stevel rlim.rlim_cur = rlim.rlim_max; 255 1914 casper (void) enable_extended_FILE_stdio(-1, -1); 256 0 stevel if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) 257 0 stevel return (fd_limit); 258 0 stevel else 259 0 stevel return (rlim.rlim_cur); 260 0 stevel } 261 0 stevel 262 0 stevel void 263 0 stevel Priocntl(char *class) 264 0 stevel { 265 0 stevel pcinfo_t pcinfo; 266 0 stevel pcparms_t pcparms; 267 0 stevel (void) strcpy(pcinfo.pc_clname, class); 268 0 stevel if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1) { 269 0 stevel Warn(gettext("cannot get real time class parameters")); 270 0 stevel return; 271 0 stevel } 272 0 stevel pcparms.pc_cid = pcinfo.pc_cid; 273 0 stevel ((rtparms_t *)pcparms.pc_clparms)->rt_pri = 0; 274 0 stevel ((rtparms_t *)pcparms.pc_clparms)->rt_tqsecs = 0; 275 0 stevel ((rtparms_t *)pcparms.pc_clparms)->rt_tqnsecs = RT_NOCHANGE; 276 0 stevel if (priocntl(P_PID, getpid(), PC_SETPARMS, (caddr_t)&pcparms) == -1) 277 0 stevel Warn(gettext("cannot enter the real time class")); 278 0 stevel } 279 0 stevel 280 0 stevel void 281 9966 Menno getprojname(projid_t projid, char *str, int len, int noresolve) 282 0 stevel { 283 0 stevel struct project proj; 284 0 stevel 285 9966 Menno if (noresolve || getprojbyid(projid, &proj, projbuf, PROJECT_BUFSZ) == 286 9966 Menno NULL) 287 9966 Menno (void) snprintf(str, len, "%-6d", (int)projid); 288 9966 Menno else 289 0 stevel (void) snprintf(str, len, "%-28s", proj.pj_name); 290 0 stevel } 291 0 stevel 292 0 stevel void 293 0 stevel getzonename(zoneid_t zoneid, char *str, int len) 294 0 stevel { 295 0 stevel char zone_name[ZONENAME_MAX]; 296 0 stevel 297 0 stevel if (getzonenamebyid(zoneid, zone_name, sizeof (zone_name)) < 0) 298 0 stevel (void) snprintf(str, len, "%-6d", (int)zoneid); 299 0 stevel else 300 0 stevel (void) snprintf(str, len, "%-28s", zone_name); 301 0 stevel } 302 0 stevel 303 0 stevel /* 304 0 stevel * Remove all unprintable characters from process name 305 0 stevel */ 306 0 stevel void 307 0 stevel stripfname(char *buf) 308 0 stevel { 309 0 stevel int bytesleft = PRFNSZ; 310 0 stevel wchar_t wchar; 311 0 stevel int length; 312 0 stevel char *cp; 313 0 stevel 314 0 stevel buf[bytesleft - 1] = '\0'; 315 0 stevel 316 0 stevel for (cp = buf; *cp != '\0'; cp += length) { 317 0 stevel length = mbtowc(&wchar, cp, MB_LEN_MAX); 318 0 stevel if (length <= 0) { 319 0 stevel *cp = '\0'; 320 0 stevel break; 321 0 stevel } 322 0 stevel if (!iswprint(wchar)) { 323 0 stevel if (bytesleft <= length) { 324 0 stevel *cp = '\0'; 325 0 stevel break; 326 0 stevel } 327 0 stevel (void) memmove(cp, cp + length, bytesleft - length); 328 0 stevel length = 0; 329 0 stevel } 330 0 stevel bytesleft -= length; 331 0 stevel } 332 0 stevel } 333