1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <stdio.h> 31 #include <string.h> 32 #include <stdlib.h> 33 #include <nss_dbdefs.h> 34 #include <prof_attr.h> 35 #include <getxby_door.h> 36 #include <sys/mman.h> 37 38 39 /* Externs from libnsl */ 40 extern profstr_t *_getprofnam(const char *, profstr_t *, char *, int, int *); 41 extern profstr_t *_getprofattr(profstr_t *, char *, int, int *); 42 extern void _setprofattr(void); 43 extern void _endprofattr(void); 44 45 static profattr_t *profstr2attr(profstr_t *); 46 static profstr_t *process_getprof(profstr_t *, char *, int, nsc_data_t *); 47 48 49 profattr_t * 50 getprofattr() 51 { 52 int err = 0; 53 char buf[NSS_BUFLEN_PROFATTR]; 54 profstr_t prof; 55 profstr_t *tmp; 56 57 tmp = _getprofattr(&prof, buf, NSS_BUFLEN_PROFATTR, &err); 58 return (profstr2attr(tmp)); 59 } 60 61 62 profattr_t * 63 getprofnam(const char *name) 64 { 65 int err = 0; 66 int ndata = 0; 67 int adata = 0; 68 char buf[NSS_BUFLEN_PROFATTR]; 69 profstr_t prof; 70 union { 71 nsc_data_t s_d; 72 char s_b[1024]; 73 } space; 74 nsc_data_t *sptr = (nsc_data_t *)NULL; 75 profstr_t *resptr = (profstr_t *)NULL; 76 77 (void) memset(&prof, 0, sizeof (profstr_t)); 78 79 #ifdef PIC 80 (void) memset(&space, 0, sizeof (space)); 81 82 if ((name == NULL) || 83 (strlen(name) >= (sizeof (space) - sizeof (nsc_data_t)))) { 84 errno = ERANGE; 85 return ((profattr_t *)NULL); 86 } 87 ndata = sizeof (space); 88 adata = strlen(name) + sizeof (nsc_call_t) + 1; 89 space.s_d.nsc_call.nsc_callnumber = GETPROFNAM; 90 (void) strcpy(space.s_d.nsc_call.nsc_u.name, name); 91 sptr = &space.s_d; 92 93 switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) { 94 case SUCCESS: /* positive cache hit */ 95 break; 96 case NOTFOUND: /* negative cache hit */ 97 return ((profattr_t *)NULL); 98 default: 99 (void) memset(&prof, 0, sizeof (profattr_t)); 100 resptr = _getprofnam(name, &prof, buf, 101 NSS_BUFLEN_PROFATTR, &err); 102 return (profstr2attr(resptr)); 103 } 104 resptr = process_getprof(&prof, buf, NSS_BUFLEN_PROFATTR, sptr); 105 106 /* 107 * check if doors reallocated the memory underneath us 108 * if they did munmap it or suffer a memory leak 109 */ 110 if (sptr != &space.s_d) 111 (void) munmap((void *)sptr, ndata); 112 #else /* !PIC */ 113 resptr = _getprofnam(name, &prof, buf, NSS_BUFLEN_PROFATTR, &err); 114 #endif /* PIC */ 115 116 return (profstr2attr(resptr)); 117 118 } 119 120 121 void 122 setprofattr() 123 { 124 _setprofattr(); 125 } 126 127 128 void 129 endprofattr() 130 { 131 _endprofattr(); 132 } 133 134 135 void 136 free_profattr(profattr_t *prof) 137 { 138 if (prof) { 139 free(prof->name); 140 free(prof->res1); 141 free(prof->res2); 142 free(prof->desc); 143 _kva_free(prof->attr); 144 free(prof); 145 } 146 } 147 148 149 static profattr_t * 150 profstr2attr(profstr_t *prof) 151 { 152 profattr_t *newprof; 153 154 if (prof == NULL) 155 return ((profattr_t *)NULL); 156 157 if ((newprof = (profattr_t *)malloc(sizeof (profattr_t))) == NULL) 158 return ((profattr_t *)NULL); 159 160 newprof->name = _do_unescape(prof->name); 161 newprof->res1 = _do_unescape(prof->res1); 162 newprof->res2 = _do_unescape(prof->res2); 163 newprof->desc = _do_unescape(prof->desc); 164 newprof->attr = _str2kva(prof->attr, KV_ASSIGN, KV_DELIMITER); 165 return (newprof); 166 } 167 168 169 static profstr_t * 170 process_getprof( 171 profstr_t *result, 172 char *buffer, 173 int buflen, 174 nsc_data_t *sptr) 175 { 176 char *fixed; 177 #ifdef _LP64 178 profstr_t prof64; 179 180 fixed = (char *)(((uintptr_t)buffer + 7) & ~7); 181 #else 182 fixed = (char *)(((uintptr_t)buffer + 3) & ~3); 183 #endif 184 buflen -= fixed - buffer; 185 buffer = fixed; 186 187 if (sptr->nsc_ret.nsc_return_code != SUCCESS) 188 return ((profstr_t *)NULL); 189 190 #ifdef _LP64 191 if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (profstr32_t) 192 > buflen) 193 #else 194 if (sptr->nsc_ret.nsc_bufferbytesused - (int)sizeof (profstr_t) 195 > buflen) 196 #endif 197 { 198 errno = ERANGE; 199 return ((profstr_t *)NULL); 200 } 201 202 #ifdef _LP64 203 (void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (profstr32_t)), 204 (sptr->nsc_ret.nsc_bufferbytesused - sizeof (profstr32_t))); 205 prof64.name = (char *)(sptr->nsc_ret.nsc_u.prof.name + 206 (uintptr_t)buffer); 207 prof64.res1 = (char *)(sptr->nsc_ret.nsc_u.prof.res1 + 208 (uintptr_t)buffer); 209 prof64.res2 = (char *)(sptr->nsc_ret.nsc_u.prof.res2 + 210 (uintptr_t)buffer); 211 prof64.desc = (char *)(sptr->nsc_ret.nsc_u.prof.desc + 212 (uintptr_t)buffer); 213 prof64.attr = (char *)(sptr->nsc_ret.nsc_u.prof.attr + 214 (uintptr_t)buffer); 215 *result = prof64; 216 #else 217 sptr->nsc_ret.nsc_u.prof.name += (uintptr_t)buffer; 218 sptr->nsc_ret.nsc_u.prof.res1 += (uintptr_t)buffer; 219 sptr->nsc_ret.nsc_u.prof.res2 += (uintptr_t)buffer; 220 sptr->nsc_ret.nsc_u.prof.desc += (uintptr_t)buffer; 221 sptr->nsc_ret.nsc_u.prof.attr += (uintptr_t)buffer; 222 *result = sptr->nsc_ret.nsc_u.prof; 223 (void) memcpy(buffer, (sptr->nsc_ret.nsc_u.buff + sizeof (profstr_t)), 224 (sptr->nsc_ret.nsc_bufferbytesused - sizeof (profstr_t))); 225 #endif 226 return (result); 227 } 228 229 230 /* 231 * Given a profile name, gets the list of profiles found from 232 * the whole hierarchy, using the given profile as root 233 */ 234 void 235 getproflist(const char *profileName, char **profArray, int *profcnt) 236 { 237 profattr_t *profattr; 238 char *subprofiles, *lasts, *profname; 239 int i; 240 241 /* Check if this is a duplicate */ 242 for (i = 0; i < *profcnt; i++) { 243 if (strcmp(profileName, profArray[i]) == 0) { 244 /* It's a duplicate, don't need to do anything */ 245 return; 246 } 247 } 248 249 profArray[*profcnt] = strdup(profileName); 250 *profcnt = *profcnt + 1; 251 252 profattr = getprofnam(profileName); 253 if (profattr == NULL) { 254 return; 255 } 256 257 if (profattr->attr == NULL) { 258 free_profattr(profattr); 259 return; 260 } 261 262 subprofiles = kva_match(profattr->attr, PROFATTR_PROFS_KW); 263 if (subprofiles == NULL) { 264 free_profattr(profattr); 265 return; 266 } 267 268 /* get execattr from each subprofiles */ 269 for (profname = (char *)strtok_r(subprofiles, ",", &lasts); 270 profname != NULL; 271 profname = (char *)strtok_r(NULL, ",", &lasts)) { 272 getproflist(profname, profArray, profcnt); 273 } 274 free_profattr(profattr); 275 } 276 277 void 278 free_proflist(char **profArray, int profcnt) 279 { 280 int i; 281 for (i = 0; i < profcnt; i++) { 282 free(profArray[i]); 283 } 284 } 285 286 287 #ifdef DEBUG 288 void 289 print_profattr(profattr_t *prof) 290 { 291 extern void print_kva(kva_t *); 292 char *empty = "empty"; 293 294 if (prof == NULL) { 295 printf("NULL\n"); 296 return; 297 } 298 299 printf("name=%s\n", prof->name ? prof->name : empty); 300 printf("res1=%s\n", prof->res1 ? prof->res1 : empty); 301 printf("res2=%s\n", prof->res2 ? prof->res2 : empty); 302 printf("desc=%s\n", prof->desc ? prof->desc : empty); 303 printf("attr=\n"); 304 print_kva(prof->attr); 305 fflush(stdout); 306 } 307 #endif /* DEBUG */ 308