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