1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2001-2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <strings.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/mman.h> 33*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 34*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 35*7c478bd9Sstevel@tonic-gate #include <unistd.h> 36*7c478bd9Sstevel@tonic-gate #include <errno.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/auxv.h> 40*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 41*7c478bd9Sstevel@tonic-gate #include <syslog.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 44*7c478bd9Sstevel@tonic-gate #include <procfs.h> 45*7c478bd9Sstevel@tonic-gate #include <libintl.h> 46*7c478bd9Sstevel@tonic-gate #include <locale.h> 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate extern int gmatch(const char *s, const char *p); 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate #pragma init(__mpssmain) 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate static const char *mpssident = "mpss.so.1"; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate /* environment variables */ 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #define ENV_MPSSCFGFILE "MPSSCFGFILE" 57*7c478bd9Sstevel@tonic-gate #define ENV_MPSSSTACK "MPSSSTACK" 58*7c478bd9Sstevel@tonic-gate #define ENV_MPSSHEAP "MPSSHEAP" 59*7c478bd9Sstevel@tonic-gate #define ENV_MPSSERRFILE "MPSSERRFILE" 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #define MPSSHEAP 0 62*7c478bd9Sstevel@tonic-gate #define MPSSSTACK 1 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* config file */ 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #define DEF_MPSSCFGFILE "/etc/mpss.conf" 67*7c478bd9Sstevel@tonic-gate #define MAXLINELEN MAXPATHLEN + 64 68*7c478bd9Sstevel@tonic-gate #define CFGDELIMITER ':' 69*7c478bd9Sstevel@tonic-gate #define ARGDELIMITER ' ' 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate /* 72*7c478bd9Sstevel@tonic-gate * avoid malloc which causes certain applications to crash 73*7c478bd9Sstevel@tonic-gate */ 74*7c478bd9Sstevel@tonic-gate static char lbuf[MAXLINELEN]; 75*7c478bd9Sstevel@tonic-gate static char pbuf[MAXPATHLEN]; 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate #ifdef MPSSDEBUG 78*7c478bd9Sstevel@tonic-gate #define ENV_MPSSDEBUG "MPSSDEBUG" 79*7c478bd9Sstevel@tonic-gate #define MPSSPRINT(x, y) if (mpssdebug & x) (void) fprintf y; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate static int mpssdebug; 82*7c478bd9Sstevel@tonic-gate #else 83*7c478bd9Sstevel@tonic-gate #define MPSSPRINT(x, y) 84*7c478bd9Sstevel@tonic-gate #endif 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 87*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 88*7c478bd9Sstevel@tonic-gate #endif 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 91*7c478bd9Sstevel@tonic-gate static void 92*7c478bd9Sstevel@tonic-gate mpsserr(FILE *fp, char *fmt, ...) 93*7c478bd9Sstevel@tonic-gate { 94*7c478bd9Sstevel@tonic-gate va_list ap; 95*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 96*7c478bd9Sstevel@tonic-gate if (fp) 97*7c478bd9Sstevel@tonic-gate (void) vfprintf(fp, fmt, ap); 98*7c478bd9Sstevel@tonic-gate else 99*7c478bd9Sstevel@tonic-gate vsyslog(LOG_ERR, fmt, ap); 100*7c478bd9Sstevel@tonic-gate va_end(ap); 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate /* 104*7c478bd9Sstevel@tonic-gate * Return the pointer to the fully-resolved path name of the process's 105*7c478bd9Sstevel@tonic-gate * executable file obtained from the AT_SUN_EXECNAME aux vector entry. 106*7c478bd9Sstevel@tonic-gate */ 107*7c478bd9Sstevel@tonic-gate static const char * 108*7c478bd9Sstevel@tonic-gate mygetexecname(void) 109*7c478bd9Sstevel@tonic-gate { 110*7c478bd9Sstevel@tonic-gate const char *execname = NULL; 111*7c478bd9Sstevel@tonic-gate static auxv_t auxb; 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate /* 114*7c478bd9Sstevel@tonic-gate * The first time through, read the initial aux vector that was 115*7c478bd9Sstevel@tonic-gate * passed to the process at exec(2). Only do this once. 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate int fd = open("/proc/self/auxv", O_RDONLY); 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate if (fd >= 0) { 120*7c478bd9Sstevel@tonic-gate while (read(fd, &auxb, sizeof (auxv_t)) == sizeof (auxv_t)) { 121*7c478bd9Sstevel@tonic-gate if (auxb.a_type == AT_SUN_EXECNAME) { 122*7c478bd9Sstevel@tonic-gate execname = auxb.a_un.a_ptr; 123*7c478bd9Sstevel@tonic-gate break; 124*7c478bd9Sstevel@tonic-gate } 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate (void) close(fd); 127*7c478bd9Sstevel@tonic-gate } 128*7c478bd9Sstevel@tonic-gate return (execname); 129*7c478bd9Sstevel@tonic-gate } 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate static size_t 132*7c478bd9Sstevel@tonic-gate atosz(char *szstr) 133*7c478bd9Sstevel@tonic-gate { 134*7c478bd9Sstevel@tonic-gate size_t sz; 135*7c478bd9Sstevel@tonic-gate char *endptr, c; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate sz = strtoll(szstr, &endptr, 0); 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate while (c = *endptr++) { 140*7c478bd9Sstevel@tonic-gate switch (c) { 141*7c478bd9Sstevel@tonic-gate case 't': 142*7c478bd9Sstevel@tonic-gate case 'T': 143*7c478bd9Sstevel@tonic-gate sz *= 1024; 144*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 145*7c478bd9Sstevel@tonic-gate case 'g': 146*7c478bd9Sstevel@tonic-gate case 'G': 147*7c478bd9Sstevel@tonic-gate sz *= 1024; 148*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 149*7c478bd9Sstevel@tonic-gate case 'm': 150*7c478bd9Sstevel@tonic-gate case 'M': 151*7c478bd9Sstevel@tonic-gate sz *= 1024; 152*7c478bd9Sstevel@tonic-gate /*FALLTHRU*/ 153*7c478bd9Sstevel@tonic-gate case 'k': 154*7c478bd9Sstevel@tonic-gate case 'K': 155*7c478bd9Sstevel@tonic-gate sz *= 1024; 156*7c478bd9Sstevel@tonic-gate default: 157*7c478bd9Sstevel@tonic-gate break; 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate return (sz); 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate #define PGSZELEM (8 * sizeof (void *)) 165*7c478bd9Sstevel@tonic-gate static size_t pgsz[PGSZELEM]; 166*7c478bd9Sstevel@tonic-gate static int nelem; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate static int 169*7c478bd9Sstevel@tonic-gate pgszok(size_t sz) 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate int i; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate if (sz == 0) 174*7c478bd9Sstevel@tonic-gate return (1); 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate for (i = 0; i < nelem; i++) { 177*7c478bd9Sstevel@tonic-gate if (sz == pgsz[i]) 178*7c478bd9Sstevel@tonic-gate break; 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate return (i < nelem); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate static void 185*7c478bd9Sstevel@tonic-gate pgszinit() 186*7c478bd9Sstevel@tonic-gate { 187*7c478bd9Sstevel@tonic-gate nelem = getpagesizes(NULL, 0); 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate if (!nelem) 190*7c478bd9Sstevel@tonic-gate return; 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate if (nelem > PGSZELEM) 193*7c478bd9Sstevel@tonic-gate nelem = PGSZELEM; 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate (void) getpagesizes(pgsz, nelem); 196*7c478bd9Sstevel@tonic-gate #ifdef MPSSDEBUG 197*7c478bd9Sstevel@tonic-gate pgsz[nelem] = 0x800000; 198*7c478bd9Sstevel@tonic-gate nelem++; 199*7c478bd9Sstevel@tonic-gate #endif 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate static int 204*7c478bd9Sstevel@tonic-gate pgszset(size_t sz, uint_t flags) 205*7c478bd9Sstevel@tonic-gate { 206*7c478bd9Sstevel@tonic-gate struct memcntl_mha mpss; 207*7c478bd9Sstevel@tonic-gate int rc; 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate mpss.mha_cmd = (flags == MPSSHEAP) ? 210*7c478bd9Sstevel@tonic-gate MHA_MAPSIZE_BSSBRK: MHA_MAPSIZE_STACK; 211*7c478bd9Sstevel@tonic-gate mpss.mha_pagesize = sz; 212*7c478bd9Sstevel@tonic-gate mpss.mha_flags = 0; 213*7c478bd9Sstevel@tonic-gate rc = memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0); 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate return (rc); 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate /* 219*7c478bd9Sstevel@tonic-gate * check if exec name matches cfgname found in mpss cfg file. 220*7c478bd9Sstevel@tonic-gate */ 221*7c478bd9Sstevel@tonic-gate static int 222*7c478bd9Sstevel@tonic-gate fnmatch(const char *execname, char *cfgname, char *cwd) 223*7c478bd9Sstevel@tonic-gate { 224*7c478bd9Sstevel@tonic-gate const char *ename; 225*7c478bd9Sstevel@tonic-gate int rc; 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate /* cfgname should not have a '/' unless it begins with one */ 228*7c478bd9Sstevel@tonic-gate if (cfgname[0] == '/') { 229*7c478bd9Sstevel@tonic-gate /* 230*7c478bd9Sstevel@tonic-gate * if execname does not begin with a '/', prepend the 231*7c478bd9Sstevel@tonic-gate * current directory. 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate if (execname[0] != '/') { 234*7c478bd9Sstevel@tonic-gate ename = (const char *)strcat(cwd, execname); 235*7c478bd9Sstevel@tonic-gate } else 236*7c478bd9Sstevel@tonic-gate ename = execname; 237*7c478bd9Sstevel@tonic-gate } else { /* simple cfg name */ 238*7c478bd9Sstevel@tonic-gate if (ename = strrchr(execname, '/')) 239*7c478bd9Sstevel@tonic-gate /* execname is a path name - get the base name */ 240*7c478bd9Sstevel@tonic-gate ename++; 241*7c478bd9Sstevel@tonic-gate else 242*7c478bd9Sstevel@tonic-gate ename = execname; 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate rc = gmatch(ename, cfgname); 245*7c478bd9Sstevel@tonic-gate MPSSPRINT(2, (stderr, "gmatch: %s %s %s %d\n", 246*7c478bd9Sstevel@tonic-gate cfgname, ename, execname, rc)); 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate return (rc); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate /* 252*7c478bd9Sstevel@tonic-gate * Check if string matches any of exec arguments. 253*7c478bd9Sstevel@tonic-gate */ 254*7c478bd9Sstevel@tonic-gate static int 255*7c478bd9Sstevel@tonic-gate argmatch(char *str, FILE *errfp) 256*7c478bd9Sstevel@tonic-gate { 257*7c478bd9Sstevel@tonic-gate int fd; 258*7c478bd9Sstevel@tonic-gate psinfo_t pi; 259*7c478bd9Sstevel@tonic-gate int rc = 0; 260*7c478bd9Sstevel@tonic-gate int arg; 261*7c478bd9Sstevel@tonic-gate char **argv; 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate fd = open("/proc/self/psinfo", O_RDONLY); 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate if (fd >= 0) { 266*7c478bd9Sstevel@tonic-gate if (read(fd, &pi, sizeof (pi)) == sizeof (pi)) { 267*7c478bd9Sstevel@tonic-gate argv = (char **)pi.pr_argv; 268*7c478bd9Sstevel@tonic-gate argv++; 269*7c478bd9Sstevel@tonic-gate MPSSPRINT(2, (stderr, "argmatch: %s ", str)); 270*7c478bd9Sstevel@tonic-gate for (arg = 1; arg < pi.pr_argc; arg++, argv++) { 271*7c478bd9Sstevel@tonic-gate if (rc = gmatch(*argv, str)) { 272*7c478bd9Sstevel@tonic-gate MPSSPRINT(2, (stderr, "%s ", *argv)); 273*7c478bd9Sstevel@tonic-gate break; 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate MPSSPRINT(2, (stderr, "%d\n", rc)); 277*7c478bd9Sstevel@tonic-gate } else { 278*7c478bd9Sstevel@tonic-gate mpsserr(errfp, dgettext(TEXT_DOMAIN, 279*7c478bd9Sstevel@tonic-gate "%s: /proc/self/psinfo read failed [%s]\n"), 280*7c478bd9Sstevel@tonic-gate mpssident, strerror(errno)); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate (void) close(fd); 283*7c478bd9Sstevel@tonic-gate } else { 284*7c478bd9Sstevel@tonic-gate mpsserr(errfp, dgettext(TEXT_DOMAIN, 285*7c478bd9Sstevel@tonic-gate "%s: /proc/self/psinfo open failed [%s]\n"), 286*7c478bd9Sstevel@tonic-gate mpssident, strerror(errno)); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate return (rc); 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate static int 292*7c478bd9Sstevel@tonic-gate empty(char *str) 293*7c478bd9Sstevel@tonic-gate { 294*7c478bd9Sstevel@tonic-gate char c; 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate while ((c = *str) == '\n' || c == ' ' || c == '\t') 297*7c478bd9Sstevel@tonic-gate str++; 298*7c478bd9Sstevel@tonic-gate return (*str == '\0'); 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate void 302*7c478bd9Sstevel@tonic-gate __mpssmain() 303*7c478bd9Sstevel@tonic-gate { 304*7c478bd9Sstevel@tonic-gate static size_t heapsz = (size_t)-1, stacksz = (size_t)-1, sz; 305*7c478bd9Sstevel@tonic-gate char *cfgfile, *errfile; 306*7c478bd9Sstevel@tonic-gate const char *execname; 307*7c478bd9Sstevel@tonic-gate char *cwd; 308*7c478bd9Sstevel@tonic-gate int cwdlen; 309*7c478bd9Sstevel@tonic-gate FILE *fp = NULL, *errfp = NULL; 310*7c478bd9Sstevel@tonic-gate char *tok, *tokheap = NULL, *tokstack = NULL, *tokarg; 311*7c478bd9Sstevel@tonic-gate char *str, *envheap, *envstack; 312*7c478bd9Sstevel@tonic-gate int lineno = 0; 313*7c478bd9Sstevel@tonic-gate char *locale; 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate /* 316*7c478bd9Sstevel@tonic-gate * If a private error file is indicated then set the locale 317*7c478bd9Sstevel@tonic-gate * for error messages for the duration of this routine. 318*7c478bd9Sstevel@tonic-gate * Error messages destined for syslog should not be translated 319*7c478bd9Sstevel@tonic-gate * and thus come from the default C locale. 320*7c478bd9Sstevel@tonic-gate */ 321*7c478bd9Sstevel@tonic-gate if ((errfile = getenv(ENV_MPSSERRFILE)) != NULL) { 322*7c478bd9Sstevel@tonic-gate errfp = fopen(errfile, "a"); 323*7c478bd9Sstevel@tonic-gate if (errfp) { 324*7c478bd9Sstevel@tonic-gate locale = setlocale(LC_MESSAGES, ""); 325*7c478bd9Sstevel@tonic-gate } else { 326*7c478bd9Sstevel@tonic-gate mpsserr(NULL, dgettext(TEXT_DOMAIN, 327*7c478bd9Sstevel@tonic-gate "%s: cannot open error file: %s [%s]\n"), 328*7c478bd9Sstevel@tonic-gate mpssident, errfile, strerror(errno)); 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate #ifdef MPSSDEBUG 333*7c478bd9Sstevel@tonic-gate if (str = getenv(ENV_MPSSDEBUG)) 334*7c478bd9Sstevel@tonic-gate mpssdebug = atosz(str); 335*7c478bd9Sstevel@tonic-gate #endif 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate pgszinit(); 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate if (envstack = getenv(ENV_MPSSSTACK)) { 340*7c478bd9Sstevel@tonic-gate sz = atosz(envstack); 341*7c478bd9Sstevel@tonic-gate if (pgszok(sz)) 342*7c478bd9Sstevel@tonic-gate stacksz = sz; 343*7c478bd9Sstevel@tonic-gate else 344*7c478bd9Sstevel@tonic-gate mpsserr(errfp, dgettext(TEXT_DOMAIN, 345*7c478bd9Sstevel@tonic-gate "%s: invalid stack page size specified:" 346*7c478bd9Sstevel@tonic-gate " MPSSSTACK=%s\n"), 347*7c478bd9Sstevel@tonic-gate mpssident, envstack); 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate 350*7c478bd9Sstevel@tonic-gate if (envheap = getenv(ENV_MPSSHEAP)) { 351*7c478bd9Sstevel@tonic-gate sz = atosz(envheap); 352*7c478bd9Sstevel@tonic-gate if (pgszok(sz)) 353*7c478bd9Sstevel@tonic-gate heapsz = sz; 354*7c478bd9Sstevel@tonic-gate else 355*7c478bd9Sstevel@tonic-gate mpsserr(errfp, dgettext(TEXT_DOMAIN, 356*7c478bd9Sstevel@tonic-gate "%s: invalid heap page size specified:" 357*7c478bd9Sstevel@tonic-gate " MPSSHEAP=%s\n"), 358*7c478bd9Sstevel@tonic-gate mpssident, envheap); 359*7c478bd9Sstevel@tonic-gate } 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate /* 362*7c478bd9Sstevel@tonic-gate * Open specified cfg file or default one. 363*7c478bd9Sstevel@tonic-gate */ 364*7c478bd9Sstevel@tonic-gate if (cfgfile = getenv(ENV_MPSSCFGFILE)) { 365*7c478bd9Sstevel@tonic-gate fp = fopen(cfgfile, "r"); 366*7c478bd9Sstevel@tonic-gate if (!fp) { 367*7c478bd9Sstevel@tonic-gate mpsserr(errfp, dgettext(TEXT_DOMAIN, 368*7c478bd9Sstevel@tonic-gate "%s: cannot open configuration file: %s [%s]\n"), 369*7c478bd9Sstevel@tonic-gate mpssident, cfgfile, strerror(errno)); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate } else { 372*7c478bd9Sstevel@tonic-gate cfgfile = DEF_MPSSCFGFILE; 373*7c478bd9Sstevel@tonic-gate fp = fopen(cfgfile, "r"); 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate execname = mygetexecname(); 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate if (fp) { 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate cwd = getcwd(pbuf, MAXPATHLEN); 381*7c478bd9Sstevel@tonic-gate if (!cwd) 382*7c478bd9Sstevel@tonic-gate return; 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate cwd = strcat(cwd, "/"); 385*7c478bd9Sstevel@tonic-gate cwdlen = strlen(cwd); 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate while (fgets(lbuf, MAXLINELEN, fp)) { 388*7c478bd9Sstevel@tonic-gate lineno++; 389*7c478bd9Sstevel@tonic-gate if (empty(lbuf)) 390*7c478bd9Sstevel@tonic-gate continue; 391*7c478bd9Sstevel@tonic-gate /* 392*7c478bd9Sstevel@tonic-gate * Make sure line wasn't truncated. 393*7c478bd9Sstevel@tonic-gate */ 394*7c478bd9Sstevel@tonic-gate if (strlen(lbuf) >= MAXLINELEN - 1) { 395*7c478bd9Sstevel@tonic-gate mpsserr(errfp, dgettext(TEXT_DOMAIN, 396*7c478bd9Sstevel@tonic-gate "%s: invalid entry, " 397*7c478bd9Sstevel@tonic-gate "line too long - cfgfile:" 398*7c478bd9Sstevel@tonic-gate " %s, line: %d\n"), 399*7c478bd9Sstevel@tonic-gate mpssident, cfgfile, lineno); 400*7c478bd9Sstevel@tonic-gate continue; 401*7c478bd9Sstevel@tonic-gate } 402*7c478bd9Sstevel@tonic-gate /* 403*7c478bd9Sstevel@tonic-gate * parse right to left in case delimiter is 404*7c478bd9Sstevel@tonic-gate * in name. 405*7c478bd9Sstevel@tonic-gate */ 406*7c478bd9Sstevel@tonic-gate if (!(tokstack = strrchr(lbuf, CFGDELIMITER))) { 407*7c478bd9Sstevel@tonic-gate mpsserr(errfp, dgettext(TEXT_DOMAIN, 408*7c478bd9Sstevel@tonic-gate "%s: no delimiters specified - cfgfile:" 409*7c478bd9Sstevel@tonic-gate " %s, line: %d\n"), 410*7c478bd9Sstevel@tonic-gate mpssident, cfgfile, lineno); 411*7c478bd9Sstevel@tonic-gate continue; 412*7c478bd9Sstevel@tonic-gate } 413*7c478bd9Sstevel@tonic-gate /* found delimiter in lbuf */ 414*7c478bd9Sstevel@tonic-gate *tokstack++ = '\0'; 415*7c478bd9Sstevel@tonic-gate /* remove for error message */ 416*7c478bd9Sstevel@tonic-gate if (str = strrchr(tokstack, '\n')) 417*7c478bd9Sstevel@tonic-gate *str = '\0'; 418*7c478bd9Sstevel@tonic-gate if (!(tokheap = strrchr(lbuf, CFGDELIMITER))) { 419*7c478bd9Sstevel@tonic-gate mpsserr(errfp, dgettext(TEXT_DOMAIN, 420*7c478bd9Sstevel@tonic-gate "%s: invalid entry, " 421*7c478bd9Sstevel@tonic-gate "missing delimiter - cfgfile: %s," 422*7c478bd9Sstevel@tonic-gate " line: %d\n"), 423*7c478bd9Sstevel@tonic-gate mpssident, cfgfile, lineno); 424*7c478bd9Sstevel@tonic-gate continue; 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate *tokheap++ = '\0'; 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate /* exec-args is optional */ 429*7c478bd9Sstevel@tonic-gate if (tokarg = strrchr(lbuf, ARGDELIMITER)) { 430*7c478bd9Sstevel@tonic-gate *tokarg++ = '\0'; 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate tok = lbuf; 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate if (!fnmatch(execname, tok, cwd)) { 436*7c478bd9Sstevel@tonic-gate tokheap = tokstack = tokarg = NULL; 437*7c478bd9Sstevel@tonic-gate cwd[cwdlen] = '\0'; 438*7c478bd9Sstevel@tonic-gate continue; 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate if (tokarg && 442*7c478bd9Sstevel@tonic-gate !empty(tokarg) && 443*7c478bd9Sstevel@tonic-gate !argmatch(tokarg, errfp)) { 444*7c478bd9Sstevel@tonic-gate tokheap = tokstack = tokarg = NULL; 445*7c478bd9Sstevel@tonic-gate cwd[cwdlen] = '\0'; 446*7c478bd9Sstevel@tonic-gate continue; 447*7c478bd9Sstevel@tonic-gate } 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate /* heap token */ 450*7c478bd9Sstevel@tonic-gate if (empty(tokheap)) { 451*7c478bd9Sstevel@tonic-gate /* empty cfg entry */ 452*7c478bd9Sstevel@tonic-gate heapsz = (size_t)-1; 453*7c478bd9Sstevel@tonic-gate } else { 454*7c478bd9Sstevel@tonic-gate sz = atosz(tokheap); 455*7c478bd9Sstevel@tonic-gate if (pgszok(sz)) 456*7c478bd9Sstevel@tonic-gate heapsz = sz; 457*7c478bd9Sstevel@tonic-gate else { 458*7c478bd9Sstevel@tonic-gate mpsserr(errfp, dgettext(TEXT_DOMAIN, 459*7c478bd9Sstevel@tonic-gate "%s: invalid heap page size" 460*7c478bd9Sstevel@tonic-gate " specified (%s) for %s - " 461*7c478bd9Sstevel@tonic-gate "cfgfile: %s, line: %d\n"), 462*7c478bd9Sstevel@tonic-gate mpssident, tokheap, 463*7c478bd9Sstevel@tonic-gate execname, cfgfile, 464*7c478bd9Sstevel@tonic-gate lineno); 465*7c478bd9Sstevel@tonic-gate heapsz = (size_t)-1; 466*7c478bd9Sstevel@tonic-gate } 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate /* stack token */ 470*7c478bd9Sstevel@tonic-gate if (empty(tokstack)) { 471*7c478bd9Sstevel@tonic-gate stacksz = (size_t)-1; 472*7c478bd9Sstevel@tonic-gate break; 473*7c478bd9Sstevel@tonic-gate } else { 474*7c478bd9Sstevel@tonic-gate sz = atosz(tokstack); 475*7c478bd9Sstevel@tonic-gate if (pgszok(sz)) 476*7c478bd9Sstevel@tonic-gate stacksz = sz; 477*7c478bd9Sstevel@tonic-gate else { 478*7c478bd9Sstevel@tonic-gate mpsserr(errfp, dgettext(TEXT_DOMAIN, 479*7c478bd9Sstevel@tonic-gate "%s: invalid stack page size" 480*7c478bd9Sstevel@tonic-gate " specified (%s) for %s - " 481*7c478bd9Sstevel@tonic-gate "cfgfile: %s, line: %d\n"), 482*7c478bd9Sstevel@tonic-gate mpssident, tokstack, 483*7c478bd9Sstevel@tonic-gate execname, cfgfile, lineno); 484*7c478bd9Sstevel@tonic-gate stacksz = (size_t)-1; 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate break; 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate if ((heapsz != (size_t)-1) && (pgszset(heapsz, MPSSHEAP) < 0)) 493*7c478bd9Sstevel@tonic-gate mpsserr(errfp, dgettext(TEXT_DOMAIN, 494*7c478bd9Sstevel@tonic-gate "%s: memcntl() failed [%s]: heap page size (%s)" 495*7c478bd9Sstevel@tonic-gate " for %s not set\n"), 496*7c478bd9Sstevel@tonic-gate mpssident, strerror(errno), (tokheap) ? tokheap : envheap, 497*7c478bd9Sstevel@tonic-gate execname); 498*7c478bd9Sstevel@tonic-gate if ((stacksz != (size_t)-1) && (pgszset(stacksz, MPSSSTACK) < 0)) 499*7c478bd9Sstevel@tonic-gate mpsserr(errfp, dgettext(TEXT_DOMAIN, 500*7c478bd9Sstevel@tonic-gate "%s: memcntl() failed [%s]: stack page size (%s)" 501*7c478bd9Sstevel@tonic-gate " for %s not set\n"), 502*7c478bd9Sstevel@tonic-gate mpssident, strerror(errno), (tokstack) ? tokstack: envstack, 503*7c478bd9Sstevel@tonic-gate execname); 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate if (errfp) { 506*7c478bd9Sstevel@tonic-gate (void) fclose(errfp); 507*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_MESSAGES, locale); 508*7c478bd9Sstevel@tonic-gate } else { 509*7c478bd9Sstevel@tonic-gate /* close log file: no-op if nothing logged to syslog */ 510*7c478bd9Sstevel@tonic-gate closelog(); 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate } 513