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
5004388ebScasper * Common Development and Distribution License (the "License").
6004388ebScasper * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
226dd84139Sdjl * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
24*655967abSMarcel Telka */
25*655967abSMarcel Telka /*
26*655967abSMarcel Telka * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
27*655967abSMarcel Telka */
28*655967abSMarcel Telka
29*655967abSMarcel Telka /*
307c478bd9Sstevel@tonic-gate * Common code and structures used by name-service-switch "files" backends.
317c478bd9Sstevel@tonic-gate */
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate /*
347c478bd9Sstevel@tonic-gate * An implementation that used mmap() sensibly would be a wonderful thing,
357c478bd9Sstevel@tonic-gate * but this here is just yer standard fgets() thang.
367c478bd9Sstevel@tonic-gate */
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate #include "files_common.h"
397c478bd9Sstevel@tonic-gate #include <stdio.h>
407c478bd9Sstevel@tonic-gate #include <stdlib.h>
417c478bd9Sstevel@tonic-gate #include <string.h>
427c478bd9Sstevel@tonic-gate #include <ctype.h>
437c478bd9Sstevel@tonic-gate #include <fcntl.h>
447c478bd9Sstevel@tonic-gate #include <poll.h>
457c478bd9Sstevel@tonic-gate #include <unistd.h>
467c478bd9Sstevel@tonic-gate #include <sys/stat.h>
47cb5caa98Sdjl #include <sys/mman.h>
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate /*ARGSUSED*/
507c478bd9Sstevel@tonic-gate nss_status_t
_nss_files_setent(be,dummy)517c478bd9Sstevel@tonic-gate _nss_files_setent(be, dummy)
527c478bd9Sstevel@tonic-gate files_backend_ptr_t be;
537c478bd9Sstevel@tonic-gate void *dummy;
547c478bd9Sstevel@tonic-gate {
557c478bd9Sstevel@tonic-gate if (be->f == 0) {
567c478bd9Sstevel@tonic-gate if (be->filename == 0) {
577c478bd9Sstevel@tonic-gate /* Backend isn't initialized properly? */
587c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL);
597c478bd9Sstevel@tonic-gate }
60004388ebScasper if ((be->f = fopen(be->filename, "rF")) == 0) {
617c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL);
627c478bd9Sstevel@tonic-gate }
637c478bd9Sstevel@tonic-gate } else {
64004388ebScasper rewind(be->f);
657c478bd9Sstevel@tonic-gate }
667c478bd9Sstevel@tonic-gate return (NSS_SUCCESS);
677c478bd9Sstevel@tonic-gate }
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate /*ARGSUSED*/
707c478bd9Sstevel@tonic-gate nss_status_t
_nss_files_endent(be,dummy)717c478bd9Sstevel@tonic-gate _nss_files_endent(be, dummy)
727c478bd9Sstevel@tonic-gate files_backend_ptr_t be;
737c478bd9Sstevel@tonic-gate void *dummy;
747c478bd9Sstevel@tonic-gate {
757c478bd9Sstevel@tonic-gate if (be->f != 0) {
76cb5caa98Sdjl (void) fclose(be->f);
777c478bd9Sstevel@tonic-gate be->f = 0;
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate if (be->buf != 0) {
807c478bd9Sstevel@tonic-gate free(be->buf);
817c478bd9Sstevel@tonic-gate be->buf = 0;
827c478bd9Sstevel@tonic-gate }
837c478bd9Sstevel@tonic-gate return (NSS_SUCCESS);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate * This routine reads a line, including the processing of continuation
887c478bd9Sstevel@tonic-gate * characters. It always leaves (or inserts) \n\0 at the end of the line.
897c478bd9Sstevel@tonic-gate * It returns the length of the line read, excluding the \n\0. Who's idea
907c478bd9Sstevel@tonic-gate * was this?
917c478bd9Sstevel@tonic-gate * Returns -1 on EOF.
927c478bd9Sstevel@tonic-gate *
937c478bd9Sstevel@tonic-gate * Note that since each concurrent call to _nss_files_read_line has
947c478bd9Sstevel@tonic-gate * it's own FILE pointer, we can use getc_unlocked w/o difficulties,
957c478bd9Sstevel@tonic-gate * a substantial performance win.
967c478bd9Sstevel@tonic-gate */
977c478bd9Sstevel@tonic-gate int
_nss_files_read_line(f,buffer,buflen)987c478bd9Sstevel@tonic-gate _nss_files_read_line(f, buffer, buflen)
99004388ebScasper FILE *f;
1007c478bd9Sstevel@tonic-gate char *buffer;
1017c478bd9Sstevel@tonic-gate int buflen;
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate int linelen; /* 1st unused slot in buffer */
1047c478bd9Sstevel@tonic-gate int c;
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate /*CONSTCOND*/
1077c478bd9Sstevel@tonic-gate while (1) {
1087c478bd9Sstevel@tonic-gate linelen = 0;
1097c478bd9Sstevel@tonic-gate while (linelen < buflen - 1) { /* "- 1" saves room for \n\0 */
110004388ebScasper switch (c = getc_unlocked(f)) {
1117c478bd9Sstevel@tonic-gate case EOF:
1127c478bd9Sstevel@tonic-gate if (linelen == 0 ||
1137c478bd9Sstevel@tonic-gate buffer[linelen - 1] == '\\') {
1147c478bd9Sstevel@tonic-gate return (-1);
1157c478bd9Sstevel@tonic-gate } else {
1167c478bd9Sstevel@tonic-gate buffer[linelen ] = '\n';
1177c478bd9Sstevel@tonic-gate buffer[linelen + 1] = '\0';
1187c478bd9Sstevel@tonic-gate return (linelen);
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate case '\n':
1217c478bd9Sstevel@tonic-gate if (linelen > 0 &&
1227c478bd9Sstevel@tonic-gate buffer[linelen - 1] == '\\') {
1237c478bd9Sstevel@tonic-gate --linelen; /* remove the '\\' */
1247c478bd9Sstevel@tonic-gate } else {
1257c478bd9Sstevel@tonic-gate buffer[linelen ] = '\n';
1267c478bd9Sstevel@tonic-gate buffer[linelen + 1] = '\0';
1277c478bd9Sstevel@tonic-gate return (linelen);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate break;
1307c478bd9Sstevel@tonic-gate default:
1317c478bd9Sstevel@tonic-gate buffer[linelen++] = c;
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate /* Buffer overflow -- eat rest of line and loop again */
1357c478bd9Sstevel@tonic-gate /* ===> Should syslog() */
1367c478bd9Sstevel@tonic-gate do {
137004388ebScasper c = getc_unlocked(f);
1387c478bd9Sstevel@tonic-gate if (c == EOF) {
1397c478bd9Sstevel@tonic-gate return (-1);
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate } while (c != '\n');
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate /*NOTREACHED*/
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate /*
1477c478bd9Sstevel@tonic-gate * used only for getgroupbymem() now.
1487c478bd9Sstevel@tonic-gate */
1497c478bd9Sstevel@tonic-gate nss_status_t
_nss_files_do_all(be,args,filter,func)1507c478bd9Sstevel@tonic-gate _nss_files_do_all(be, args, filter, func)
1517c478bd9Sstevel@tonic-gate files_backend_ptr_t be;
1527c478bd9Sstevel@tonic-gate void *args;
1537c478bd9Sstevel@tonic-gate const char *filter;
1547c478bd9Sstevel@tonic-gate files_do_all_func_t func;
1557c478bd9Sstevel@tonic-gate {
1566dd84139Sdjl long grlen;
1577c478bd9Sstevel@tonic-gate char *buffer;
1587c478bd9Sstevel@tonic-gate int buflen;
1597c478bd9Sstevel@tonic-gate nss_status_t res;
1607c478bd9Sstevel@tonic-gate
1616dd84139Sdjl if (be->buf == 0) {
1626dd84139Sdjl if ((grlen = sysconf(_SC_GETGR_R_SIZE_MAX)) > 0)
1636dd84139Sdjl be->minbuf = grlen;
1646dd84139Sdjl if ((be->buf = malloc(be->minbuf)) == 0)
1657c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL);
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate buffer = be->buf;
1687c478bd9Sstevel@tonic-gate buflen = be->minbuf;
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate if ((res = _nss_files_setent(be, 0)) != NSS_SUCCESS) {
1717c478bd9Sstevel@tonic-gate return (res);
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND;
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate do {
1777c478bd9Sstevel@tonic-gate int linelen;
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate if ((linelen = _nss_files_read_line(be->f, buffer,
1807c478bd9Sstevel@tonic-gate buflen)) < 0) {
1817c478bd9Sstevel@tonic-gate /* End of file */
1827c478bd9Sstevel@tonic-gate break;
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate if (filter != 0 && strstr(buffer, filter) == 0) {
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate * Optimization: if the entry doesn't contain the
1877c478bd9Sstevel@tonic-gate * filter string then it can't be the entry we want,
1887c478bd9Sstevel@tonic-gate * so don't bother looking more closely at it.
1897c478bd9Sstevel@tonic-gate */
1907c478bd9Sstevel@tonic-gate continue;
1917c478bd9Sstevel@tonic-gate }
1927c478bd9Sstevel@tonic-gate res = (*func)(buffer, linelen, args);
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate } while (res == NSS_NOTFOUND);
1957c478bd9Sstevel@tonic-gate
196cb5caa98Sdjl (void) _nss_files_endent(be, 0);
1977c478bd9Sstevel@tonic-gate return (res);
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate /*
2017c478bd9Sstevel@tonic-gate * Could implement this as an iterator function on top of _nss_files_do_all(),
2027c478bd9Sstevel@tonic-gate * but the shared code is small enough that it'd be pretty silly.
2037c478bd9Sstevel@tonic-gate */
2047c478bd9Sstevel@tonic-gate nss_status_t
_nss_files_XY_all(be,args,netdb,filter,check)2057c478bd9Sstevel@tonic-gate _nss_files_XY_all(be, args, netdb, filter, check)
2067c478bd9Sstevel@tonic-gate files_backend_ptr_t be;
2077c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args;
2087c478bd9Sstevel@tonic-gate int netdb; /* whether it uses netdb */
2097c478bd9Sstevel@tonic-gate /* format or not */
2107c478bd9Sstevel@tonic-gate const char *filter; /* advisory, to speed up */
2117c478bd9Sstevel@tonic-gate /* string search */
2127c478bd9Sstevel@tonic-gate files_XY_check_func check; /* NULL means one-shot, for getXXent */
2137c478bd9Sstevel@tonic-gate {
2146dd84139Sdjl char *r;
2157c478bd9Sstevel@tonic-gate nss_status_t res;
2167c478bd9Sstevel@tonic-gate int parsestat;
2177c478bd9Sstevel@tonic-gate int (*func)();
2187c478bd9Sstevel@tonic-gate
219cb5caa98Sdjl if (filter != NULL && *filter == '\0')
220cb5caa98Sdjl return (NSS_NOTFOUND);
2216dd84139Sdjl if (be->buf == 0 || (be->minbuf < args->buf.buflen)) {
2226dd84139Sdjl if (be->minbuf < args->buf.buflen) {
2236dd84139Sdjl if (be->buf == 0) {
2246dd84139Sdjl be->minbuf = args->buf.buflen;
2256dd84139Sdjl } else if (
2266dd84139Sdjl (r = realloc(be->buf, args->buf.buflen)) != NULL) {
2276dd84139Sdjl be->buf = r;
2286dd84139Sdjl be->minbuf = args->buf.buflen;
2296dd84139Sdjl }
2306dd84139Sdjl }
2317c478bd9Sstevel@tonic-gate if (be->buf == 0 &&
2326dd84139Sdjl (be->buf = malloc(be->minbuf)) == 0)
2336dd84139Sdjl return (NSS_UNAVAIL);
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate if (check != 0 || be->f == 0) {
2377c478bd9Sstevel@tonic-gate if ((res = _nss_files_setent(be, 0)) != NSS_SUCCESS) {
2387c478bd9Sstevel@tonic-gate return (res);
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate res = NSS_NOTFOUND;
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate /*CONSTCOND*/
2457c478bd9Sstevel@tonic-gate while (1) {
2467c478bd9Sstevel@tonic-gate char *instr = be->buf;
2477c478bd9Sstevel@tonic-gate int linelen;
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate if ((linelen = _nss_files_read_line(be->f, instr,
2507c478bd9Sstevel@tonic-gate be->minbuf)) < 0) {
2517c478bd9Sstevel@tonic-gate /* End of file */
2527c478bd9Sstevel@tonic-gate args->returnval = 0;
253cb5caa98Sdjl args->returnlen = 0;
2547c478bd9Sstevel@tonic-gate break;
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate if (filter != 0 && strstr(instr, filter) == 0) {
2577c478bd9Sstevel@tonic-gate /*
2587c478bd9Sstevel@tonic-gate * Optimization: if the entry doesn't contain the
2597c478bd9Sstevel@tonic-gate * filter string then it can't be the entry we want,
2607c478bd9Sstevel@tonic-gate * so don't bother looking more closely at it.
2617c478bd9Sstevel@tonic-gate */
2627c478bd9Sstevel@tonic-gate continue;
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate if (netdb) {
2657c478bd9Sstevel@tonic-gate char *first;
2667c478bd9Sstevel@tonic-gate char *last;
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate if ((last = strchr(instr, '#')) == 0) {
2697c478bd9Sstevel@tonic-gate last = instr + linelen;
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate *last-- = '\0'; /* Nuke '\n' or #comment */
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate /*
2747c478bd9Sstevel@tonic-gate * Skip leading whitespace. Normally there isn't
2757c478bd9Sstevel@tonic-gate * any, so it's not worth calling strspn().
2767c478bd9Sstevel@tonic-gate */
2777c478bd9Sstevel@tonic-gate for (first = instr; isspace(*first); first++) {
2787c478bd9Sstevel@tonic-gate ;
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate if (*first == '\0') {
2817c478bd9Sstevel@tonic-gate continue;
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate /*
2847c478bd9Sstevel@tonic-gate * Found something non-blank on the line. Skip back
2857c478bd9Sstevel@tonic-gate * over any trailing whitespace; since we know
2867c478bd9Sstevel@tonic-gate * there's non-whitespace earlier in the line,
2877c478bd9Sstevel@tonic-gate * checking for termination is easy.
2887c478bd9Sstevel@tonic-gate */
2897c478bd9Sstevel@tonic-gate while (isspace(*last)) {
2907c478bd9Sstevel@tonic-gate --last;
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate linelen = last - first + 1;
2947c478bd9Sstevel@tonic-gate if (first != instr) {
2957c478bd9Sstevel@tonic-gate instr = first;
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate args->returnval = 0;
300cb5caa98Sdjl args->returnlen = 0;
301cb5caa98Sdjl
302cb5caa98Sdjl if (check != NULL && (*check)(args, instr, linelen) == 0)
303cb5caa98Sdjl continue;
3047c478bd9Sstevel@tonic-gate
3052b4a7802SBaban Kenkre parsestat = NSS_STR_PARSE_SUCCESS;
3062b4a7802SBaban Kenkre if (be->filename != NULL) {
3072b4a7802SBaban Kenkre /*
3082b4a7802SBaban Kenkre * Special case for passwd and group wherein we
3092b4a7802SBaban Kenkre * replace uids/gids > MAXUID by ID_NOBODY
3102b4a7802SBaban Kenkre * because files backend does not support
3112b4a7802SBaban Kenkre * ephemeral ids.
3122b4a7802SBaban Kenkre */
3132b4a7802SBaban Kenkre if (strcmp(be->filename, PF_PATH) == 0)
3142b4a7802SBaban Kenkre parsestat = validate_passwd_ids(instr,
3152b4a7802SBaban Kenkre &linelen, be->minbuf, 2);
3162b4a7802SBaban Kenkre else if (strcmp(be->filename, GF_PATH) == 0)
3172b4a7802SBaban Kenkre parsestat = validate_group_ids(instr,
3182b4a7802SBaban Kenkre &linelen, be->minbuf, 2, check);
3192b4a7802SBaban Kenkre }
3202b4a7802SBaban Kenkre
3212b4a7802SBaban Kenkre if (parsestat == NSS_STR_PARSE_SUCCESS) {
3227c478bd9Sstevel@tonic-gate func = args->str2ent;
3237c478bd9Sstevel@tonic-gate parsestat = (*func)(instr, linelen, args->buf.result,
3247c478bd9Sstevel@tonic-gate args->buf.buffer, args->buf.buflen);
3252b4a7802SBaban Kenkre }
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate if (parsestat == NSS_STR_PARSE_SUCCESS) {
328cb5caa98Sdjl args->returnval = (args->buf.result != NULL)?
329cb5caa98Sdjl args->buf.result : args->buf.buffer;
330cb5caa98Sdjl args->returnlen = linelen;
3317c478bd9Sstevel@tonic-gate res = NSS_SUCCESS;
3327c478bd9Sstevel@tonic-gate break;
3337c478bd9Sstevel@tonic-gate } else if (parsestat == NSS_STR_PARSE_ERANGE) {
3347c478bd9Sstevel@tonic-gate args->erange = 1;
3357c478bd9Sstevel@tonic-gate break;
3367c478bd9Sstevel@tonic-gate } /* else if (parsestat == NSS_STR_PARSE_PARSE) don't care ! */
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate /*
3407c478bd9Sstevel@tonic-gate * stayopen is set to 0 by default in order to close the opened
3417c478bd9Sstevel@tonic-gate * file. Some applications may break if it is set to 1.
3427c478bd9Sstevel@tonic-gate */
3437c478bd9Sstevel@tonic-gate if (check != 0 && !args->stayopen) {
3447c478bd9Sstevel@tonic-gate (void) _nss_files_endent(be, 0);
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate return (res);
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate /*
3517c478bd9Sstevel@tonic-gate * File hashing support. Critical for sites with large (e.g. 1000+ lines)
3527c478bd9Sstevel@tonic-gate * /etc/passwd or /etc/group files. Currently only used by getpw*() and
3537c478bd9Sstevel@tonic-gate * getgr*() routines, but any files backend can use this stuff.
3547c478bd9Sstevel@tonic-gate */
3557c478bd9Sstevel@tonic-gate static void
_nss_files_hash_destroy(files_hash_t * fhp)3567c478bd9Sstevel@tonic-gate _nss_files_hash_destroy(files_hash_t *fhp)
3577c478bd9Sstevel@tonic-gate {
3587c478bd9Sstevel@tonic-gate free(fhp->fh_table);
3597c478bd9Sstevel@tonic-gate fhp->fh_table = NULL;
3607c478bd9Sstevel@tonic-gate free(fhp->fh_line);
3617c478bd9Sstevel@tonic-gate fhp->fh_line = NULL;
3627c478bd9Sstevel@tonic-gate free(fhp->fh_file_start);
3637c478bd9Sstevel@tonic-gate fhp->fh_file_start = NULL;
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate #ifdef PIC
3667c478bd9Sstevel@tonic-gate /*
3677c478bd9Sstevel@tonic-gate * It turns out the hashing stuff really needs to be disabled for processes
3687c478bd9Sstevel@tonic-gate * other than the nscd; the consumption of swap space and memory is otherwise
3697c478bd9Sstevel@tonic-gate * unacceptable when the nscd is killed w/ a large passwd file (4M) active.
3707c478bd9Sstevel@tonic-gate * See 4031930 for details.
3717c478bd9Sstevel@tonic-gate * So we just use this psuedo function to enable the hashing feature. Since
3727c478bd9Sstevel@tonic-gate * this function name is private, we just create a function w/ the name
3737c478bd9Sstevel@tonic-gate * __nss_use_files_hash in the nscd itself and everyone else uses the old
3747c478bd9Sstevel@tonic-gate * interface.
3757c478bd9Sstevel@tonic-gate * We also disable hashing for .a executables to avoid problems with large
3767c478bd9Sstevel@tonic-gate * files....
3777c478bd9Sstevel@tonic-gate */
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate #pragma weak __nss_use_files_hash
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate extern void __nss_use_files_hash(void);
3827c478bd9Sstevel@tonic-gate #endif /* pic */
3837c478bd9Sstevel@tonic-gate
384cb5caa98Sdjl /*ARGSUSED*/
3857c478bd9Sstevel@tonic-gate nss_status_t
_nss_files_XY_hash(files_backend_ptr_t be,nss_XbyY_args_t * args,int netdb,files_hash_t * fhp,int hashop,files_XY_check_func check)3867c478bd9Sstevel@tonic-gate _nss_files_XY_hash(files_backend_ptr_t be, nss_XbyY_args_t *args,
3877c478bd9Sstevel@tonic-gate int netdb, files_hash_t *fhp, int hashop, files_XY_check_func check)
3887c478bd9Sstevel@tonic-gate {
389cb5caa98Sdjl /* LINTED E_FUNC_VAR_UNUSED */
3902b4a7802SBaban Kenkre int fd, retries, ht, stat;
391cb5caa98Sdjl /* LINTED E_FUNC_VAR_UNUSED */
3927c478bd9Sstevel@tonic-gate uint_t hash, line, f;
393cb5caa98Sdjl /* LINTED E_FUNC_VAR_UNUSED */
3947c478bd9Sstevel@tonic-gate files_hashent_t *hp, *htab;
395cb5caa98Sdjl /* LINTED E_FUNC_VAR_UNUSED */
3967c478bd9Sstevel@tonic-gate char *cp, *first, *last;
397cb5caa98Sdjl /* LINTED E_FUNC_VAR_UNUSED */
3987c478bd9Sstevel@tonic-gate nss_XbyY_args_t xargs;
399cb5caa98Sdjl /* LINTED E_FUNC_VAR_UNUSED */
4007c478bd9Sstevel@tonic-gate struct stat64 st;
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate #ifndef PIC
4037c478bd9Sstevel@tonic-gate return (_nss_files_XY_all(be, args, netdb, 0, check));
4047c478bd9Sstevel@tonic-gate }
4057c478bd9Sstevel@tonic-gate #else
4067c478bd9Sstevel@tonic-gate if (__nss_use_files_hash == 0)
4077c478bd9Sstevel@tonic-gate return (_nss_files_XY_all(be, args, netdb, 0, check));
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate mutex_lock(&fhp->fh_lock);
4107c478bd9Sstevel@tonic-gate retry:
4117c478bd9Sstevel@tonic-gate retries = 100;
4127c478bd9Sstevel@tonic-gate while (stat64(be->filename, &st) < 0) {
4137c478bd9Sstevel@tonic-gate /*
414*655967abSMarcel Telka * This can happen only in two cases: Either the file is
415*655967abSMarcel Telka * completely missing and we were not able to read it yet
416*655967abSMarcel Telka * (fh_table is NULL), or there is some brief period when the
417*655967abSMarcel Telka * file is being modified/renamed. Keep trying until things
418*655967abSMarcel Telka * settle down, but eventually give up.
4197c478bd9Sstevel@tonic-gate */
420*655967abSMarcel Telka if (fhp->fh_table == NULL || --retries == 0)
4217c478bd9Sstevel@tonic-gate goto unavail;
4227c478bd9Sstevel@tonic-gate poll(0, 0, 100);
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate if (st.st_mtim.tv_sec == fhp->fh_mtime.tv_sec &&
4267c478bd9Sstevel@tonic-gate st.st_mtim.tv_nsec == fhp->fh_mtime.tv_nsec &&
4277c478bd9Sstevel@tonic-gate fhp->fh_table != NULL) {
4287c478bd9Sstevel@tonic-gate htab = &fhp->fh_table[hashop * fhp->fh_size];
429cb5caa98Sdjl hash = fhp->fh_hash_func[hashop](args, 1, NULL, 0);
4307c478bd9Sstevel@tonic-gate for (hp = htab[hash % fhp->fh_size].h_first; hp != NULL;
4317c478bd9Sstevel@tonic-gate hp = hp->h_next) {
4327c478bd9Sstevel@tonic-gate if (hp->h_hash != hash)
4337c478bd9Sstevel@tonic-gate continue;
4347c478bd9Sstevel@tonic-gate line = hp - htab;
435cb5caa98Sdjl if ((*check)(args, fhp->fh_line[line].l_start,
436cb5caa98Sdjl fhp->fh_line[line].l_len) == 0)
437cb5caa98Sdjl continue;
4382b4a7802SBaban Kenkre
4392b4a7802SBaban Kenkre if (be->filename != NULL) {
4402b4a7802SBaban Kenkre stat = NSS_STR_PARSE_SUCCESS;
4412b4a7802SBaban Kenkre if (strcmp(be->filename, PF_PATH) == 0)
4422b4a7802SBaban Kenkre stat = validate_passwd_ids(
4432b4a7802SBaban Kenkre fhp->fh_line[line].l_start,
4442b4a7802SBaban Kenkre &fhp->fh_line[line].l_len,
4452b4a7802SBaban Kenkre fhp->fh_line[line].l_len + 1,
4462b4a7802SBaban Kenkre 1);
4472b4a7802SBaban Kenkre else if (strcmp(be->filename, GF_PATH) == 0)
4482b4a7802SBaban Kenkre stat = validate_group_ids(
4492b4a7802SBaban Kenkre fhp->fh_line[line].l_start,
4502b4a7802SBaban Kenkre &fhp->fh_line[line].l_len,
4512b4a7802SBaban Kenkre fhp->fh_line[line].l_len + 1,
4522b4a7802SBaban Kenkre 1, check);
4532b4a7802SBaban Kenkre if (stat != NSS_STR_PARSE_SUCCESS) {
4542b4a7802SBaban Kenkre if (stat == NSS_STR_PARSE_ERANGE)
4552b4a7802SBaban Kenkre args->erange = 1;
4562b4a7802SBaban Kenkre continue;
4572b4a7802SBaban Kenkre }
4582b4a7802SBaban Kenkre }
4592b4a7802SBaban Kenkre
4607c478bd9Sstevel@tonic-gate if ((*args->str2ent)(fhp->fh_line[line].l_start,
4617c478bd9Sstevel@tonic-gate fhp->fh_line[line].l_len, args->buf.result,
4627c478bd9Sstevel@tonic-gate args->buf.buffer, args->buf.buflen) ==
4637c478bd9Sstevel@tonic-gate NSS_STR_PARSE_SUCCESS) {
464cb5caa98Sdjl args->returnval = (args->buf.result)?
465cb5caa98Sdjl args->buf.result:args->buf.buffer;
466cb5caa98Sdjl args->returnlen = fhp->fh_line[line].l_len;
4677c478bd9Sstevel@tonic-gate mutex_unlock(&fhp->fh_lock);
4687c478bd9Sstevel@tonic-gate return (NSS_SUCCESS);
4697c478bd9Sstevel@tonic-gate } else {
4707c478bd9Sstevel@tonic-gate args->erange = 1;
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate args->returnval = 0;
474cb5caa98Sdjl args->returnlen = 0;
4757c478bd9Sstevel@tonic-gate mutex_unlock(&fhp->fh_lock);
4767c478bd9Sstevel@tonic-gate return (NSS_NOTFOUND);
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate
4797c478bd9Sstevel@tonic-gate _nss_files_hash_destroy(fhp);
4807c478bd9Sstevel@tonic-gate
4817c478bd9Sstevel@tonic-gate if (st.st_size > SSIZE_MAX)
4827c478bd9Sstevel@tonic-gate goto unavail;
4837c478bd9Sstevel@tonic-gate
4847c478bd9Sstevel@tonic-gate if ((fhp->fh_file_start = malloc((ssize_t)st.st_size + 1)) == NULL)
4857c478bd9Sstevel@tonic-gate goto unavail;
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate if ((fd = open(be->filename, O_RDONLY)) < 0)
4887c478bd9Sstevel@tonic-gate goto unavail;
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate if (read(fd, fhp->fh_file_start, (ssize_t)st.st_size) !=
4917c478bd9Sstevel@tonic-gate (ssize_t)st.st_size) {
4927c478bd9Sstevel@tonic-gate close(fd);
4937c478bd9Sstevel@tonic-gate goto retry;
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate close(fd);
4977c478bd9Sstevel@tonic-gate
4987c478bd9Sstevel@tonic-gate fhp->fh_file_end = fhp->fh_file_start + (off_t)st.st_size;
4997c478bd9Sstevel@tonic-gate *fhp->fh_file_end = '\n';
5007c478bd9Sstevel@tonic-gate fhp->fh_mtime = st.st_mtim;
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate /*
5037c478bd9Sstevel@tonic-gate * If the file changed since we read it, or if it's less than
5047c478bd9Sstevel@tonic-gate * 1-2 seconds old, don't trust it; its modification may still
5057c478bd9Sstevel@tonic-gate * be in progress. The latter is a heuristic hack to minimize
5067c478bd9Sstevel@tonic-gate * the likelihood of damage if someone modifies /etc/mumble
5077c478bd9Sstevel@tonic-gate * directly (as opposed to editing and renaming a temp file).
5087c478bd9Sstevel@tonic-gate *
5097c478bd9Sstevel@tonic-gate * Note: the cast to u_int is there in case (1) someone rdated
5107c478bd9Sstevel@tonic-gate * the system backwards since the last modification of /etc/mumble
5117c478bd9Sstevel@tonic-gate * or (2) this is a diskless client whose time is badly out of sync
5127c478bd9Sstevel@tonic-gate * with its server. The 1-2 second age hack doesn't cover these
5137c478bd9Sstevel@tonic-gate * cases -- oh well.
5147c478bd9Sstevel@tonic-gate */
5157c478bd9Sstevel@tonic-gate if (stat64(be->filename, &st) < 0 ||
5167c478bd9Sstevel@tonic-gate st.st_mtim.tv_sec != fhp->fh_mtime.tv_sec ||
5177c478bd9Sstevel@tonic-gate st.st_mtim.tv_nsec != fhp->fh_mtime.tv_nsec ||
5187c478bd9Sstevel@tonic-gate (uint_t)(time(0) - st.st_mtim.tv_sec + 2) < 4) {
5197c478bd9Sstevel@tonic-gate poll(0, 0, 1000);
5207c478bd9Sstevel@tonic-gate goto retry;
5217c478bd9Sstevel@tonic-gate }
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate line = 1;
5247c478bd9Sstevel@tonic-gate for (cp = fhp->fh_file_start; cp < fhp->fh_file_end; cp++)
5257c478bd9Sstevel@tonic-gate if (*cp == '\n')
5267c478bd9Sstevel@tonic-gate line++;
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate for (f = 2; f * f <= line; f++) { /* find next largest prime */
5297c478bd9Sstevel@tonic-gate if (line % f == 0) {
5307c478bd9Sstevel@tonic-gate f = 1;
5317c478bd9Sstevel@tonic-gate line++;
5327c478bd9Sstevel@tonic-gate }
5337c478bd9Sstevel@tonic-gate }
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate fhp->fh_size = line;
5367c478bd9Sstevel@tonic-gate fhp->fh_line = malloc(line * sizeof (files_linetab_t));
5377c478bd9Sstevel@tonic-gate fhp->fh_table = calloc(line * fhp->fh_nhtab, sizeof (files_hashent_t));
5387c478bd9Sstevel@tonic-gate if (fhp->fh_line == NULL || fhp->fh_table == NULL)
5397c478bd9Sstevel@tonic-gate goto unavail;
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate line = 0;
5427c478bd9Sstevel@tonic-gate cp = fhp->fh_file_start;
5437c478bd9Sstevel@tonic-gate while (cp < fhp->fh_file_end) {
5447c478bd9Sstevel@tonic-gate first = cp;
5457c478bd9Sstevel@tonic-gate while (*cp != '\n')
5467c478bd9Sstevel@tonic-gate cp++;
5477c478bd9Sstevel@tonic-gate if (cp > first && *(cp - 1) == '\\') {
5487c478bd9Sstevel@tonic-gate memmove(first + 2, first, cp - first - 1);
5497c478bd9Sstevel@tonic-gate cp = first + 2;
5507c478bd9Sstevel@tonic-gate continue;
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate last = cp;
5537c478bd9Sstevel@tonic-gate *cp++ = '\0';
5547c478bd9Sstevel@tonic-gate if (netdb) {
5557c478bd9Sstevel@tonic-gate if ((last = strchr(first, '#')) == 0)
5567c478bd9Sstevel@tonic-gate last = cp - 1;
5577c478bd9Sstevel@tonic-gate *last-- = '\0'; /* nuke '\n' or #comment */
5587c478bd9Sstevel@tonic-gate while (isspace(*first)) /* nuke leading whitespace */
5597c478bd9Sstevel@tonic-gate first++;
5607c478bd9Sstevel@tonic-gate if (*first == '\0') /* skip content-free lines */
5617c478bd9Sstevel@tonic-gate continue;
5627c478bd9Sstevel@tonic-gate while (isspace(*last)) /* nuke trailing whitespace */
5637c478bd9Sstevel@tonic-gate --last;
5647c478bd9Sstevel@tonic-gate *++last = '\0';
5657c478bd9Sstevel@tonic-gate }
5667c478bd9Sstevel@tonic-gate for (ht = 0; ht < fhp->fh_nhtab; ht++) {
5677c478bd9Sstevel@tonic-gate hp = &fhp->fh_table[ht * fhp->fh_size + line];
568cb5caa98Sdjl hp->h_hash = fhp->fh_hash_func[ht](&xargs, 0, first,
569cb5caa98Sdjl last - first);
5707c478bd9Sstevel@tonic-gate }
5717c478bd9Sstevel@tonic-gate fhp->fh_line[line].l_start = first;
5727c478bd9Sstevel@tonic-gate fhp->fh_line[line++].l_len = last - first;
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate /*
5767c478bd9Sstevel@tonic-gate * Populate the hash tables in reverse order so that the hash chains
5777c478bd9Sstevel@tonic-gate * end up in forward order. This ensures that hashed lookups find
5787c478bd9Sstevel@tonic-gate * things in the same order that a linear search of the file would.
5797c478bd9Sstevel@tonic-gate * This is essential in cases where there could be multiple matches.
5807c478bd9Sstevel@tonic-gate * For example: until 2.7, root and smtp both had uid 0; but we
5817c478bd9Sstevel@tonic-gate * certainly wouldn't want getpwuid(0) to return smtp.
5827c478bd9Sstevel@tonic-gate */
5837c478bd9Sstevel@tonic-gate for (ht = 0; ht < fhp->fh_nhtab; ht++) {
5847c478bd9Sstevel@tonic-gate htab = &fhp->fh_table[ht * fhp->fh_size];
5857c478bd9Sstevel@tonic-gate for (hp = &htab[line - 1]; hp >= htab; hp--) {
5867c478bd9Sstevel@tonic-gate uint_t bucket = hp->h_hash % fhp->fh_size;
5877c478bd9Sstevel@tonic-gate hp->h_next = htab[bucket].h_first;
5887c478bd9Sstevel@tonic-gate htab[bucket].h_first = hp;
5897c478bd9Sstevel@tonic-gate }
5907c478bd9Sstevel@tonic-gate }
5917c478bd9Sstevel@tonic-gate
5927c478bd9Sstevel@tonic-gate goto retry;
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate unavail:
5957c478bd9Sstevel@tonic-gate _nss_files_hash_destroy(fhp);
5967c478bd9Sstevel@tonic-gate mutex_unlock(&fhp->fh_lock);
5977c478bd9Sstevel@tonic-gate return (NSS_UNAVAIL);
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate #endif /* PIC */
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate nss_status_t
_nss_files_getent_rigid(be,a)6027c478bd9Sstevel@tonic-gate _nss_files_getent_rigid(be, a)
6037c478bd9Sstevel@tonic-gate files_backend_ptr_t be;
6047c478bd9Sstevel@tonic-gate void *a;
6057c478bd9Sstevel@tonic-gate {
6067c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args = (nss_XbyY_args_t *)a;
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate return (_nss_files_XY_all(be, args, 0, 0, 0));
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate
6117c478bd9Sstevel@tonic-gate nss_status_t
_nss_files_getent_netdb(be,a)6127c478bd9Sstevel@tonic-gate _nss_files_getent_netdb(be, a)
6137c478bd9Sstevel@tonic-gate files_backend_ptr_t be;
6147c478bd9Sstevel@tonic-gate void *a;
6157c478bd9Sstevel@tonic-gate {
6167c478bd9Sstevel@tonic-gate nss_XbyY_args_t *args = (nss_XbyY_args_t *)a;
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate return (_nss_files_XY_all(be, args, 1, 0, 0));
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6227c478bd9Sstevel@tonic-gate nss_status_t
_nss_files_destr(be,dummy)6237c478bd9Sstevel@tonic-gate _nss_files_destr(be, dummy)
6247c478bd9Sstevel@tonic-gate files_backend_ptr_t be;
6257c478bd9Sstevel@tonic-gate void *dummy;
6267c478bd9Sstevel@tonic-gate {
6277c478bd9Sstevel@tonic-gate if (be != 0) {
6287c478bd9Sstevel@tonic-gate if (be->f != 0) {
629cb5caa98Sdjl (void) _nss_files_endent(be, 0);
6307c478bd9Sstevel@tonic-gate }
6317c478bd9Sstevel@tonic-gate if (be->hashinfo != NULL) {
632cb5caa98Sdjl (void) mutex_lock(&be->hashinfo->fh_lock);
6337c478bd9Sstevel@tonic-gate if (--be->hashinfo->fh_refcnt == 0)
6347c478bd9Sstevel@tonic-gate _nss_files_hash_destroy(be->hashinfo);
635cb5caa98Sdjl (void) mutex_unlock(&be->hashinfo->fh_lock);
6367c478bd9Sstevel@tonic-gate }
6377c478bd9Sstevel@tonic-gate free(be);
6387c478bd9Sstevel@tonic-gate }
6397c478bd9Sstevel@tonic-gate return (NSS_SUCCESS); /* In case anyone is dumb enough to check */
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate nss_backend_t *
_nss_files_constr(ops,n_ops,filename,min_bufsize,fhp)6437c478bd9Sstevel@tonic-gate _nss_files_constr(ops, n_ops, filename, min_bufsize, fhp)
6447c478bd9Sstevel@tonic-gate files_backend_op_t ops[];
6457c478bd9Sstevel@tonic-gate int n_ops;
6467c478bd9Sstevel@tonic-gate const char *filename;
6477c478bd9Sstevel@tonic-gate int min_bufsize;
6487c478bd9Sstevel@tonic-gate files_hash_t *fhp;
6497c478bd9Sstevel@tonic-gate {
6507c478bd9Sstevel@tonic-gate files_backend_ptr_t be;
6517c478bd9Sstevel@tonic-gate
6527c478bd9Sstevel@tonic-gate if ((be = (files_backend_ptr_t)malloc(sizeof (*be))) == 0) {
6537c478bd9Sstevel@tonic-gate return (0);
6547c478bd9Sstevel@tonic-gate }
6557c478bd9Sstevel@tonic-gate be->ops = ops;
6567c478bd9Sstevel@tonic-gate be->n_ops = n_ops;
6577c478bd9Sstevel@tonic-gate be->filename = filename;
6587c478bd9Sstevel@tonic-gate be->minbuf = min_bufsize;
6597c478bd9Sstevel@tonic-gate be->f = 0;
6607c478bd9Sstevel@tonic-gate be->buf = 0;
6617c478bd9Sstevel@tonic-gate be->hashinfo = fhp;
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate if (fhp != NULL) {
664cb5caa98Sdjl (void) mutex_lock(&fhp->fh_lock);
6657c478bd9Sstevel@tonic-gate fhp->fh_refcnt++;
666cb5caa98Sdjl (void) mutex_unlock(&fhp->fh_lock);
6677c478bd9Sstevel@tonic-gate }
6687c478bd9Sstevel@tonic-gate
6697c478bd9Sstevel@tonic-gate return ((nss_backend_t *)be);
6707c478bd9Sstevel@tonic-gate }
671cb5caa98Sdjl
672cb5caa98Sdjl int
_nss_files_check_name_colon(nss_XbyY_args_t * argp,const char * line,int linelen)673cb5caa98Sdjl _nss_files_check_name_colon(nss_XbyY_args_t *argp, const char *line,
674cb5caa98Sdjl int linelen)
675cb5caa98Sdjl {
676cb5caa98Sdjl const char *linep, *limit;
677cb5caa98Sdjl const char *keyp = argp->key.name;
678cb5caa98Sdjl
679cb5caa98Sdjl linep = line;
680cb5caa98Sdjl limit = line + linelen;
681cb5caa98Sdjl while (*keyp && linep < limit && *keyp == *linep) {
682cb5caa98Sdjl keyp++;
683cb5caa98Sdjl linep++;
684cb5caa98Sdjl }
685cb5caa98Sdjl return (linep < limit && *keyp == '\0' && *linep == ':');
686cb5caa98Sdjl }
687cb5caa98Sdjl
688cb5caa98Sdjl /*
689cb5caa98Sdjl * This routine is used to parse lines of the form:
690cb5caa98Sdjl * name number aliases
691cb5caa98Sdjl * It returns 1 if the key in argp matches any one of the
692cb5caa98Sdjl * names in the line, otherwise 0
693cb5caa98Sdjl * Used by rpc, networks, protocols
694cb5caa98Sdjl */
695cb5caa98Sdjl int
_nss_files_check_name_aliases(nss_XbyY_args_t * argp,const char * line,int linelen)696cb5caa98Sdjl _nss_files_check_name_aliases(nss_XbyY_args_t *argp, const char *line,
697cb5caa98Sdjl int linelen)
698cb5caa98Sdjl {
699cb5caa98Sdjl const char *limit, *linep, *keyp;
700cb5caa98Sdjl
701cb5caa98Sdjl linep = line;
702cb5caa98Sdjl limit = line + linelen;
703cb5caa98Sdjl keyp = argp->key.name;
704cb5caa98Sdjl
705cb5caa98Sdjl /* compare name */
706cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
707cb5caa98Sdjl keyp++;
708cb5caa98Sdjl linep++;
709cb5caa98Sdjl }
710cb5caa98Sdjl if (*keyp == '\0' && linep < limit && isspace(*linep))
711cb5caa98Sdjl return (1);
712cb5caa98Sdjl /* skip remainder of the name, if any */
713cb5caa98Sdjl while (linep < limit && !isspace(*linep))
714cb5caa98Sdjl linep++;
715cb5caa98Sdjl /* skip the delimiting spaces */
716cb5caa98Sdjl while (linep < limit && isspace(*linep))
717cb5caa98Sdjl linep++;
718cb5caa98Sdjl /* compare with the aliases */
719cb5caa98Sdjl while (linep < limit) {
720cb5caa98Sdjl /*
721cb5caa98Sdjl * 1st pass: skip number
722cb5caa98Sdjl * Other passes: skip remainder of the alias name, if any
723cb5caa98Sdjl */
724cb5caa98Sdjl while (linep < limit && !isspace(*linep))
725cb5caa98Sdjl linep++;
726cb5caa98Sdjl /* skip the delimiting spaces */
727cb5caa98Sdjl while (linep < limit && isspace(*linep))
728cb5caa98Sdjl linep++;
729cb5caa98Sdjl /* compare with the alias name */
730cb5caa98Sdjl keyp = argp->key.name;
731cb5caa98Sdjl while (*keyp && linep < limit && !isspace(*linep) &&
732cb5caa98Sdjl *keyp == *linep) {
733cb5caa98Sdjl keyp++;
734cb5caa98Sdjl linep++;
735cb5caa98Sdjl }
736cb5caa98Sdjl if (*keyp == '\0' && (linep == limit || isspace(*linep)))
737cb5caa98Sdjl return (1);
738cb5caa98Sdjl }
739cb5caa98Sdjl return (0);
740cb5caa98Sdjl }
741