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 /* 237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <stdio.h> 287c478bd9Sstevel@tonic-gate #include <stdlib.h> 297c478bd9Sstevel@tonic-gate #include <strings.h> 307c478bd9Sstevel@tonic-gate #include <string.h> 317c478bd9Sstevel@tonic-gate #include <unistd.h> 327c478bd9Sstevel@tonic-gate #include <pthread.h> 337c478bd9Sstevel@tonic-gate #include <sys/types.h> 347c478bd9Sstevel@tonic-gate #include <sys/socket.h> 357c478bd9Sstevel@tonic-gate #include <netinet/in.h> 367c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include "ldap_util.h" 397c478bd9Sstevel@tonic-gate #include "ldap_glob.h" 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate static time_t msgtime[MSG_LASTMSG] = {0}; 427c478bd9Sstevel@tonic-gate static time_t msgtimeout = 3600; 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate static pthread_key_t tsdKey; 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate /* 477c478bd9Sstevel@tonic-gate * Log a message to the appropriate place. 487c478bd9Sstevel@tonic-gate */ 497c478bd9Sstevel@tonic-gate void 50*8d0852b7SRichard Lowe logmsg(int msgtype, int priority, const char *fmt, ...) { 517c478bd9Sstevel@tonic-gate va_list ap; 527c478bd9Sstevel@tonic-gate struct timeval tp; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /* 557c478bd9Sstevel@tonic-gate * Only log LOG_INFO priority if 'verbose' is on, or if 567c478bd9Sstevel@tonic-gate * msgtype is MSG_ALWAYS. 577c478bd9Sstevel@tonic-gate */ 587c478bd9Sstevel@tonic-gate if (priority == LOG_INFO && !verbose && msgtype != MSG_ALWAYS) 597c478bd9Sstevel@tonic-gate return; 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate /* Make sure we don't log the same message too often */ 627c478bd9Sstevel@tonic-gate if (msgtype != MSG_NOTIMECHECK && msgtype != MSG_ALWAYS && 637c478bd9Sstevel@tonic-gate msgtype > 0 && msgtype < MSG_LASTMSG && 647c478bd9Sstevel@tonic-gate gettimeofday(&tp, 0) != -1) { 657c478bd9Sstevel@tonic-gate if (tp.tv_sec - msgtime[msgtype] < msgtimeout) 667c478bd9Sstevel@tonic-gate return; 677c478bd9Sstevel@tonic-gate msgtime[msgtype] = tp.tv_sec; 687c478bd9Sstevel@tonic-gate } 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate va_start(ap, fmt); 717c478bd9Sstevel@tonic-gate if (cons == 0) { 727c478bd9Sstevel@tonic-gate vsyslog(priority, fmt, ap); 737c478bd9Sstevel@tonic-gate } else { 747c478bd9Sstevel@tonic-gate int flen = slen(fmt); 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate vfprintf(cons, fmt, ap); 777c478bd9Sstevel@tonic-gate /* 787c478bd9Sstevel@tonic-gate * If the last character in 'fmt' wasn't a '\n', write one 797c478bd9Sstevel@tonic-gate * to the console. 807c478bd9Sstevel@tonic-gate */ 817c478bd9Sstevel@tonic-gate if (flen > 0 && fmt[flen-1] != '\n') 827c478bd9Sstevel@tonic-gate fprintf(cons, "\n"); 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate va_end(ap); 857c478bd9Sstevel@tonic-gate } 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate void 887c478bd9Sstevel@tonic-gate __destroyTsdKey(void *arg) { 897c478bd9Sstevel@tonic-gate __nis_deferred_error_t *defErr = arg; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate if (defErr != 0) { 927c478bd9Sstevel@tonic-gate sfree(defErr->message); 937c478bd9Sstevel@tonic-gate free(defErr); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate static void 987c478bd9Sstevel@tonic-gate __initTsdKey(void) 997c478bd9Sstevel@tonic-gate { 1007c478bd9Sstevel@tonic-gate (void) pthread_key_create(&tsdKey, __destroyTsdKey); 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate #pragma init(__initTsdKey) 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate void 1057c478bd9Sstevel@tonic-gate reportError(int error, char *fmt, ...) { 1067c478bd9Sstevel@tonic-gate __nis_deferred_error_t *defErr = pthread_getspecific(tsdKey); 1077c478bd9Sstevel@tonic-gate int doStore = (defErr == 0); 1087c478bd9Sstevel@tonic-gate char *myself = "reportError"; 1097c478bd9Sstevel@tonic-gate va_list ap; 1107c478bd9Sstevel@tonic-gate __nis_buffer_t b = {0, 0}; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate if (defErr == 0 && (defErr = am(myself, sizeof (*defErr))) == 0) 1137c478bd9Sstevel@tonic-gate return; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate va_start(ap, fmt); 1167c478bd9Sstevel@tonic-gate b.len = vp2buf(myself, &b.buf, b.len, fmt, ap); 1177c478bd9Sstevel@tonic-gate va_end(ap); 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate if (b.len > 0) { 1207c478bd9Sstevel@tonic-gate defErr->error = error; 1217c478bd9Sstevel@tonic-gate defErr->message = b.buf; 1227c478bd9Sstevel@tonic-gate if (doStore) { 1237c478bd9Sstevel@tonic-gate int ret = pthread_setspecific(tsdKey, defErr); 1247c478bd9Sstevel@tonic-gate if (ret != 0) { 1257c478bd9Sstevel@tonic-gate logmsg(MSG_TSDERR, LOG_ERR, 1267c478bd9Sstevel@tonic-gate "%s: pthread_setspecific() => %d", 1277c478bd9Sstevel@tonic-gate myself, ret); 1287c478bd9Sstevel@tonic-gate sfree(b.buf); 1297c478bd9Sstevel@tonic-gate free(defErr); 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate int 1367c478bd9Sstevel@tonic-gate getError(char **message) { 1377c478bd9Sstevel@tonic-gate __nis_deferred_error_t *defErr = pthread_getspecific(tsdKey); 1387c478bd9Sstevel@tonic-gate char *myself = "getError"; 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate if (defErr == 0) { 1417c478bd9Sstevel@tonic-gate if (message != 0) 1427c478bd9Sstevel@tonic-gate *message = sdup(myself, T, "no TSD"); 1437c478bd9Sstevel@tonic-gate return (NPL_TSDERR); 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate if (message != 0) 1477c478bd9Sstevel@tonic-gate *message = sdup(myself, T, defErr->message); 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate return (defErr->error); 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate void 1537c478bd9Sstevel@tonic-gate clearError(void) { 1547c478bd9Sstevel@tonic-gate __nis_deferred_error_t *defErr = pthread_getspecific(tsdKey); 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate if (defErr != 0) { 1577c478bd9Sstevel@tonic-gate sfree(defErr->message); 1587c478bd9Sstevel@tonic-gate defErr->message = 0; 1597c478bd9Sstevel@tonic-gate defErr->error = NPL_NOERROR; 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate void 1647c478bd9Sstevel@tonic-gate logError(int priority) { 1657c478bd9Sstevel@tonic-gate __nis_deferred_error_t *defErr = pthread_getspecific(tsdKey); 1667c478bd9Sstevel@tonic-gate int msgtype; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate if (defErr != 0) { 1697c478bd9Sstevel@tonic-gate switch (defErr->error) { 1707c478bd9Sstevel@tonic-gate case NPL_NOERROR: 1717c478bd9Sstevel@tonic-gate msgtype = MSG_LASTMSG; 1727c478bd9Sstevel@tonic-gate break; 1737c478bd9Sstevel@tonic-gate case NPL_NOMEM: 1747c478bd9Sstevel@tonic-gate msgtype = MSG_NOMEM; 1757c478bd9Sstevel@tonic-gate break; 1767c478bd9Sstevel@tonic-gate case NPL_TSDERR: 1777c478bd9Sstevel@tonic-gate msgtype = MSG_TSDERR; 1787c478bd9Sstevel@tonic-gate break; 1797c478bd9Sstevel@tonic-gate case NPL_BERENCODE: 1807c478bd9Sstevel@tonic-gate case NPL_BERDECODE: 1817c478bd9Sstevel@tonic-gate msgtype = MSG_BER; 1827c478bd9Sstevel@tonic-gate break; 1837c478bd9Sstevel@tonic-gate default: 1847c478bd9Sstevel@tonic-gate msgtype = MSG_LASTMSG; 1857c478bd9Sstevel@tonic-gate break; 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate if (msgtype != MSG_LASTMSG) { 1897c478bd9Sstevel@tonic-gate logmsg(msgtype, priority, defErr->message); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate /* 1957c478bd9Sstevel@tonic-gate * Allocate zero-initialized memory of the specified 'size'. If the 1967c478bd9Sstevel@tonic-gate * allocation fails, log a message and return NULL. Allocation of 1977c478bd9Sstevel@tonic-gate * zero bytes is legal, and returns a NULL pointer. 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate void * 200*8d0852b7SRichard Lowe am(const char *msg, int size) { 2017c478bd9Sstevel@tonic-gate void *p; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate if (size > 0) { 2047c478bd9Sstevel@tonic-gate p = calloc(1, size); 2057c478bd9Sstevel@tonic-gate if (p == 0) { 2067c478bd9Sstevel@tonic-gate if (msg == 0) 2077c478bd9Sstevel@tonic-gate msg = "<unknown>"; 2087c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "%s: calloc(%d) => NULL\n", 2097c478bd9Sstevel@tonic-gate msg, size); 2107c478bd9Sstevel@tonic-gate return (0); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate } else if (size == 0) { 2137c478bd9Sstevel@tonic-gate p = 0; 2147c478bd9Sstevel@tonic-gate } else { 2157c478bd9Sstevel@tonic-gate if (msg == 0) 2167c478bd9Sstevel@tonic-gate msg = "<unknown>"; 2177c478bd9Sstevel@tonic-gate logmsg(MSG_MEMPARAM, LOG_INFO, "%s: size (%d) < 0\n", size); 2187c478bd9Sstevel@tonic-gate exit(-1); 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate return (p); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate /* 2247c478bd9Sstevel@tonic-gate * Return the length of a string, just like strlen(), but don't croak 2257c478bd9Sstevel@tonic-gate * on a NULL pointer. 2267c478bd9Sstevel@tonic-gate */ 2277c478bd9Sstevel@tonic-gate int 228*8d0852b7SRichard Lowe slen(const char *str) { 2297c478bd9Sstevel@tonic-gate return ((str != 0) ? strlen(str) : 0); 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate /* 2337c478bd9Sstevel@tonic-gate * If allocate==0, return 'str'; othewise, duplicate the string just 2347c478bd9Sstevel@tonic-gate * like strdup(), but don't die if 'str' is a NULL pointer. 2357c478bd9Sstevel@tonic-gate */ 2367c478bd9Sstevel@tonic-gate char * 237*8d0852b7SRichard Lowe sdup(const char *msg, int allocate, char *str) { 2387c478bd9Sstevel@tonic-gate char *s; 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate if (!allocate) 2417c478bd9Sstevel@tonic-gate return (str); 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate if (str == 0) { 2447c478bd9Sstevel@tonic-gate s = strdup(""); 2457c478bd9Sstevel@tonic-gate } else { 2467c478bd9Sstevel@tonic-gate s = strdup(str); 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate if (s == 0) { 2497c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "%s: strdup(%d bytes) => NULL\n", 2507c478bd9Sstevel@tonic-gate (msg != 0) ? msg : "<unknown>", slen(str)+1); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate return (s); 2537c478bd9Sstevel@tonic-gate } 2547c478bd9Sstevel@tonic-gate 2557c478bd9Sstevel@tonic-gate /* 2567c478bd9Sstevel@tonic-gate * Concatenate strings like strcat(), but don't expire if passed a 2577c478bd9Sstevel@tonic-gate * NULL pointer or two. If deallocate!=0, free() the input strings. 2587c478bd9Sstevel@tonic-gate */ 2597c478bd9Sstevel@tonic-gate char * 260*8d0852b7SRichard Lowe scat(const char *msg, int deallocate, char *s1, char *s2) { 2617c478bd9Sstevel@tonic-gate char *n; 2627c478bd9Sstevel@tonic-gate int l1 = 0, l2 = 0; 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate if (s1 == 0) { 2657c478bd9Sstevel@tonic-gate n = sdup(msg, T, s2); 2667c478bd9Sstevel@tonic-gate if (deallocate) 2677c478bd9Sstevel@tonic-gate sfree(s2); 2687c478bd9Sstevel@tonic-gate return (n); 2697c478bd9Sstevel@tonic-gate } else if (s2 == 0) { 2707c478bd9Sstevel@tonic-gate n = sdup(msg, T, s1); 2717c478bd9Sstevel@tonic-gate if (deallocate) 2727c478bd9Sstevel@tonic-gate free(s1); 2737c478bd9Sstevel@tonic-gate return (n); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate l1 = strlen(s1); 2777c478bd9Sstevel@tonic-gate l2 = strlen(s2); 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate n = malloc(l1+l2+1); 2807c478bd9Sstevel@tonic-gate if (n != 0) { 2817c478bd9Sstevel@tonic-gate memcpy(n, s1, l1); 2827c478bd9Sstevel@tonic-gate memcpy(&n[l1], s2, l2); 2837c478bd9Sstevel@tonic-gate n[l1+l2] = '\0'; 2847c478bd9Sstevel@tonic-gate } else { 2857c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "%s: malloc(%d) => NULL\n", 2867c478bd9Sstevel@tonic-gate (msg != 0) ? msg : "<unknown>", l1+l2+1); 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate if (deallocate) { 2907c478bd9Sstevel@tonic-gate free(s1); 2917c478bd9Sstevel@tonic-gate free(s2); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate return (n); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate /* For debugging */ 2987c478bd9Sstevel@tonic-gate static void *PTR = 0; 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate /* 3017c478bd9Sstevel@tonic-gate * Counters for memory errors. Note that we don't protect access, 3027c478bd9Sstevel@tonic-gate * so the values aren't entirely reliable in an MT application. 3037c478bd9Sstevel@tonic-gate */ 3047c478bd9Sstevel@tonic-gate ulong_t numMisaligned = 0; 3057c478bd9Sstevel@tonic-gate ulong_t numNotActive = 0; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate /* free() the input, but don't pass away if it's NULL */ 3087c478bd9Sstevel@tonic-gate void 3097c478bd9Sstevel@tonic-gate sfree(void *ptr) { 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate /* NULL pointer OK */ 3127c478bd9Sstevel@tonic-gate if (ptr == 0) 3137c478bd9Sstevel@tonic-gate return; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate /* 3167c478bd9Sstevel@tonic-gate * For use in the debugger, when we need to detect free of a 3177c478bd9Sstevel@tonic-gate * certain address. 3187c478bd9Sstevel@tonic-gate */ 3197c478bd9Sstevel@tonic-gate if (ptr == PTR) 3207c478bd9Sstevel@tonic-gate abort(); 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* 3237c478bd9Sstevel@tonic-gate * All addresses returned by malloc() and friends are "suitably 3247c478bd9Sstevel@tonic-gate * aligned for any use", so they should fall on eight-byte boundaries. 3257c478bd9Sstevel@tonic-gate */ 3267c478bd9Sstevel@tonic-gate if (((unsigned long)ptr % 8) != 0) { 3277c478bd9Sstevel@tonic-gate numMisaligned++; 3287c478bd9Sstevel@tonic-gate return; 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate #ifdef NISDB_LDAP_DEBUG 3327c478bd9Sstevel@tonic-gate /* 3337c478bd9Sstevel@tonic-gate * Malloc:ed memory should have the length (four bytes), starting 3347c478bd9Sstevel@tonic-gate * eight bytes before the block, and with the least-significant 3357c478bd9Sstevel@tonic-gate * bit set. 3367c478bd9Sstevel@tonic-gate */ 3377c478bd9Sstevel@tonic-gate if ((((uint_t *)ptr)[-2] & 0x1) == 0) { 3387c478bd9Sstevel@tonic-gate numNotActive++; 3397c478bd9Sstevel@tonic-gate return; 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate #endif /* NISDB_LDAP_DEBUG */ 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate /* Finally, we believe it's OK to free() the pointer */ 3447c478bd9Sstevel@tonic-gate free(ptr); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate /* 3487c478bd9Sstevel@tonic-gate * If a __nis_single_value_t represents a string, the length count may or may 3497c478bd9Sstevel@tonic-gate * not include a concluding NUL. Hence this function, which returns the last 3507c478bd9Sstevel@tonic-gate * non-NUL character of the value. 3517c478bd9Sstevel@tonic-gate */ 3527c478bd9Sstevel@tonic-gate char 3537c478bd9Sstevel@tonic-gate lastChar(__nis_single_value_t *v) { 3547c478bd9Sstevel@tonic-gate char *s; 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate if (v == 0 || v->value == 0 || v->length < 2) 3577c478bd9Sstevel@tonic-gate return ('\0'); 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate s = v->value; 3607c478bd9Sstevel@tonic-gate if (s[v->length - 1] != '\0') 3617c478bd9Sstevel@tonic-gate return (s[v->length - 1]); 3627c478bd9Sstevel@tonic-gate else 3637c478bd9Sstevel@tonic-gate return (s[v->length - 2]); 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate void * 3677c478bd9Sstevel@tonic-gate appendString2SingleVal(char *str, __nis_single_value_t *v, int *newLen) { 3687c478bd9Sstevel@tonic-gate void *s; 3697c478bd9Sstevel@tonic-gate int l, nl; 3707c478bd9Sstevel@tonic-gate char *myself = "appendString2SingleVal"; 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate if (v == 0 || v->length < 0) 3737c478bd9Sstevel@tonic-gate return (0); 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate /* 3767c478bd9Sstevel@tonic-gate * If 'str' is NULL or empty, just return NULL so that the caller 3777c478bd9Sstevel@tonic-gate * does nothing. 3787c478bd9Sstevel@tonic-gate */ 3797c478bd9Sstevel@tonic-gate l = slen(str); 3807c478bd9Sstevel@tonic-gate if (l <= 0) 3817c478bd9Sstevel@tonic-gate return (0); 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate s = am(myself, (nl = l + v->length) + 1); 3847c478bd9Sstevel@tonic-gate if (s == 0) { 3857c478bd9Sstevel@tonic-gate /* Caller does nothing; let's hope for the best... */ 3867c478bd9Sstevel@tonic-gate return (0); 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate if (v->value != 0) 3907c478bd9Sstevel@tonic-gate memcpy(s, v->value, v->length); 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate memcpy(&(((char *)s)[v->length]), str, l); 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate if (newLen != 0) 3957c478bd9Sstevel@tonic-gate *newLen = nl; 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate return (s); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate /* 4027c478bd9Sstevel@tonic-gate * Do the equivalent of a strcmp() between a string and a string-valued 4037c478bd9Sstevel@tonic-gate * __nis_single_value_t. 4047c478bd9Sstevel@tonic-gate */ 4057c478bd9Sstevel@tonic-gate int 4067c478bd9Sstevel@tonic-gate scmp(char *s, __nis_single_value_t *v) { 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate if (s == 0) 4097c478bd9Sstevel@tonic-gate return (1); 4107c478bd9Sstevel@tonic-gate else if (v == 0 || v->value == 0 || v->length <= 0) 4117c478bd9Sstevel@tonic-gate return (-1); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate return (strncmp(s, v->value, v->length)); 4147c478bd9Sstevel@tonic-gate } 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate /* 4177c478bd9Sstevel@tonic-gate * Do the equivalent of a strcasecmp() between a string and a string-valued 4187c478bd9Sstevel@tonic-gate * __nis_single_value_t. 4197c478bd9Sstevel@tonic-gate */ 4207c478bd9Sstevel@tonic-gate int 4217c478bd9Sstevel@tonic-gate scasecmp(char *s, __nis_single_value_t *v) { 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if (s == 0) 4247c478bd9Sstevel@tonic-gate return (1); 4257c478bd9Sstevel@tonic-gate else if (v == 0 || v->value == 0 || v->length <= 0) 4267c478bd9Sstevel@tonic-gate return (-1); 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate return (strncasecmp(s, v->value, v->length)); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate #define STDBUFSIZE 81 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate /* 4347c478bd9Sstevel@tonic-gate * vsprintf the 'fmt' and 'ap' to a buffer, then concatenate the 4357c478bd9Sstevel@tonic-gate * result to '*buf'. 4367c478bd9Sstevel@tonic-gate */ 4377c478bd9Sstevel@tonic-gate int 438*8d0852b7SRichard Lowe vp2buf(const char *msg, char **buf, int buflen, const char *fmt, va_list ap) { 4397c478bd9Sstevel@tonic-gate char *newbuf = am(msg, STDBUFSIZE); 4407c478bd9Sstevel@tonic-gate int size = 0; 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate if (newbuf == 0) 4437c478bd9Sstevel@tonic-gate return (0); 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate if (buf == 0 || buflen < 0 || fmt == 0) { 4467c478bd9Sstevel@tonic-gate free(newbuf); 4477c478bd9Sstevel@tonic-gate return (0); 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate /* Find out how large the new buffer needs to be */ 4517c478bd9Sstevel@tonic-gate size = vsnprintf(newbuf, STDBUFSIZE, fmt, ap); 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate if (size > STDBUFSIZE) { 4547c478bd9Sstevel@tonic-gate free(newbuf); 4557c478bd9Sstevel@tonic-gate newbuf = am(msg, size+1); 4567c478bd9Sstevel@tonic-gate if (newbuf == 0) 4577c478bd9Sstevel@tonic-gate return (0); 4587c478bd9Sstevel@tonic-gate size = vsnprintf(newbuf, size+1, fmt, ap); 4597c478bd9Sstevel@tonic-gate } 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate *buf = scat(msg, T, *buf, newbuf); 4627c478bd9Sstevel@tonic-gate /* Don't count the NUL. This enables us to concatenate correctly */ 4637c478bd9Sstevel@tonic-gate buflen += size; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate return (buflen); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate /* Generic print buffer */ 4697c478bd9Sstevel@tonic-gate __nis_buffer_t pb = {0, 0}; 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate /* sprintf to the generic __nis_buffer_t */ 4727c478bd9Sstevel@tonic-gate void 4737c478bd9Sstevel@tonic-gate p2buf(char *msg, char *fmt, ...) { 4747c478bd9Sstevel@tonic-gate va_list ap; 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate va_start(ap, fmt); 4777c478bd9Sstevel@tonic-gate pb.len = vp2buf(msg, &pb.buf, pb.len, fmt, ap); 4787c478bd9Sstevel@tonic-gate va_end(ap); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate /* sprintf to the specified __nis_buffer_t */ 4827c478bd9Sstevel@tonic-gate void 483*8d0852b7SRichard Lowe bp2buf(const char *msg, __nis_buffer_t *b, const char *fmt, ...) { 4847c478bd9Sstevel@tonic-gate va_list ap; 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate va_start(ap, fmt); 4877c478bd9Sstevel@tonic-gate b->len = vp2buf(msg, &b->buf, b->len, fmt, ap); 4887c478bd9Sstevel@tonic-gate va_end(ap); 4897c478bd9Sstevel@tonic-gate } 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate /* Copy 'buf' to the specified __nis_buffer_t */ 4927c478bd9Sstevel@tonic-gate void 493*8d0852b7SRichard Lowe bc2buf(const char *msg, void *buf, int len, __nis_buffer_t *b) { 4947c478bd9Sstevel@tonic-gate void *new; 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* 4977c478bd9Sstevel@tonic-gate * Make buffer one byte larger than the lenghts indicate. This 4987c478bd9Sstevel@tonic-gate * gives us room to append a NUL, so that we can mix string and 4997c478bd9Sstevel@tonic-gate * non-string copies into the buffer, and still end up with 5007c478bd9Sstevel@tonic-gate * something that can be sent to printf(), strcat(), etc. 5017c478bd9Sstevel@tonic-gate */ 5027c478bd9Sstevel@tonic-gate new = realloc(b->buf, b->len+len+1); 5037c478bd9Sstevel@tonic-gate if (new != 0) { 5047c478bd9Sstevel@tonic-gate b->buf = new; 5057c478bd9Sstevel@tonic-gate memcpy(&(b->buf[b->len]), buf, len); 5067c478bd9Sstevel@tonic-gate b->len += len; 5077c478bd9Sstevel@tonic-gate /* Put a NUL at the end, just in case we printf() */ 5087c478bd9Sstevel@tonic-gate if (b->len > 0 && b->buf[b->len-1] != '\0') 5097c478bd9Sstevel@tonic-gate b->buf[b->len] = '\0'; 5107c478bd9Sstevel@tonic-gate } else { 5117c478bd9Sstevel@tonic-gate logmsg(MSG_NOMEM, LOG_ERR, "%s: realloc(%d) => NULL\n", 5127c478bd9Sstevel@tonic-gate (msg != 0) ? msg : "<unknown", b->len+len); 5137c478bd9Sstevel@tonic-gate } 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate /* Like bc2buf(), but remove any trailing NUL bytes */ 5177c478bd9Sstevel@tonic-gate void 518*8d0852b7SRichard Lowe sbc2buf(const char *msg, void *buf, int len, __nis_buffer_t *b) { 5197c478bd9Sstevel@tonic-gate if (buf == 0 || len <= 0 || b == 0) 5207c478bd9Sstevel@tonic-gate return; 5217c478bd9Sstevel@tonic-gate /* Snip off trailing NULs */ 5227c478bd9Sstevel@tonic-gate while (len > 0 && ((char *)buf)[len-1] == '\0') 5237c478bd9Sstevel@tonic-gate len--; 5247c478bd9Sstevel@tonic-gate if (len <= 0) 5257c478bd9Sstevel@tonic-gate return; 5267c478bd9Sstevel@tonic-gate bc2buf(msg, buf, len, b); 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate /* Copy 'buf' to the generic __nis_buffer_t */ 5307c478bd9Sstevel@tonic-gate void 5317c478bd9Sstevel@tonic-gate c2buf(char *msg, void *buf, int len) { 5327c478bd9Sstevel@tonic-gate bc2buf(msg, buf, len, &pb); 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate /* Like c2buf(), but remove trailing NUL bytes */ 5367c478bd9Sstevel@tonic-gate void 5377c478bd9Sstevel@tonic-gate sc2buf(char *msg, void *buf, int len) { 5387c478bd9Sstevel@tonic-gate sbc2buf(msg, buf, len, &pb); 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate /* How many times we try write(2) if it fails */ 5427c478bd9Sstevel@tonic-gate #define MAXTRY 10 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate /* Output the generic __nis_buffer_t to stdout */ 5457c478bd9Sstevel@tonic-gate void 5467c478bd9Sstevel@tonic-gate printbuf(void) { 5477c478bd9Sstevel@tonic-gate int maxtry = MAXTRY, len = pb.len; 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate if (pb.buf != 0) { 5507c478bd9Sstevel@tonic-gate int tmp; 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate while (len > 0 && maxtry > 0) { 5537c478bd9Sstevel@tonic-gate tmp = write(1, pb.buf, len); 5547c478bd9Sstevel@tonic-gate if (tmp < 0) 5557c478bd9Sstevel@tonic-gate break; 5567c478bd9Sstevel@tonic-gate len -= tmp; 5577c478bd9Sstevel@tonic-gate if (tmp > 0) 5587c478bd9Sstevel@tonic-gate maxtry = MAXTRY; 5597c478bd9Sstevel@tonic-gate else 5607c478bd9Sstevel@tonic-gate maxtry--; 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate free(pb.buf); 5637c478bd9Sstevel@tonic-gate pb.buf = 0; 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate pb.len = 0; 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate void * 5697c478bd9Sstevel@tonic-gate extendArray(void *array, int newsize) { 5707c478bd9Sstevel@tonic-gate void *new = realloc(array, newsize); 5717c478bd9Sstevel@tonic-gate if (new == 0) 5727c478bd9Sstevel@tonic-gate sfree(array); 5737c478bd9Sstevel@tonic-gate return (new); 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate /* 5777c478bd9Sstevel@tonic-gate * Determine if the given string is an IP address (IPv4 or IPv6). 5787c478bd9Sstevel@tonic-gate * If so, it converts it to the format as required by rfc2307bis 5797c478bd9Sstevel@tonic-gate * and *newaddr will point to the new Address. 5807c478bd9Sstevel@tonic-gate * 5817c478bd9Sstevel@tonic-gate * Returns -2 : error 5827c478bd9Sstevel@tonic-gate * -1 : not an IP address 5837c478bd9Sstevel@tonic-gate * 0 : IP address not supported by rfc2307bis 5847c478bd9Sstevel@tonic-gate * AF_INET : IPv4 5857c478bd9Sstevel@tonic-gate * AF_INET6 : IPv6 5867c478bd9Sstevel@tonic-gate */ 5877c478bd9Sstevel@tonic-gate int 5887c478bd9Sstevel@tonic-gate checkIPaddress(char *addr, int len, char **newaddr) { 5897c478bd9Sstevel@tonic-gate ipaddr_t addr_ipv4; 5907c478bd9Sstevel@tonic-gate in6_addr_t addr_ipv6; 5917c478bd9Sstevel@tonic-gate char *buffer; 5927c478bd9Sstevel@tonic-gate int s, e; 5937c478bd9Sstevel@tonic-gate char *myself = "checkIPaddress"; 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate /* skip leading whitespaces */ 5967c478bd9Sstevel@tonic-gate for (s = 0; (s < len) && (addr[s] == ' ' || addr[s] == '\t'); s++); 5977c478bd9Sstevel@tonic-gate if (s >= len) 5987c478bd9Sstevel@tonic-gate return (-1); 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate /* skip trailing whitespaces */ 6017c478bd9Sstevel@tonic-gate for (e = len - 1; (e > s) && (addr[e] == ' ' || addr[e] == '\t'); e--); 6027c478bd9Sstevel@tonic-gate if (s == e) 6037c478bd9Sstevel@tonic-gate return (-1); 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate /* adjust len */ 6067c478bd9Sstevel@tonic-gate len = e - s + 1; 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate if ((buffer = am(myself, len + 1)) == 0) 6097c478bd9Sstevel@tonic-gate return (-2); 6107c478bd9Sstevel@tonic-gate (void) memcpy(buffer, addr + s, len); 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET6, buffer, &addr_ipv6) == 1) { 6137c478bd9Sstevel@tonic-gate sfree(buffer); 6147c478bd9Sstevel@tonic-gate /* 6157c478bd9Sstevel@tonic-gate * IPv4-compatible IPv6 address and IPv4-mapped 6167c478bd9Sstevel@tonic-gate * IPv6 addresses not allowed by rfc2307bis 6177c478bd9Sstevel@tonic-gate */ 6187c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_V4COMPAT(&addr_ipv6)) 6197c478bd9Sstevel@tonic-gate return (0); 6207c478bd9Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(&addr_ipv6)) 6217c478bd9Sstevel@tonic-gate return (0); 6227c478bd9Sstevel@tonic-gate if (newaddr == 0) 6237c478bd9Sstevel@tonic-gate return (AF_INET6); 6247c478bd9Sstevel@tonic-gate if ((*newaddr = am(myself, INET6_ADDRSTRLEN)) == 0) 6257c478bd9Sstevel@tonic-gate return (-2); 6267c478bd9Sstevel@tonic-gate if (inet_ntop(AF_INET6, &addr_ipv6, *newaddr, INET6_ADDRSTRLEN)) 6277c478bd9Sstevel@tonic-gate return (AF_INET6); 6287c478bd9Sstevel@tonic-gate sfree(*newaddr); 6297c478bd9Sstevel@tonic-gate return (-2); 6307c478bd9Sstevel@tonic-gate } 6317c478bd9Sstevel@tonic-gate 6327c478bd9Sstevel@tonic-gate if (inet_pton(AF_INET, buffer, &addr_ipv4) == 1) { 6337c478bd9Sstevel@tonic-gate sfree(buffer); 6347c478bd9Sstevel@tonic-gate if (newaddr == 0) 6357c478bd9Sstevel@tonic-gate return (AF_INET); 6367c478bd9Sstevel@tonic-gate if ((*newaddr = am(myself, INET_ADDRSTRLEN)) == 0) 6377c478bd9Sstevel@tonic-gate return (-2); 6387c478bd9Sstevel@tonic-gate if (inet_ntop(AF_INET, &addr_ipv4, *newaddr, INET_ADDRSTRLEN)) 6397c478bd9Sstevel@tonic-gate return (AF_INET); 6407c478bd9Sstevel@tonic-gate sfree(*newaddr); 6417c478bd9Sstevel@tonic-gate return (-2); 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate sfree(buffer); 6457c478bd9Sstevel@tonic-gate return (-1); 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate int 6497c478bd9Sstevel@tonic-gate sstrncmp(const char *s1, const char *s2, int n) { 6507c478bd9Sstevel@tonic-gate if (s1 == 0 && s2 == 0) 6517c478bd9Sstevel@tonic-gate return (0); 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate if (s1 == 0) 6547c478bd9Sstevel@tonic-gate return (1); 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate if (s2 == 0) 6577c478bd9Sstevel@tonic-gate return (-1); 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate return (strncmp(s1, s2, n)); 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate /* 6637c478bd9Sstevel@tonic-gate * Does the following: 6647c478bd9Sstevel@tonic-gate * - Trims leading and trailing whitespaces 6657c478bd9Sstevel@tonic-gate * - Collapses two or more whitespaces into one space 6667c478bd9Sstevel@tonic-gate * - Converts all whitespaces into spaces 6677c478bd9Sstevel@tonic-gate * - At entrance, *len contains length of str 6687c478bd9Sstevel@tonic-gate * - At exit, *len will contain length of the return string 6697c478bd9Sstevel@tonic-gate * - In case of mem alloc failure, *len should be ignored 6707c478bd9Sstevel@tonic-gate */ 6717c478bd9Sstevel@tonic-gate char * 6727c478bd9Sstevel@tonic-gate trimWhiteSpaces(char *str, int *len, int deallocate) { 6737c478bd9Sstevel@tonic-gate char *ostr; 6747c478bd9Sstevel@tonic-gate int olen = 0; 6757c478bd9Sstevel@tonic-gate int first = 1, i; 6767c478bd9Sstevel@tonic-gate char *myself = "trimWhiteSpaces"; 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate if ((ostr = am(myself, *len + 1)) == 0) { 6797c478bd9Sstevel@tonic-gate if (deallocate) 6807c478bd9Sstevel@tonic-gate sfree(str); 6817c478bd9Sstevel@tonic-gate *len = 0; 6827c478bd9Sstevel@tonic-gate return (0); 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate /* Skip leading whitespaces */ 6867c478bd9Sstevel@tonic-gate for (i = 0; i < *len && (str[i] == ' ' || str[i] == '\t'); i++); 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate /* Collapse multiple whitespaces into one */ 6897c478bd9Sstevel@tonic-gate for (; i < *len; i++) { 6907c478bd9Sstevel@tonic-gate if (str[i] == ' ' || str[i] == '\t') { 6917c478bd9Sstevel@tonic-gate if (first) { 6927c478bd9Sstevel@tonic-gate first = 0; 6937c478bd9Sstevel@tonic-gate ostr[olen++] = ' '; 6947c478bd9Sstevel@tonic-gate } 6957c478bd9Sstevel@tonic-gate continue; 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate first = 1; 6987c478bd9Sstevel@tonic-gate ostr[olen++] = str[i]; 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate /* Handle the trailing whitespace if any */ 7027c478bd9Sstevel@tonic-gate if (olen && ostr[olen - 1] == ' ') { 7037c478bd9Sstevel@tonic-gate olen--; 7047c478bd9Sstevel@tonic-gate ostr[olen] = 0; 7057c478bd9Sstevel@tonic-gate } 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate if (deallocate) 7087c478bd9Sstevel@tonic-gate sfree(str); 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate *len = olen; 7117c478bd9Sstevel@tonic-gate return (ostr); 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate /* 7157c478bd9Sstevel@tonic-gate * Escapes special characters in DN using the list from RFC 2253 7167c478bd9Sstevel@tonic-gate */ 7177c478bd9Sstevel@tonic-gate int 7187c478bd9Sstevel@tonic-gate escapeSpecialChars(__nis_value_t *val) { 7197c478bd9Sstevel@tonic-gate int i, j, k, count; 7207c478bd9Sstevel@tonic-gate char *newval, *s; 7217c478bd9Sstevel@tonic-gate char *myself = "escapeSpecialChars"; 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate /* Assume val is always non NULL */ 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate for (i = 0; i < val->numVals; i++) { 7267c478bd9Sstevel@tonic-gate /* 7277c478bd9Sstevel@tonic-gate * Count the special characters in value to determine 7287c478bd9Sstevel@tonic-gate * the length for the new value 7297c478bd9Sstevel@tonic-gate */ 7307c478bd9Sstevel@tonic-gate s = val->val[i].value; 7317c478bd9Sstevel@tonic-gate for (j = 0, count = 0; j < val->val[i].length; j++, s++) { 7327c478bd9Sstevel@tonic-gate if (*s == '#' || *s == ',' || *s == '+' || *s == '"' || 7337c478bd9Sstevel@tonic-gate *s == '\\' || *s == '<' || *s == '>' || *s == ';') 7347c478bd9Sstevel@tonic-gate count++; 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate if (count == 0) 7377c478bd9Sstevel@tonic-gate continue; 7387c478bd9Sstevel@tonic-gate 7397c478bd9Sstevel@tonic-gate if ((newval = am(myself, val->val[i].length + count + 1)) == 0) 7407c478bd9Sstevel@tonic-gate return (-1); 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate /* Escape the special characters using '\\' */ 7437c478bd9Sstevel@tonic-gate s = val->val[i].value; 7447c478bd9Sstevel@tonic-gate for (j = 0, k = 0; j < val->val[i].length; j++, k++, s++) { 7457c478bd9Sstevel@tonic-gate if (*s == '#' || *s == ',' || *s == '+' || *s == '"' || 7467c478bd9Sstevel@tonic-gate *s == '\\' || *s == '<' || *s == '>' || *s == ';') 7477c478bd9Sstevel@tonic-gate newval[k++] = '\\'; 7487c478bd9Sstevel@tonic-gate newval[k] = *s; 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate sfree(val->val[i].value); 7527c478bd9Sstevel@tonic-gate val->val[i].value = newval; 7537c478bd9Sstevel@tonic-gate val->val[i].length += count; 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate return (1); 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate /* 7607c478bd9Sstevel@tonic-gate * Remove escape characters from DN returned by LDAP server 7617c478bd9Sstevel@tonic-gate */ 7627c478bd9Sstevel@tonic-gate void 7637c478bd9Sstevel@tonic-gate removeEscapeChars(__nis_value_t *val) { 7647c478bd9Sstevel@tonic-gate int i; 7657c478bd9Sstevel@tonic-gate char *s, *d, *end; 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate for (i = 0; i < val->numVals; i++) { 7697c478bd9Sstevel@tonic-gate s = val->val[i].value; 7707c478bd9Sstevel@tonic-gate end = s + val->val[i].length; 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate /* 7737c478bd9Sstevel@tonic-gate * This function is called frequently and for most entries 7747c478bd9Sstevel@tonic-gate * there will be no escapes. Process rapidly up to first escape. 7757c478bd9Sstevel@tonic-gate */ 7767c478bd9Sstevel@tonic-gate for (d = s; s < end; s++, d++) { 7777c478bd9Sstevel@tonic-gate if (*s == '\\') 7787c478bd9Sstevel@tonic-gate break; 7797c478bd9Sstevel@tonic-gate } 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate /* 7827c478bd9Sstevel@tonic-gate * Reached the end, in which case will not go into loop, 7837c478bd9Sstevel@tonic-gate * or found an escape and now have to start moving data. 7847c478bd9Sstevel@tonic-gate */ 7857c478bd9Sstevel@tonic-gate for (; s < end; s++) { 7867c478bd9Sstevel@tonic-gate if (*s == '\\') { 7877c478bd9Sstevel@tonic-gate val->val[i].length--; 7887c478bd9Sstevel@tonic-gate /* 7897c478bd9Sstevel@tonic-gate * Next character gets coppied without being 7907c478bd9Sstevel@tonic-gate * checked 7917c478bd9Sstevel@tonic-gate */ 7927c478bd9Sstevel@tonic-gate s++; 7937c478bd9Sstevel@tonic-gate if (s >= end) 7947c478bd9Sstevel@tonic-gate break; 7957c478bd9Sstevel@tonic-gate } 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate *d = *s; 7987c478bd9Sstevel@tonic-gate d++; 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate } 802