17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 23*f166393fSesolom * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * Routines to handle getexec* calls in nscd 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate #include <assert.h> 347c478bd9Sstevel@tonic-gate #include <errno.h> 357c478bd9Sstevel@tonic-gate #include <memory.h> 367c478bd9Sstevel@tonic-gate #include <signal.h> 377c478bd9Sstevel@tonic-gate #include <stdio.h> 387c478bd9Sstevel@tonic-gate #include <stdlib.h> 397c478bd9Sstevel@tonic-gate #include <string.h> 407c478bd9Sstevel@tonic-gate #include <sys/door.h> 417c478bd9Sstevel@tonic-gate #include <sys/stat.h> 427c478bd9Sstevel@tonic-gate #include <sys/time.h> 437c478bd9Sstevel@tonic-gate #include <sys/types.h> 447c478bd9Sstevel@tonic-gate #include <sys/wait.h> 457c478bd9Sstevel@tonic-gate #include <thread.h> 467c478bd9Sstevel@tonic-gate #include <unistd.h> 477c478bd9Sstevel@tonic-gate #include <ucred.h> 487c478bd9Sstevel@tonic-gate #include <nss_common.h> 497c478bd9Sstevel@tonic-gate #include <nss_dbdefs.h> 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate #include <exec_attr.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #include <getxby_door.h> 547c478bd9Sstevel@tonic-gate #include "server_door.h" 557c478bd9Sstevel@tonic-gate #include "nscd.h" 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate extern execstr_t *_getexecprof(char *, char *, char *, int, execstr_t *, 587c478bd9Sstevel@tonic-gate char *, int, int *); 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate static hash_t *nam_hash; 617c478bd9Sstevel@tonic-gate static mutex_t db_lock = DEFAULTMUTEX; 627c478bd9Sstevel@tonic-gate static waiter_t db_wait; 637c478bd9Sstevel@tonic-gate 64*f166393fSesolom static int getexec_namekeepalive(int keep, int interval); 657c478bd9Sstevel@tonic-gate static int update_exec_bucket(nsc_bucket_t **old, nsc_bucket_t *new, 667c478bd9Sstevel@tonic-gate int callnumber); 677c478bd9Sstevel@tonic-gate static nsc_bucket_t *fixbuffer(nsc_return_t *in, int maxlen); 687c478bd9Sstevel@tonic-gate static void do_findgnams(nsc_bucket_t *ptr, int *table, char *gnam); 697c478bd9Sstevel@tonic-gate static void do_invalidate(nsc_bucket_t **ptr, int callnumber); 707c478bd9Sstevel@tonic-gate static void getexec_invalidate_unlocked(void); 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate void 747c478bd9Sstevel@tonic-gate getexec_init(void) 757c478bd9Sstevel@tonic-gate { 767c478bd9Sstevel@tonic-gate nam_hash = make_hash(current_admin.exec.nsc_suggestedsize); 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate static void 807c478bd9Sstevel@tonic-gate do_invalidate(nsc_bucket_t ** ptr, int callnumber) 817c478bd9Sstevel@tonic-gate { 827c478bd9Sstevel@tonic-gate if (*ptr != NULL && *ptr != (nsc_bucket_t *)-1) { 837c478bd9Sstevel@tonic-gate /* leave pending calls alone */ 847c478bd9Sstevel@tonic-gate update_exec_bucket(ptr, NULL, callnumber); 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate static void 897c478bd9Sstevel@tonic-gate do_findgnams(nsc_bucket_t *ptr, int *table, char *gnam) 907c478bd9Sstevel@tonic-gate { 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * be careful with ptr - it may be -1 or NULL. 947c478bd9Sstevel@tonic-gate */ 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate if (ptr != NULL && ptr != (nsc_bucket_t *)-1) { 977c478bd9Sstevel@tonic-gate char *tmp = (char *)insertn(table, ptr->nsc_hits, 987c478bd9Sstevel@tonic-gate (int)strdup(gnam)); 997c478bd9Sstevel@tonic-gate if (tmp != (char *)-1) 1007c478bd9Sstevel@tonic-gate free(tmp); 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate void 1057c478bd9Sstevel@tonic-gate getexec_revalidate(void) 1067c478bd9Sstevel@tonic-gate { 1077c478bd9Sstevel@tonic-gate for (;;) { 1087c478bd9Sstevel@tonic-gate int slp; 1097c478bd9Sstevel@tonic-gate int interval; 1107c478bd9Sstevel@tonic-gate int count; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate slp = current_admin.exec.nsc_pos_ttl; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate if (slp < 60) { 1157c478bd9Sstevel@tonic-gate slp = 60; 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate if ((count = current_admin.exec.nsc_keephot) != 0) { 1187c478bd9Sstevel@tonic-gate interval = (slp / 2)/count; 1197c478bd9Sstevel@tonic-gate if (interval == 0) interval = 1; 1207c478bd9Sstevel@tonic-gate sleep(slp * 2 / 3); 1217c478bd9Sstevel@tonic-gate getexec_namekeepalive(count, interval); 1227c478bd9Sstevel@tonic-gate } else { 1237c478bd9Sstevel@tonic-gate sleep(slp); 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate 128*f166393fSesolom static int 1297c478bd9Sstevel@tonic-gate getexec_namekeepalive(int keep, int interval) 1307c478bd9Sstevel@tonic-gate { 1317c478bd9Sstevel@tonic-gate int *table; 1327c478bd9Sstevel@tonic-gate union { 1337c478bd9Sstevel@tonic-gate nsc_data_t ping; 1347c478bd9Sstevel@tonic-gate char space[sizeof (nsc_data_t) + NSCDMAXNAMELEN]; 1357c478bd9Sstevel@tonic-gate } u; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate int i; 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate if (!keep) 1407c478bd9Sstevel@tonic-gate return (0); 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate table = maken(keep); 1437c478bd9Sstevel@tonic-gate mutex_lock(&db_lock); 1447c478bd9Sstevel@tonic-gate operate_hash(nam_hash, do_findgnams, (char *)table); 1457c478bd9Sstevel@tonic-gate mutex_unlock(&db_lock); 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate for (i = 1; i <= keep; i++) { 1487c478bd9Sstevel@tonic-gate char *tmp; 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate u.ping.nsc_call.nsc_callnumber = GETEXECID; 1517c478bd9Sstevel@tonic-gate if ((tmp = (char *)table[keep + 1 + i]) == (char *)-1) 1527c478bd9Sstevel@tonic-gate continue; /* unused slot in table */ 1537c478bd9Sstevel@tonic-gate strcpy(u.ping.nsc_call.nsc_u.name, tmp); 1547c478bd9Sstevel@tonic-gate launch_update(&u.ping.nsc_call); 1557c478bd9Sstevel@tonic-gate sleep(interval); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate for (i = 1; i <= keep; i++) { 1597c478bd9Sstevel@tonic-gate char *tmp; 1607c478bd9Sstevel@tonic-gate if ((tmp = (char *)table[keep + 1 + i]) != (char *)-1) 1617c478bd9Sstevel@tonic-gate free(tmp); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate free(table); 1657c478bd9Sstevel@tonic-gate return (0); 1667c478bd9Sstevel@tonic-gate } 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /* 1707c478bd9Sstevel@tonic-gate * This routine marks all entries as invalid 1717c478bd9Sstevel@tonic-gate * 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate void 1757c478bd9Sstevel@tonic-gate getexec_invalidate(void) 1767c478bd9Sstevel@tonic-gate { 1777c478bd9Sstevel@tonic-gate mutex_lock(&db_lock); 1787c478bd9Sstevel@tonic-gate getexec_invalidate_unlocked(); 1797c478bd9Sstevel@tonic-gate mutex_unlock(&db_lock); 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate static void 1837c478bd9Sstevel@tonic-gate getexec_invalidate_unlocked(void) 1847c478bd9Sstevel@tonic-gate { 1857c478bd9Sstevel@tonic-gate operate_hash_addr(nam_hash, do_invalidate, (char *)GETEXECID); 1867c478bd9Sstevel@tonic-gate current_admin.exec.nsc_invalidate_count++; 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate void 1907c478bd9Sstevel@tonic-gate getexec_lookup(nsc_return_t *out, int maxsize, nsc_call_t *in, time_t now) 1917c478bd9Sstevel@tonic-gate { 1927c478bd9Sstevel@tonic-gate int out_of_date; 1937c478bd9Sstevel@tonic-gate nsc_bucket_t *retb; 1947c478bd9Sstevel@tonic-gate char **bucket; 1957c478bd9Sstevel@tonic-gate char *p_name; 1967c478bd9Sstevel@tonic-gate char *p_type; 1977c478bd9Sstevel@tonic-gate char *p_id; 1987c478bd9Sstevel@tonic-gate char *unique; 1997c478bd9Sstevel@tonic-gate char *lasts; 2007c478bd9Sstevel@tonic-gate char *sep = ":"; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate static time_t lastmod; 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate int bufferspace = maxsize - sizeof (nsc_return_t); 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate if (current_admin.exec.nsc_enabled == 0) { 2077c478bd9Sstevel@tonic-gate out->nsc_return_code = NOSERVER; 2087c478bd9Sstevel@tonic-gate out->nsc_bufferbytesused = sizeof (*out); 2097c478bd9Sstevel@tonic-gate return; 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate mutex_lock(&db_lock); 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate if (current_admin.exec.nsc_check_files) { 2157c478bd9Sstevel@tonic-gate struct stat buf; 2167c478bd9Sstevel@tonic-gate 2177c478bd9Sstevel@tonic-gate if (stat(EXECATTR_FILENAME, &buf) < 0) { 2187c478bd9Sstevel@tonic-gate /*EMPTY*/; 2197c478bd9Sstevel@tonic-gate } else if (lastmod == 0) { 2207c478bd9Sstevel@tonic-gate lastmod = buf.st_mtime; 2217c478bd9Sstevel@tonic-gate } else if (lastmod < buf.st_mtime) { 2227c478bd9Sstevel@tonic-gate getexec_invalidate_unlocked(); 2237c478bd9Sstevel@tonic-gate lastmod = buf.st_mtime; 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 2287c478bd9Sstevel@tonic-gate logit("getexec_lookup: looking for name %s\n", 2297c478bd9Sstevel@tonic-gate in->nsc_u.name); 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate for (;;) { 2337c478bd9Sstevel@tonic-gate if (attr_strlen(in->nsc_u.name) > NSCDMAXNAMELEN) { 2347c478bd9Sstevel@tonic-gate ucred_t *uc = NULL; 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate if (door_ucred(&uc) != 0) { 2377c478bd9Sstevel@tonic-gate logit("getexec_lookup: Name too long, " 2387c478bd9Sstevel@tonic-gate "but no user credential: %s\n", 2397c478bd9Sstevel@tonic-gate strerror(errno)); 2407c478bd9Sstevel@tonic-gate } else { 2417c478bd9Sstevel@tonic-gate logit("getexec_lookup: Name too long from pid " 2427c478bd9Sstevel@tonic-gate "%d uid %d\n", ucred_getpid(uc), 2437c478bd9Sstevel@tonic-gate ucred_getruid(uc)); 2447c478bd9Sstevel@tonic-gate ucred_free(uc); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate out->nsc_errno = NSS_NOTFOUND; 2487c478bd9Sstevel@tonic-gate out->nsc_return_code = NOTFOUND; 2497c478bd9Sstevel@tonic-gate out->nsc_bufferbytesused = sizeof (*out); 2507c478bd9Sstevel@tonic-gate goto getout; 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate bucket = get_hash(nam_hash, in->nsc_u.name); 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate if (*bucket == (char *)-1) { /* pending lookup */ 2557c478bd9Sstevel@tonic-gate if (get_clearance(in->nsc_callnumber) != 0) { 2567c478bd9Sstevel@tonic-gate /* no threads available */ 2577c478bd9Sstevel@tonic-gate out->nsc_return_code = NOSERVER; 2587c478bd9Sstevel@tonic-gate /* cannot process now */ 2597c478bd9Sstevel@tonic-gate out->nsc_bufferbytesused = 2607c478bd9Sstevel@tonic-gate sizeof (*out); 2617c478bd9Sstevel@tonic-gate current_admin.exec.nsc_throttle_count++; 2627c478bd9Sstevel@tonic-gate goto getout; 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate nscd_wait(&db_wait, &db_lock, bucket); 2657c478bd9Sstevel@tonic-gate release_clearance(in->nsc_callnumber); 2667c478bd9Sstevel@tonic-gate continue; /* go back and relookup hash bucket */ 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate break; 2697c478bd9Sstevel@tonic-gate } 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate /* 2727c478bd9Sstevel@tonic-gate * check for no name_service mode 2737c478bd9Sstevel@tonic-gate */ 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate if (*bucket == NULL && current_admin.avoid_nameservice) { 2767c478bd9Sstevel@tonic-gate out->nsc_return_code = NOTFOUND; 2777c478bd9Sstevel@tonic-gate out->nsc_bufferbytesused = sizeof (*out); 2787c478bd9Sstevel@tonic-gate } else if ((*bucket == NULL) || /* New entry in name service */ 2797c478bd9Sstevel@tonic-gate (in->nsc_callnumber & UPDATEBIT) || /* needs updating */ 2807c478bd9Sstevel@tonic-gate (out_of_date = (!current_admin.avoid_nameservice && 2817c478bd9Sstevel@tonic-gate (current_admin.exec.nsc_old_data_ok == 0) && 2827c478bd9Sstevel@tonic-gate (((nsc_bucket_t *)*bucket)->nsc_timestamp < now)))) { 2837c478bd9Sstevel@tonic-gate /* time has expired */ 2847c478bd9Sstevel@tonic-gate int saved_errno; 2857c478bd9Sstevel@tonic-gate int saved_hits = 0; 2867c478bd9Sstevel@tonic-gate execstr_t *p; 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate if (get_clearance(in->nsc_callnumber) != 0) { 2897c478bd9Sstevel@tonic-gate /* no threads available */ 2907c478bd9Sstevel@tonic-gate out->nsc_return_code = NOSERVER; 2917c478bd9Sstevel@tonic-gate /* cannot process now */ 2927c478bd9Sstevel@tonic-gate out->nsc_bufferbytesused = sizeof (*out); 2937c478bd9Sstevel@tonic-gate current_admin.exec.nsc_throttle_count++; 2947c478bd9Sstevel@tonic-gate goto getout; 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate if (*bucket != NULL) { 2987c478bd9Sstevel@tonic-gate saved_hits = 2997c478bd9Sstevel@tonic-gate ((nsc_bucket_t *)*bucket)->nsc_hits; 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * block any threads accessing this bucket if data is 3047c478bd9Sstevel@tonic-gate * non-existent out of date 3057c478bd9Sstevel@tonic-gate */ 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate if (*bucket == NULL || out_of_date) { 3087c478bd9Sstevel@tonic-gate update_exec_bucket((nsc_bucket_t **)bucket, 3097c478bd9Sstevel@tonic-gate (nsc_bucket_t *)-1, 3107c478bd9Sstevel@tonic-gate in->nsc_callnumber); 3117c478bd9Sstevel@tonic-gate } else { 3127c478bd9Sstevel@tonic-gate /* 3137c478bd9Sstevel@tonic-gate * if still not -1 bucket we are doing update... 3147c478bd9Sstevel@tonic-gate * mark to prevent 3157c478bd9Sstevel@tonic-gate * pileups of threads if the name service is hanging.... 3167c478bd9Sstevel@tonic-gate */ 3177c478bd9Sstevel@tonic-gate ((nsc_bucket_t *)(*bucket))->nsc_status |= 3187c478bd9Sstevel@tonic-gate ST_UPDATE_PENDING; 3197c478bd9Sstevel@tonic-gate /* cleared by deletion of old data */ 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate mutex_unlock(&db_lock); 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate /* 3247c478bd9Sstevel@tonic-gate * Call non-caching version in libnsl. 3257c478bd9Sstevel@tonic-gate */ 3267c478bd9Sstevel@tonic-gate unique = strdup(in->nsc_u.name); 3277c478bd9Sstevel@tonic-gate p_name = strtok_r(unique, sep, &lasts); 3287c478bd9Sstevel@tonic-gate p_type = strtok_r(NULL, sep, &lasts); 3297c478bd9Sstevel@tonic-gate p_id = strtok_r(NULL, sep, &lasts); 3307c478bd9Sstevel@tonic-gate p = _getexecprof(p_name, 3317c478bd9Sstevel@tonic-gate p_type, 3327c478bd9Sstevel@tonic-gate p_id, 3337c478bd9Sstevel@tonic-gate GET_ONE, 3347c478bd9Sstevel@tonic-gate &out->nsc_u.exec, 3357c478bd9Sstevel@tonic-gate out->nsc_u.buff + sizeof (execstr_t), 3367c478bd9Sstevel@tonic-gate bufferspace, 3377c478bd9Sstevel@tonic-gate &saved_errno); 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate free(unique); 3407c478bd9Sstevel@tonic-gate mutex_lock(&db_lock); 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate release_clearance(in->nsc_callnumber); 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate if (p == NULL) { /* data not found */ 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_CANT_FIND) { 3477c478bd9Sstevel@tonic-gate logit("getexec_lookup: nscd COULDN'T FIND exec_attr name %s\n", 3487c478bd9Sstevel@tonic-gate in->nsc_u.name); 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate if (!(UPDATEBIT & in->nsc_callnumber)) 3527c478bd9Sstevel@tonic-gate current_admin.exec.nsc_neg_cache_misses++; 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate retb = (nsc_bucket_t *)malloc(sizeof (nsc_bucket_t)); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate retb->nsc_refcount = 1; 3577c478bd9Sstevel@tonic-gate retb->nsc_data.nsc_bufferbytesused = 3587c478bd9Sstevel@tonic-gate sizeof (nsc_return_t); 3597c478bd9Sstevel@tonic-gate retb->nsc_data.nsc_return_code = NOTFOUND; 3607c478bd9Sstevel@tonic-gate retb->nsc_data.nsc_errno = saved_errno; 3617c478bd9Sstevel@tonic-gate memcpy(out, &retb->nsc_data, 3627c478bd9Sstevel@tonic-gate retb->nsc_data.nsc_bufferbytesused); 3637c478bd9Sstevel@tonic-gate update_exec_bucket((nsc_bucket_t **)bucket, 3647c478bd9Sstevel@tonic-gate retb, in->nsc_callnumber); 3657c478bd9Sstevel@tonic-gate goto getout; 3667c478bd9Sstevel@tonic-gate } else { 3677c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 3687c478bd9Sstevel@tonic-gate logit("getexec_lookup: nscd FOUND exec_attr name %s\n", 3697c478bd9Sstevel@tonic-gate in->nsc_u.name); 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate if (!(UPDATEBIT & in->nsc_callnumber)) 3727c478bd9Sstevel@tonic-gate current_admin.exec.nsc_pos_cache_misses++; 3737c478bd9Sstevel@tonic-gate retb = fixbuffer(out, bufferspace); 3747c478bd9Sstevel@tonic-gate update_exec_bucket((nsc_bucket_t **)bucket, 3757c478bd9Sstevel@tonic-gate retb, in->nsc_callnumber); 3767c478bd9Sstevel@tonic-gate if (saved_hits) 3777c478bd9Sstevel@tonic-gate retb->nsc_hits = saved_hits; 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate } else { /* found entry in cache */ 3807c478bd9Sstevel@tonic-gate retb = (nsc_bucket_t *)*bucket; 3817c478bd9Sstevel@tonic-gate retb->nsc_hits++; 3827c478bd9Sstevel@tonic-gate memcpy(out, &(retb->nsc_data), 3837c478bd9Sstevel@tonic-gate retb->nsc_data.nsc_bufferbytesused); 3847c478bd9Sstevel@tonic-gate if (out->nsc_return_code == SUCCESS) { 3857c478bd9Sstevel@tonic-gate if (!(UPDATEBIT & in->nsc_callnumber)) 3867c478bd9Sstevel@tonic-gate current_admin.exec.nsc_pos_cache_hits++; 3877c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 3887c478bd9Sstevel@tonic-gate logit("getexec_lookup: found name %s in cache\n", 3897c478bd9Sstevel@tonic-gate in->nsc_u.name); 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate } else { 3927c478bd9Sstevel@tonic-gate if (!(UPDATEBIT & in->nsc_callnumber)) 3937c478bd9Sstevel@tonic-gate current_admin.exec.nsc_neg_cache_hits++; 3947c478bd9Sstevel@tonic-gate if (current_admin.debug_level >= DBG_ALL) { 3957c478bd9Sstevel@tonic-gate logit("getexec_lookup: %s marked as NOT FOUND in cache.\n", 3967c478bd9Sstevel@tonic-gate in->nsc_u.name); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate if ((retb->nsc_timestamp < now) && 4017c478bd9Sstevel@tonic-gate !(in->nsc_callnumber & UPDATEBIT) && 4027c478bd9Sstevel@tonic-gate !(retb->nsc_status & ST_UPDATE_PENDING)) { 4037c478bd9Sstevel@tonic-gate logit("launch update since time = %d\n", retb->nsc_timestamp); 4047c478bd9Sstevel@tonic-gate retb->nsc_status |= ST_UPDATE_PENDING; 4057c478bd9Sstevel@tonic-gate /* cleared by deletion of old data */ 4067c478bd9Sstevel@tonic-gate launch_update(in); 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate getout: 4117c478bd9Sstevel@tonic-gate mutex_unlock(&db_lock); 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4157c478bd9Sstevel@tonic-gate static int 4167c478bd9Sstevel@tonic-gate update_exec_bucket(nsc_bucket_t **old, nsc_bucket_t *new, int callnumber) 4177c478bd9Sstevel@tonic-gate { 4187c478bd9Sstevel@tonic-gate if (*old != NULL && *old != (nsc_bucket_t *)-1) { /* old data exists */ 4197c478bd9Sstevel@tonic-gate free(*old); 4207c478bd9Sstevel@tonic-gate current_admin.exec.nsc_entries--; 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate /* 4247c478bd9Sstevel@tonic-gate * we can do this before reseting *old since we're holding the lock 4257c478bd9Sstevel@tonic-gate */ 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate else if (*old == (nsc_bucket_t *)-1) { 4287c478bd9Sstevel@tonic-gate nscd_signal(&db_wait, (char **)old); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate *old = new; 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate if ((new != NULL) && (new != (nsc_bucket_t *)-1)) { 4347c478bd9Sstevel@tonic-gate /* real data, not just update pending or invalidate */ 4357c478bd9Sstevel@tonic-gate new->nsc_hits = 1; 4367c478bd9Sstevel@tonic-gate new->nsc_status = 0; 4377c478bd9Sstevel@tonic-gate new->nsc_refcount = 1; 4387c478bd9Sstevel@tonic-gate current_admin.exec.nsc_entries++; 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate if (new->nsc_data.nsc_return_code == SUCCESS) { 4417c478bd9Sstevel@tonic-gate new->nsc_timestamp = time(NULL) + 4427c478bd9Sstevel@tonic-gate current_admin.exec.nsc_pos_ttl; 4437c478bd9Sstevel@tonic-gate } else { 4447c478bd9Sstevel@tonic-gate new->nsc_timestamp = time(NULL) + 4457c478bd9Sstevel@tonic-gate current_admin.exec.nsc_neg_ttl; 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate return (0); 4497c478bd9Sstevel@tonic-gate } 4507c478bd9Sstevel@tonic-gate 4517c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4527c478bd9Sstevel@tonic-gate static nsc_bucket_t * 4537c478bd9Sstevel@tonic-gate fixbuffer(nsc_return_t *in, int maxlen) 4547c478bd9Sstevel@tonic-gate { 4557c478bd9Sstevel@tonic-gate nsc_bucket_t *retb; 4567c478bd9Sstevel@tonic-gate nsc_return_t *out; 4577c478bd9Sstevel@tonic-gate char *dest; 4587c478bd9Sstevel@tonic-gate int offset; 4597c478bd9Sstevel@tonic-gate int strs; 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate /* 4627c478bd9Sstevel@tonic-gate * find out the size of the data block we're going to need 4637c478bd9Sstevel@tonic-gate */ 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate strs = attr_strlen(in->nsc_u.exec.name) + 4667c478bd9Sstevel@tonic-gate attr_strlen(in->nsc_u.exec.policy) + 4677c478bd9Sstevel@tonic-gate attr_strlen(in->nsc_u.exec.type) + 4687c478bd9Sstevel@tonic-gate attr_strlen(in->nsc_u.exec.res1) + 4697c478bd9Sstevel@tonic-gate attr_strlen(in->nsc_u.exec.res2) + 4707c478bd9Sstevel@tonic-gate attr_strlen(in->nsc_u.exec.id) + 4717c478bd9Sstevel@tonic-gate attr_strlen(in->nsc_u.exec.attr) + EXECATTR_DB_NCOL; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate /* 4747c478bd9Sstevel@tonic-gate * allocate it and copy it in 4757c478bd9Sstevel@tonic-gate * code doesn't assume packing order in original buffer 4767c478bd9Sstevel@tonic-gate */ 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate if ((retb = (nsc_bucket_t *)malloc(sizeof (*retb) + strs)) == NULL) { 4797c478bd9Sstevel@tonic-gate return (NULL); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate out = &(retb->nsc_data); 4837c478bd9Sstevel@tonic-gate out->nsc_bufferbytesused = strs + ((int)&out->nsc_u.exec - (int)out) + 4847c478bd9Sstevel@tonic-gate sizeof (execstr_t); 4857c478bd9Sstevel@tonic-gate out->nsc_return_code = SUCCESS; 4867c478bd9Sstevel@tonic-gate out->nsc_errno = 0; 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate dest = retb->nsc_data.nsc_u.buff + sizeof (execstr_t); 4897c478bd9Sstevel@tonic-gate offset = (int)dest; 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate attr_strcpy(dest, in->nsc_u.exec.name); 4927c478bd9Sstevel@tonic-gate strs = 1 + attr_strlen(in->nsc_u.exec.name); 4937c478bd9Sstevel@tonic-gate out->nsc_u.exec.name = dest - offset; 4947c478bd9Sstevel@tonic-gate dest += strs; 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate attr_strcpy(dest, in->nsc_u.exec.policy); 4977c478bd9Sstevel@tonic-gate strs = 1 + attr_strlen(in->nsc_u.exec.policy); 4987c478bd9Sstevel@tonic-gate out->nsc_u.exec.policy = dest - offset; 4997c478bd9Sstevel@tonic-gate dest += strs; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate attr_strcpy(dest, in->nsc_u.exec.type); 5027c478bd9Sstevel@tonic-gate strs = 1 + attr_strlen(in->nsc_u.exec.type); 5037c478bd9Sstevel@tonic-gate out->nsc_u.exec.type = dest - offset; 5047c478bd9Sstevel@tonic-gate dest += strs; 5057c478bd9Sstevel@tonic-gate 5067c478bd9Sstevel@tonic-gate attr_strcpy(dest, in->nsc_u.exec.res1); 5077c478bd9Sstevel@tonic-gate strs = 1 + attr_strlen(in->nsc_u.exec.res1); 5087c478bd9Sstevel@tonic-gate out->nsc_u.exec.res1 = dest - offset; 5097c478bd9Sstevel@tonic-gate dest += strs; 5107c478bd9Sstevel@tonic-gate 5117c478bd9Sstevel@tonic-gate attr_strcpy(dest, in->nsc_u.exec.res2); 5127c478bd9Sstevel@tonic-gate strs = 1 + attr_strlen(in->nsc_u.exec.res2); 5137c478bd9Sstevel@tonic-gate out->nsc_u.exec.res2 = dest - offset; 5147c478bd9Sstevel@tonic-gate dest += strs; 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate attr_strcpy(dest, in->nsc_u.exec.id); 5177c478bd9Sstevel@tonic-gate strs = 1 + attr_strlen(in->nsc_u.exec.id); 5187c478bd9Sstevel@tonic-gate out->nsc_u.exec.id = dest - offset; 5197c478bd9Sstevel@tonic-gate dest += strs; 5207c478bd9Sstevel@tonic-gate 5217c478bd9Sstevel@tonic-gate attr_strcpy(dest, in->nsc_u.exec.attr); 5227c478bd9Sstevel@tonic-gate out->nsc_u.exec.attr = dest - offset; 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate memcpy(in, out, out->nsc_bufferbytesused); 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate return (retb); 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate void 5307c478bd9Sstevel@tonic-gate getexec_reaper(void) 5317c478bd9Sstevel@tonic-gate { 5327c478bd9Sstevel@tonic-gate nsc_reaper("getexec", nam_hash, ¤t_admin.exec, &db_lock); 5337c478bd9Sstevel@tonic-gate } 534