diff options
Diffstat (limited to 'REORG.TODO/nss/nss_files')
-rw-r--r-- | REORG.TODO/nss/nss_files/files-XXX.c | 300 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-alias.c | 404 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-ethers.c | 67 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-grp.c | 44 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-hosts.c | 482 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-init.c | 64 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-initgroups.c | 142 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-key.c | 111 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-netgrp.c | 294 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-network.c | 88 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-parse.c | 335 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-proto.c | 46 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-pwd.c | 44 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-rpc.c | 46 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-service.c | 63 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-sgrp.c | 37 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_files/files-spwd.c | 37 |
17 files changed, 2604 insertions, 0 deletions
diff --git a/REORG.TODO/nss/nss_files/files-XXX.c b/REORG.TODO/nss/nss_files/files-XXX.c new file mode 100644 index 0000000000..265331ef21 --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-XXX.c @@ -0,0 +1,300 @@ +/* Common code for file-based databases in nss_files module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <libc-lock.h> +#include "nsswitch.h" + +#include <kernel-features.h> + +/* These symbols are defined by the including source file: + + ENTNAME -- database name of the structure and functions (hostent, pwent). + STRUCTURE -- struct name, define only if not ENTNAME (passwd, group). + DATABASE -- string of the database file's name ("hosts", "passwd"). + + NEED_H_ERRNO - defined iff an arg `int *herrnop' is used. + + Also see files-parse.c. +*/ + +#define ENTNAME_r CONCAT(ENTNAME,_r) + +#define DATAFILE "/etc/" DATABASE + +#ifdef NEED_H_ERRNO +# include <netdb.h> +# define H_ERRNO_PROTO , int *herrnop +# define H_ERRNO_ARG , herrnop +# define H_ERRNO_SET(val) (*herrnop = (val)) +#else +# define H_ERRNO_PROTO +# define H_ERRNO_ARG +# define H_ERRNO_SET(val) ((void) 0) +#endif + +#ifndef EXTRA_ARGS +# define EXTRA_ARGS +# define EXTRA_ARGS_DECL +# define EXTRA_ARGS_VALUE +#endif + +/* Locks the static variables in this file. */ +__libc_lock_define_initialized (static, lock) + +/* Maintenance of the stream open on the database file. For getXXent + operations the stream needs to be held open across calls, the other + getXXbyYY operations all use their own stream. */ + +static FILE *stream; + +/* Open database file if not already opened. */ +static enum nss_status +internal_setent (FILE **stream) +{ + enum nss_status status = NSS_STATUS_SUCCESS; + + if (*stream == NULL) + { + *stream = fopen (DATAFILE, "rce"); + + if (*stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + } + else + rewind (*stream); + + return status; +} + + +/* Thread-safe, exported version of that. */ +enum nss_status +CONCAT(_nss_files_set,ENTNAME) (int stayopen) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_setent (&stream); + + __libc_lock_unlock (lock); + + return status; +} + + +/* Close the database file. */ +static void +internal_endent (FILE **stream) +{ + if (*stream != NULL) + { + fclose (*stream); + *stream = NULL; + } +} + + +/* Thread-safe, exported version of that. */ +enum nss_status +CONCAT(_nss_files_end,ENTNAME) (void) +{ + __libc_lock_lock (lock); + + internal_endent (&stream); + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + + +typedef enum +{ + gcr_ok = 0, + gcr_error = -1, + gcr_overflow = -2 +} get_contents_ret; + +/* Hack around the fact that fgets only accepts int sizes. */ +static get_contents_ret +get_contents (char *linebuf, size_t len, FILE *stream) +{ + size_t remaining_len = len; + char *curbuf = linebuf; + + do + { + int curlen = ((remaining_len > (size_t) INT_MAX) ? INT_MAX + : remaining_len); + + /* Terminate the line so that we can test for overflow. */ + ((unsigned char *) curbuf)[curlen - 1] = 0xff; + + char *p = fgets_unlocked (curbuf, curlen, stream); + + /* EOF or read error. */ + if (p == NULL) + return gcr_error; + + /* Done reading in the line. */ + if (((unsigned char *) curbuf)[curlen - 1] == 0xff) + return gcr_ok; + + /* Drop the terminating '\0'. */ + remaining_len -= curlen - 1; + curbuf += curlen - 1; + } + /* fgets copies one less than the input length. Our last iteration is of + REMAINING_LEN and once that is done, REMAINING_LEN is decremented by + REMAINING_LEN - 1, leaving the result as 1. */ + while (remaining_len > 1); + + /* This means that the current buffer was not large enough. */ + return gcr_overflow; +} + +/* Parsing the database file into `struct STRUCTURE' data structures. */ +static enum nss_status +internal_getent (FILE *stream, struct STRUCTURE *result, + char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO + EXTRA_ARGS_DECL) +{ + char *p; + struct parser_data *data = (void *) buffer; + size_t linebuflen = buffer + buflen - data->linebuffer; + int parse_result; + + if (buflen < sizeof *data + 2) + { + *errnop = ERANGE; + H_ERRNO_SET (NETDB_INTERNAL); + return NSS_STATUS_TRYAGAIN; + } + + do + { + get_contents_ret r = get_contents (data->linebuffer, linebuflen, stream); + + if (r == gcr_error) + { + /* End of file or read error. */ + H_ERRNO_SET (HOST_NOT_FOUND); + return NSS_STATUS_NOTFOUND; + } + + if (r == gcr_overflow) + { + /* The line is too long. Give the user the opportunity to + enlarge the buffer. */ + *errnop = ERANGE; + H_ERRNO_SET (NETDB_INTERNAL); + return NSS_STATUS_TRYAGAIN; + } + + /* Everything OK. Now skip leading blanks. */ + p = data->linebuffer; + while (isspace (*p)) + ++p; + } + while (*p == '\0' || *p == '#' /* Ignore empty and comment lines. */ + /* Parse the line. If it is invalid, loop to get the next + line of the file to parse. */ + || ! (parse_result = parse_line (p, result, data, buflen, errnop + EXTRA_ARGS))); + + if (__glibc_unlikely (parse_result == -1)) + { + H_ERRNO_SET (NETDB_INTERNAL); + return NSS_STATUS_TRYAGAIN; + } + + /* Filled in RESULT with the next entry from the database file. */ + return NSS_STATUS_SUCCESS; +} + + +/* Return the next entry from the database file, doing locking. */ +enum nss_status +CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer, + size_t buflen, int *errnop H_ERRNO_PROTO) +{ + /* Return next entry in host file. */ + enum nss_status status = NSS_STATUS_SUCCESS; + + __libc_lock_lock (lock); + + /* Be prepared that the set*ent function was not called before. */ + if (stream == NULL) + { + int save_errno = errno; + + status = internal_setent (&stream); + + __set_errno (save_errno); + } + + if (status == NSS_STATUS_SUCCESS) + status = internal_getent (stream, result, buffer, buflen, errnop + H_ERRNO_ARG EXTRA_ARGS_VALUE); + + __libc_lock_unlock (lock); + + return status; +} + +/* Macro for defining lookup functions for this file-based database. + + NAME is the name of the lookup; e.g. `hostbyname'. + + DB_CHAR, KEYPATTERN, KEYSIZE are ignored here but used by db-XXX.c + e.g. `1 + sizeof (id) * 4'. + + PROTO is the potentially empty list of other parameters. + + BREAK_IF_MATCH is a block of code which compares `struct STRUCTURE *result' + to the lookup key arguments and does `break;' if they match. */ + +#define DB_LOOKUP(name, db_char, keysize, keypattern, break_if_match, proto...)\ +enum nss_status \ +_nss_files_get##name##_r (proto, \ + struct STRUCTURE *result, char *buffer, \ + size_t buflen, int *errnop H_ERRNO_PROTO) \ +{ \ + enum nss_status status; \ + FILE *stream = NULL; \ + \ + /* Open file. */ \ + status = internal_setent (&stream); \ + \ + if (status == NSS_STATUS_SUCCESS) \ + { \ + while ((status = internal_getent (stream, result, buffer, buflen, errnop \ + H_ERRNO_ARG EXTRA_ARGS_VALUE)) \ + == NSS_STATUS_SUCCESS) \ + { break_if_match } \ + \ + internal_endent (&stream); \ + } \ + \ + return status; \ +} diff --git a/REORG.TODO/nss/nss_files/files-alias.c b/REORG.TODO/nss/nss_files/files-alias.c new file mode 100644 index 0000000000..cf872bb603 --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-alias.c @@ -0,0 +1,404 @@ +/* Mail alias file parser in nss_files module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <aliases.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <libc-lock.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <kernel-features.h> + +#include "nsswitch.h" + +/* Locks the static variables in this file. */ +__libc_lock_define_initialized (static, lock) + +/* Maintenance of the stream open on the database file. For getXXent + operations the stream needs to be held open across calls, the other + getXXbyYY operations all use their own stream. */ + +static FILE *stream; + + +static enum nss_status +internal_setent (FILE **stream) +{ + enum nss_status status = NSS_STATUS_SUCCESS; + + if (*stream == NULL) + { + *stream = fopen ("/etc/aliases", "rce"); + + if (*stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + } + else + rewind (*stream); + + return status; +} + + +/* Thread-safe, exported version of that. */ +enum nss_status +_nss_files_setaliasent (void) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_setent (&stream); + + __libc_lock_unlock (lock); + + return status; +} + + +/* Close the database file. */ +static void +internal_endent (FILE **stream) +{ + if (*stream != NULL) + { + fclose (*stream); + *stream = NULL; + } +} + + +/* Thread-safe, exported version of that. */ +enum nss_status +_nss_files_endaliasent (void) +{ + __libc_lock_lock (lock); + + internal_endent (&stream); + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +/* Parsing the database file into `struct aliasent' data structures. */ +static enum nss_status +get_next_alias (FILE *stream, const char *match, struct aliasent *result, + char *buffer, size_t buflen, int *errnop) +{ + enum nss_status status = NSS_STATUS_NOTFOUND; + int ignore = 0; + + result->alias_members_len = 0; + + while (1) + { + /* Now we are ready to process the input. We have to read a + line and all its continuations and construct the array of + string pointers. This pointers and the names itself have to + be placed in BUFFER. */ + char *first_unused = buffer; + size_t room_left = buflen - (buflen % __alignof__ (char *)); + char *line; + + /* Check whether the buffer is large enough for even trying to + read something. */ + if (room_left < 2) + goto no_more_room; + + /* Read the first line. It must contain the alias name and + possibly some alias names. */ + first_unused[room_left - 1] = '\xff'; + line = fgets_unlocked (first_unused, room_left, stream); + if (line == NULL) + /* Nothing to read. */ + break; + else if (first_unused[room_left - 1] != '\xff') + { + /* The line is too long for our buffer. */ + no_more_room: + *errnop = ERANGE; + status = NSS_STATUS_TRYAGAIN; + break; + } + else + { + char *cp; + + /* If we are in IGNORE mode and the first character in the + line is a white space we ignore the line and start + reading the next. */ + if (ignore && isspace (*first_unused)) + continue; + + /* Terminate the line for any case. */ + cp = strpbrk (first_unused, "#\n"); + if (cp != NULL) + *cp = '\0'; + + /* Skip leading blanks. */ + while (isspace (*line)) + ++line; + + result->alias_name = first_unused; + while (*line != '\0' && *line != ':') + *first_unused++ = *line++; + if (*line == '\0' || result->alias_name == first_unused) + /* No valid name. Ignore the line. */ + continue; + + *first_unused++ = '\0'; + if (room_left < (size_t) (first_unused - result->alias_name)) + goto no_more_room; + room_left -= first_unused - result->alias_name; + ++line; + + /* When we search for a specific alias we can avoid all the + difficult parts and compare now with the name we are + looking for. If it does not match we simply ignore all + lines until the next line containing the start of a new + alias is found. */ + ignore = (match != NULL + && __strcasecmp (result->alias_name, match) != 0); + + while (! ignore) + { + while (isspace (*line)) + ++line; + + cp = first_unused; + while (*line != '\0' && *line != ',') + *first_unused++ = *line++; + + if (first_unused != cp) + { + /* OK, we can have a regular entry or an include + request. */ + if (*line != '\0') + ++line; + *first_unused++ = '\0'; + + if (strncmp (cp, ":include:", 9) != 0) + { + if (room_left < (first_unused - cp) + sizeof (char *)) + goto no_more_room; + room_left -= (first_unused - cp) + sizeof (char *); + + ++result->alias_members_len; + } + else + { + /* Oh well, we have to read the addressed file. */ + FILE *listfile; + char *old_line = NULL; + + first_unused = cp; + + listfile = fopen (&cp[9], "rce"); + /* If the file does not exist we simply ignore + the statement. */ + if (listfile != NULL + && (old_line = strdup (line)) != NULL) + { + while (! feof_unlocked (listfile)) + { + first_unused[room_left - 1] = '\xff'; + line = fgets_unlocked (first_unused, room_left, + listfile); + if (line == NULL) + break; + if (first_unused[room_left - 1] != '\xff') + { + free (old_line); + goto no_more_room; + } + + /* Parse the line. */ + cp = strpbrk (line, "#\n"); + if (cp != NULL) + *cp = '\0'; + + do + { + while (isspace (*line)) + ++line; + + cp = first_unused; + while (*line != '\0' && *line != ',') + *first_unused++ = *line++; + + if (*line != '\0') + ++line; + + if (first_unused != cp) + { + *first_unused++ = '\0'; + if (room_left < ((first_unused - cp) + + __alignof__ (char *))) + { + free (old_line); + goto no_more_room; + } + room_left -= ((first_unused - cp) + + __alignof__ (char *)); + ++result->alias_members_len; + } + } + while (*line != '\0'); + } + fclose (listfile); + + first_unused[room_left - 1] = '\0'; + strncpy (first_unused, old_line, room_left); + + free (old_line); + line = first_unused; + + if (first_unused[room_left - 1] != '\0') + goto no_more_room; + } + } + } + + if (*line == '\0') + { + /* Get the next line. But we must be careful. We + must not read the whole line at once since it + might belong to the current alias. Simply read + the first character. If it is a white space we + have a continuation line. Otherwise it is the + beginning of a new alias and we can push back the + just read character. */ + int ch; + + ch = fgetc_unlocked (stream); + if (ch == EOF || ch == '\n' || !isspace (ch)) + { + size_t cnt; + + /* Now prepare the return. Provide string + pointers for the currently selected aliases. */ + if (ch != EOF) + ungetc (ch, stream); + + /* Adjust the pointer so it is aligned for + storing pointers. */ + first_unused += __alignof__ (char *) - 1; + first_unused -= ((first_unused - (char *) 0) + % __alignof__ (char *)); + result->alias_members = (char **) first_unused; + + /* Compute addresses of alias entry strings. */ + cp = result->alias_name; + for (cnt = 0; cnt < result->alias_members_len; ++cnt) + { + cp = strchr (cp, '\0') + 1; + result->alias_members[cnt] = cp; + } + + status = (result->alias_members_len == 0 + ? NSS_STATUS_RETURN : NSS_STATUS_SUCCESS); + break; + } + + /* The just read character is a white space and so + can be ignored. */ + first_unused[room_left - 1] = '\xff'; + line = fgets_unlocked (first_unused, room_left, stream); + if (first_unused[room_left - 1] != '\xff') + goto no_more_room; + cp = strpbrk (line, "#\n"); + if (cp != NULL) + *cp = '\0'; + } + } + } + + if (status != NSS_STATUS_NOTFOUND) + /* We read something. In any case break here. */ + break; + } + + return status; +} + + +enum nss_status +_nss_files_getaliasent_r (struct aliasent *result, char *buffer, size_t buflen, + int *errnop) +{ + /* Return next entry in host file. */ + enum nss_status status = NSS_STATUS_SUCCESS; + + __libc_lock_lock (lock); + + /* Be prepared that the set*ent function was not called before. */ + if (stream == NULL) + status = internal_setent (&stream); + + if (status == NSS_STATUS_SUCCESS) + { + result->alias_local = 1; + + /* Read lines until we get a definite result. */ + do + status = get_next_alias (stream, NULL, result, buffer, buflen, errnop); + while (status == NSS_STATUS_RETURN); + } + + __libc_lock_unlock (lock); + + return status; +} + + +enum nss_status +_nss_files_getaliasbyname_r (const char *name, struct aliasent *result, + char *buffer, size_t buflen, int *errnop) +{ + /* Return next entry in host file. */ + enum nss_status status = NSS_STATUS_SUCCESS; + FILE *stream = NULL; + + if (name == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + /* Open the stream. */ + status = internal_setent (&stream); + + if (status == NSS_STATUS_SUCCESS) + { + result->alias_local = 1; + + /* Read lines until we get a definite result. */ + do + status = get_next_alias (stream, name, result, buffer, buflen, errnop); + while (status == NSS_STATUS_RETURN); + } + + internal_endent (&stream); + + return status; +} diff --git a/REORG.TODO/nss/nss_files/files-ethers.c b/REORG.TODO/nss/nss_files/files-ethers.c new file mode 100644 index 0000000000..6f5c02636f --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-ethers.c @@ -0,0 +1,67 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <netinet/ether.h> +#include <netinet/if_ether.h> + +struct etherent_data {}; + +#define ENTNAME etherent +#define DATABASE "ethers" +#include "files-parse.c" +LINE_PARSER +("#", + /* Read the ethernet address: 6 x 8bit hexadecimal number. */ + { + size_t cnt; + + for (cnt = 0; cnt < 6; ++cnt) + { + unsigned int number; + + if (cnt < 5) + INT_FIELD (number, ISCOLON , 0, 16, (unsigned int)) + else + INT_FIELD (number, isspace, 1, 16, (unsigned int)) + + if (number > 0xff) + return 0; + result->e_addr.ether_addr_octet[cnt] = number; + } + }; + STRING_FIELD (result->e_name, isspace, 1); + ) + + +#include GENERIC + +DB_LOOKUP (hostton, '.', 0, ("%s", name), + { + if (__strcasecmp (result->e_name, name) == 0) + break; + }, const char *name) + +DB_LOOKUP (ntohost, '=', 18, ("%x:%x:%x:%x:%x:%x", + addr->ether_addr_octet[0], addr->ether_addr_octet[1], + addr->ether_addr_octet[2], addr->ether_addr_octet[3], + addr->ether_addr_octet[4], addr->ether_addr_octet[5]), + { + if (memcmp (&result->e_addr, addr, + sizeof (struct ether_addr)) == 0) + break; + }, const struct ether_addr *addr) diff --git a/REORG.TODO/nss/nss_files/files-grp.c b/REORG.TODO/nss/nss_files/files-grp.c new file mode 100644 index 0000000000..ff8b27f2b3 --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-grp.c @@ -0,0 +1,44 @@ +/* Group file parser in nss_files module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <grp.h> + +#define STRUCTURE group +#define ENTNAME grent +#define DATABASE "group" +struct grent_data {}; + +/* Our parser function is already defined in fgetgrent.c, so use that. + to parse lines from the database file. */ +#define EXTERN_PARSER +#include "files-parse.c" +#include GENERIC + +DB_LOOKUP (grnam, '.', 0, ("%s", name), + { + if (name[0] != '-' && name[0] != '+' + && ! strcmp (name, result->gr_name)) + break; + }, const char *name) + +DB_LOOKUP (grgid, '=', 20, ("%lu", (unsigned long int) gid), + { + if (result->gr_gid == gid && result->gr_name[0] != '+' + && result->gr_name[0] != '-') + break; + }, gid_t gid) diff --git a/REORG.TODO/nss/nss_files/files-hosts.c b/REORG.TODO/nss/nss_files/files-hosts.c new file mode 100644 index 0000000000..bccb6a5780 --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-hosts.c @@ -0,0 +1,482 @@ +/* Hosts file parser in nss_files module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <assert.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <netdb.h> +#include <resolv/resolv-internal.h> + + +/* Get implementation for some internal functions. */ +#include "../resolv/mapv4v6addr.h" +#include "../resolv/res_hconf.h" + + +#define ENTNAME hostent +#define DATABASE "hosts" +#define NEED_H_ERRNO + +#define EXTRA_ARGS , af, flags +#define EXTRA_ARGS_DECL , int af, int flags + +#define ENTDATA hostent_data +struct hostent_data + { + unsigned char host_addr[16]; /* IPv4 or IPv6 address. */ + char *h_addr_ptrs[2]; /* Points to that and null terminator. */ + }; + +#define TRAILING_LIST_MEMBER h_aliases +#define TRAILING_LIST_SEPARATOR_P isspace +#include "files-parse.c" +LINE_PARSER +("#", + { + char *addr; + + STRING_FIELD (addr, isspace, 1); + + /* Parse address. */ + if (inet_pton (af == AF_UNSPEC ? AF_INET : af, addr, entdata->host_addr) + > 0) + af = af == AF_UNSPEC ? AF_INET : af; + else + { + if (af == AF_INET6 && (flags & AI_V4MAPPED) != 0 + && inet_pton (AF_INET, addr, entdata->host_addr) > 0) + map_v4v6_address ((char *) entdata->host_addr, + (char *) entdata->host_addr); + else if (af == AF_INET + && inet_pton (AF_INET6, addr, entdata->host_addr) > 0) + { + if (IN6_IS_ADDR_V4MAPPED (entdata->host_addr)) + memcpy (entdata->host_addr, entdata->host_addr + 12, INADDRSZ); + else if (IN6_IS_ADDR_LOOPBACK (entdata->host_addr)) + { + in_addr_t localhost = htonl (INADDR_LOOPBACK); + memcpy (entdata->host_addr, &localhost, sizeof (localhost)); + } + else + /* Illegal address: ignore line. */ + return 0; + } + else if (af == AF_UNSPEC + && inet_pton (AF_INET6, addr, entdata->host_addr) > 0) + af = AF_INET6; + else + /* Illegal address: ignore line. */ + return 0; + } + + /* We always return entries of the requested form. */ + result->h_addrtype = af; + result->h_length = af == AF_INET ? INADDRSZ : IN6ADDRSZ; + + /* Store a pointer to the address in the expected form. */ + entdata->h_addr_ptrs[0] = (char *) entdata->host_addr; + entdata->h_addr_ptrs[1] = NULL; + result->h_addr_list = entdata->h_addr_ptrs; + + STRING_FIELD (result->h_name, isspace, 1); + }) + +#define EXTRA_ARGS_VALUE \ + , (res_use_inet6 () ? AF_INET6 : AF_INET), \ + (res_use_inet6 () ? AI_V4MAPPED : 0) +#include "files-XXX.c" +#undef EXTRA_ARGS_VALUE + +/* We only need to consider IPv4 mapped addresses if the input to the + gethostbyaddr() function is an IPv6 address. */ +#define EXTRA_ARGS_VALUE \ + , af, (len == IN6ADDRSZ ? AI_V4MAPPED : 0) +DB_LOOKUP (hostbyaddr, ,,, + { + if (result->h_length == (int) len + && ! memcmp (addr, result->h_addr_list[0], len)) + break; + }, const void *addr, socklen_t len, int af) +#undef EXTRA_ARGS_VALUE + +enum nss_status +_nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *herrnop, int32_t *ttlp, char **canonp) +{ + FILE *stream = NULL; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct hostent_data); + buffer += pad; + buflen = buflen > pad ? buflen - pad : 0; + + /* Open file. */ + enum nss_status status = internal_setent (&stream); + + if (status == NSS_STATUS_SUCCESS) + { + /* XXX Is using _res to determine whether we want to convert IPv4 + addresses to IPv6 addresses really the right thing to do? */ + int flags = (res_use_inet6 () ? AI_V4MAPPED : 0); + + while ((status = internal_getent (stream, result, buffer, buflen, errnop, + herrnop, af, flags)) + == NSS_STATUS_SUCCESS) + { + LOOKUP_NAME_CASE (h_name, h_aliases) + } + + if (status == NSS_STATUS_SUCCESS + && _res_hconf.flags & HCONF_FLAG_MULTI) + { + /* We have to get all host entries from the file. */ + size_t tmp_buflen = MIN (buflen, 4096); + char tmp_buffer_stack[tmp_buflen] + __attribute__ ((__aligned__ (__alignof__ (struct hostent_data)))); + char *tmp_buffer = tmp_buffer_stack; + struct hostent tmp_result_buf; + int naddrs = 1; + int naliases = 0; + char *bufferend; + bool tmp_buffer_malloced = false; + + while (result->h_aliases[naliases] != NULL) + ++naliases; + + bufferend = (char *) &result->h_aliases[naliases + 1]; + + again: + while ((status = internal_getent (stream, &tmp_result_buf, tmp_buffer, + tmp_buflen, errnop, herrnop, af, + flags)) + == NSS_STATUS_SUCCESS) + { + int matches = 1; + struct hostent *old_result = result; + result = &tmp_result_buf; + /* The following piece is a bit clumsy but we want to use the + `LOOKUP_NAME_CASE' value. The optimizer should do its + job. */ + do + { + LOOKUP_NAME_CASE (h_name, h_aliases) + result = old_result; + } + while ((matches = 0)); + + if (matches) + { + /* We could be very clever and try to recycle a few bytes + in the buffer instead of generating new arrays. But + we are not doing this here since it's more work than + it's worth. Simply let the user provide a bit bigger + buffer. */ + char **new_h_addr_list; + char **new_h_aliases; + int newaliases = 0; + size_t newstrlen = 0; + int cnt; + + /* Count the new aliases and the length of the strings. */ + while (tmp_result_buf.h_aliases[newaliases] != NULL) + { + char *cp = tmp_result_buf.h_aliases[newaliases]; + ++newaliases; + newstrlen += strlen (cp) + 1; + } + /* If the real name is different add it also to the + aliases. This means that there is a duplication + in the alias list but this is really the user's + problem. */ + if (strcmp (old_result->h_name, + tmp_result_buf.h_name) != 0) + { + ++newaliases; + newstrlen += strlen (tmp_result_buf.h_name) + 1; + } + + /* Make sure bufferend is aligned. */ + assert ((bufferend - (char *) 0) % sizeof (char *) == 0); + + /* Now we can check whether the buffer is large enough. + 16 is the maximal size of the IP address. */ + if (bufferend + 16 + (naddrs + 2) * sizeof (char *) + + roundup (newstrlen, sizeof (char *)) + + (naliases + newaliases + 1) * sizeof (char *) + >= buffer + buflen) + { + *errnop = ERANGE; + *herrnop = NETDB_INTERNAL; + status = NSS_STATUS_TRYAGAIN; + goto out; + } + + new_h_addr_list = + (char **) (bufferend + + roundup (newstrlen, sizeof (char *)) + + 16); + new_h_aliases = + (char **) ((char *) new_h_addr_list + + (naddrs + 2) * sizeof (char *)); + + /* Copy the old data in the new arrays. */ + for (cnt = 0; cnt < naddrs; ++cnt) + new_h_addr_list[cnt] = old_result->h_addr_list[cnt]; + + for (cnt = 0; cnt < naliases; ++cnt) + new_h_aliases[cnt] = old_result->h_aliases[cnt]; + + /* Store the new strings. */ + cnt = 0; + while (tmp_result_buf.h_aliases[cnt] != NULL) + { + new_h_aliases[naliases++] = bufferend; + bufferend = (__stpcpy (bufferend, + tmp_result_buf.h_aliases[cnt]) + + 1); + ++cnt; + } + + if (cnt < newaliases) + { + new_h_aliases[naliases++] = bufferend; + bufferend = __stpcpy (bufferend, + tmp_result_buf.h_name) + 1; + } + + /* Final NULL pointer. */ + new_h_aliases[naliases] = NULL; + + /* Round up the buffer end address. */ + bufferend += (sizeof (char *) + - ((bufferend - (char *) 0) + % sizeof (char *))) % sizeof (char *); + + /* Now the new address. */ + new_h_addr_list[naddrs++] = + memcpy (bufferend, tmp_result_buf.h_addr, + tmp_result_buf.h_length); + + /* Also here a final NULL pointer. */ + new_h_addr_list[naddrs] = NULL; + + /* Store the new array pointers. */ + old_result->h_aliases = new_h_aliases; + old_result->h_addr_list = new_h_addr_list; + + /* Compute the new buffer end. */ + bufferend = (char *) &new_h_aliases[naliases + 1]; + assert (bufferend <= buffer + buflen); + + result = old_result; + } + } + + if (status == NSS_STATUS_TRYAGAIN) + { + size_t newsize = 2 * tmp_buflen; + if (tmp_buffer_malloced) + { + char *newp = realloc (tmp_buffer, newsize); + if (newp != NULL) + { + assert ((((uintptr_t) newp) + & (__alignof__ (struct hostent_data) - 1)) + == 0); + tmp_buffer = newp; + tmp_buflen = newsize; + goto again; + } + } + else if (!__libc_use_alloca (buflen + newsize)) + { + tmp_buffer = malloc (newsize); + if (tmp_buffer != NULL) + { + assert ((((uintptr_t) tmp_buffer) + & (__alignof__ (struct hostent_data) - 1)) + == 0); + tmp_buffer_malloced = true; + tmp_buflen = newsize; + goto again; + } + } + else + { + tmp_buffer + = extend_alloca (tmp_buffer, tmp_buflen, + newsize + + __alignof__ (struct hostent_data)); + tmp_buffer = (char *) (((uintptr_t) tmp_buffer + + __alignof__ (struct hostent_data) + - 1) + & ~(__alignof__ (struct hostent_data) + - 1)); + goto again; + } + } + else + status = NSS_STATUS_SUCCESS; + out: + if (tmp_buffer_malloced) + free (tmp_buffer); + } + + internal_endent (&stream); + } + + if (canonp && status == NSS_STATUS_SUCCESS) + *canonp = result->h_name; + + return status; +} + +enum nss_status +_nss_files_gethostbyname_r (const char *name, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *herrnop) +{ + int af = (res_use_inet6 () ? AF_INET6 : AF_INET); + + return _nss_files_gethostbyname3_r (name, af, result, buffer, buflen, + errnop, herrnop, NULL, NULL); +} + +enum nss_status +_nss_files_gethostbyname2_r (const char *name, int af, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *herrnop) +{ + return _nss_files_gethostbyname3_r (name, af, result, buffer, buflen, + errnop, herrnop, NULL, NULL); +} + +enum nss_status +_nss_files_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, + char *buffer, size_t buflen, int *errnop, + int *herrnop, int32_t *ttlp) +{ + FILE *stream = NULL; + + /* Open file. */ + enum nss_status status = internal_setent (&stream); + + if (status == NSS_STATUS_SUCCESS) + { + bool any = false; + bool got_canon = false; + while (1) + { + /* Align the buffer for the next record. */ + uintptr_t pad = (-(uintptr_t) buffer + % __alignof__ (struct hostent_data)); + buffer += pad; + buflen = buflen > pad ? buflen - pad : 0; + + struct hostent result; + status = internal_getent (stream, &result, buffer, buflen, errnop, + herrnop, AF_UNSPEC, 0); + if (status != NSS_STATUS_SUCCESS) + break; + + int naliases = 0; + if (__strcasecmp (name, result.h_name) != 0) + { + for (; result.h_aliases[naliases] != NULL; ++naliases) + if (! __strcasecmp (name, result.h_aliases[naliases])) + break; + if (result.h_aliases[naliases] == NULL) + continue; + + /* We know this alias exist. Count it. */ + ++naliases; + } + + /* Determine how much memory has been used so far. */ + // XXX It is not necessary to preserve the aliases array + while (result.h_aliases[naliases] != NULL) + ++naliases; + char *bufferend = (char *) &result.h_aliases[naliases + 1]; + assert (buflen >= bufferend - buffer); + buflen -= bufferend - buffer; + buffer = bufferend; + + /* We found something. */ + any = true; + + /* Create the record the caller expects. There is only one + address. */ + assert (result.h_addr_list[1] == NULL); + if (*pat == NULL) + { + uintptr_t pad = (-(uintptr_t) buffer + % __alignof__ (struct gaih_addrtuple)); + buffer += pad; + buflen = buflen > pad ? buflen - pad : 0; + + if (__builtin_expect (buflen < sizeof (struct gaih_addrtuple), + 0)) + { + *errnop = ERANGE; + *herrnop = NETDB_INTERNAL; + status = NSS_STATUS_TRYAGAIN; + break; + } + + *pat = (struct gaih_addrtuple *) buffer; + buffer += sizeof (struct gaih_addrtuple); + buflen -= sizeof (struct gaih_addrtuple); + } + + (*pat)->next = NULL; + (*pat)->name = got_canon ? NULL : result.h_name; + got_canon = true; + (*pat)->family = result.h_addrtype; + memcpy ((*pat)->addr, result.h_addr_list[0], result.h_length); + (*pat)->scopeid = 0; + + pat = &((*pat)->next); + + /* If we only look for the first matching entry we are done. */ + if ((_res_hconf.flags & HCONF_FLAG_MULTI) == 0) + break; + } + + /* If we have to look for multiple records and found one, this + is a success. */ + if (status == NSS_STATUS_NOTFOUND && any) + { + assert ((_res_hconf.flags & HCONF_FLAG_MULTI) != 0); + status = NSS_STATUS_SUCCESS; + } + + internal_endent (&stream); + } + else if (status == NSS_STATUS_TRYAGAIN) + { + *errnop = errno; + *herrnop = TRY_AGAIN; + } + else + { + *errnop = errno; + *herrnop = NO_DATA; + } + + return status; +} diff --git a/REORG.TODO/nss/nss_files/files-init.c b/REORG.TODO/nss/nss_files/files-init.c new file mode 100644 index 0000000000..9243d86cc9 --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-init.c @@ -0,0 +1,64 @@ +/* Initialization in nss_files module. + Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifdef USE_NSCD + +#include <string.h> +#include <nscd/nscd.h> + +#define PWD_FILENAME "/etc/passwd" +define_traced_file (pwd, PWD_FILENAME); + +#define GRP_FILENAME "/etc/group" +define_traced_file (grp, GRP_FILENAME); + +#define HST_FILENAME "/etc/hosts" +define_traced_file (hst, HST_FILENAME); + +#define RESOLV_FILENAME "/etc/resolv.conf" +define_traced_file (resolv, RESOLV_FILENAME); + +#define SERV_FILENAME "/etc/services" +define_traced_file (serv, SERV_FILENAME); + +#define NETGR_FILENAME "/etc/netgroup" +define_traced_file (netgr, NETGR_FILENAME); + +void +_nss_files_init (void (*cb) (size_t, struct traced_file *)) +{ + init_traced_file (&pwd_traced_file.file, PWD_FILENAME, 0); + cb (pwddb, &pwd_traced_file.file); + + init_traced_file (&grp_traced_file.file, GRP_FILENAME, 0); + cb (grpdb, &grp_traced_file.file); + + init_traced_file (&hst_traced_file.file, HST_FILENAME, 0); + cb (hstdb, &hst_traced_file.file); + + init_traced_file (&resolv_traced_file.file, RESOLV_FILENAME, 1); + cb (hstdb, &resolv_traced_file.file); + + init_traced_file (&serv_traced_file.file, SERV_FILENAME, 0); + cb (servdb, &serv_traced_file.file); + + init_traced_file (&netgr_traced_file.file, NETGR_FILENAME, 0); + cb (netgrdb, &netgr_traced_file.file); +} + +#endif diff --git a/REORG.TODO/nss/nss_files/files-initgroups.c b/REORG.TODO/nss/nss_files/files-initgroups.c new file mode 100644 index 0000000000..27cd8ece40 --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-initgroups.c @@ -0,0 +1,142 @@ +/* Initgroups handling in nss_files module. + Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <alloca.h> +#include <errno.h> +#include <grp.h> +#include <nss.h> +#include <stdio_ext.h> +#include <string.h> +#include <sys/param.h> +#include <stdbool.h> +#include <stdlib.h> + +enum nss_status +_nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, + long int *size, gid_t **groupsp, long int limit, + int *errnop) +{ + FILE *stream = fopen ("/etc/group", "rce"); + if (stream == NULL) + { + *errnop = errno; + return *errnop == ENOMEM ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + } + + /* No other thread using this stream. */ + __fsetlocking (stream, FSETLOCKING_BYCALLER); + + char *line = NULL; + size_t linelen = 0; + enum nss_status status = NSS_STATUS_SUCCESS; + bool any = false; + + size_t buflen = 1024; + void *buffer = alloca (buflen); + bool buffer_use_malloc = false; + + gid_t *groups = *groupsp; + + /* We have to iterate over the entire file. */ + while (1) + { + fpos_t pos; + fgetpos (stream, &pos); + ssize_t n = getline (&line, &linelen, stream); + if (n < 0) + { + if (! feof_unlocked (stream)) + status = ((*errnop = errno) == ENOMEM + ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL); + break; + } + + struct group grp; + int res = _nss_files_parse_grent (line, &grp, buffer, buflen, errnop); + if (res == -1) + { + size_t newbuflen = 2 * buflen; + if (buffer_use_malloc || ! __libc_use_alloca (buflen + newbuflen)) + { + void *newbuf = realloc (buffer_use_malloc ? buffer : NULL, + newbuflen); + if (newbuf == NULL) + { + *errnop = ENOMEM; + status = NSS_STATUS_TRYAGAIN; + goto out; + } + buffer = newbuf; + buflen = newbuflen; + buffer_use_malloc = true; + } + else + buffer = extend_alloca (buffer, buflen, newbuflen); + /* Reread current line, the parser has clobbered it. */ + fsetpos (stream, &pos); + continue; + } + + if (res > 0 && grp.gr_gid != group) + for (char **m = grp.gr_mem; *m != NULL; ++m) + if (strcmp (*m, user) == 0) + { + /* Matches user. Insert this group. */ + if (*start == *size) + { + /* Need a bigger buffer. */ + if (limit > 0 && *size == limit) + /* We reached the maximum. */ + goto out; + + long int newsize; + if (limit <= 0) + newsize = 2 * *size; + else + newsize = MIN (limit, 2 * *size); + + gid_t *newgroups = realloc (groups, + newsize * sizeof (*groups)); + if (newgroups == NULL) + { + *errnop = ENOMEM; + status = NSS_STATUS_TRYAGAIN; + goto out; + } + *groupsp = groups = newgroups; + *size = newsize; + } + + groups[*start] = grp.gr_gid; + *start += 1; + any = true; + + break; + } + } + + out: + /* Free memory. */ + if (buffer_use_malloc) + free (buffer); + free (line); + + fclose (stream); + + return status == NSS_STATUS_SUCCESS && !any ? NSS_STATUS_NOTFOUND : status; +} diff --git a/REORG.TODO/nss/nss_files/files-key.c b/REORG.TODO/nss/nss_files/files-key.c new file mode 100644 index 0000000000..11a574a0b1 --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-key.c @@ -0,0 +1,111 @@ +/* Public key file parser in nss_files module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <netdb.h> +#include <rpc/key_prot.h> +#include <rpc/des_crypt.h> +#include "nsswitch.h" + +#define DATAFILE "/etc/publickey" + + +static enum nss_status +search (const char *netname, char *result, int *errnop, int secret) +{ + FILE *stream = fopen (DATAFILE, "rce"); + if (stream == NULL) + return errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + + for (;;) + { + char buffer[HEXKEYBYTES * 2 + KEYCHECKSUMSIZE + MAXNETNAMELEN + 17]; + char *p; + char *save_ptr; + + buffer[sizeof (buffer) - 1] = '\xff'; + p = fgets_unlocked (buffer, sizeof (buffer), stream); + if (p == NULL) + { + /* End of file or read error. */ + *errnop = errno; + fclose (stream); + return NSS_STATUS_NOTFOUND; + } + else if (buffer[sizeof (buffer) - 1] != '\xff') + { + /* Invalid line in file? Skip remainder of line. */ + if (buffer[sizeof (buffer) - 2] != '\0') + while (getc_unlocked (stream) != '\n') + continue; + continue; + } + + /* Parse line. */ + p = __strtok_r (buffer, "# \t:\n", &save_ptr); + if (p == NULL) /* Skip empty and comment lines. */ + continue; + if (strcmp (p, netname) != 0) + continue; + + /* A hit! Find the field we want and return. */ + p = __strtok_r (NULL, ":\n", &save_ptr); + if (p == NULL) /* malformed line? */ + continue; + if (secret) + p = __strtok_r (NULL, ":\n", &save_ptr); + if (p == NULL) /* malformed line? */ + continue; + fclose (stream); + strcpy (result, p); + return NSS_STATUS_SUCCESS; + } +} + +enum nss_status +_nss_files_getpublickey (const char *netname, char *pkey, int *errnop) +{ + return search (netname, pkey, errnop, 0); +} + +enum nss_status +_nss_files_getsecretkey (const char *netname, char *skey, char *passwd, + int *errnop) +{ + enum nss_status status; + char buf[HEXKEYBYTES + KEYCHECKSUMSIZE + 16]; + + skey[0] = 0; + + status = search (netname, buf, errnop, 1); + if (status != NSS_STATUS_SUCCESS) + return status; + + if (!xdecrypt (buf, passwd)) + return NSS_STATUS_SUCCESS; + + if (memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) != 0) + return NSS_STATUS_SUCCESS; + + buf[HEXKEYBYTES] = 0; + strcpy (skey, buf); + + return NSS_STATUS_SUCCESS; +} diff --git a/REORG.TODO/nss/nss_files/files-netgrp.c b/REORG.TODO/nss/nss_files/files-netgrp.c new file mode 100644 index 0000000000..009ce02432 --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-netgrp.c @@ -0,0 +1,294 @@ +/* Netgroup file parser in nss_files modules. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <stdlib.h> +#include <string.h> +#include "nsswitch.h" +#include "netgroup.h" + +#define DATAFILE "/etc/netgroup" + +libnss_files_hidden_proto (_nss_files_endnetgrent) + +#define EXPAND(needed) \ + do \ + { \ + size_t old_cursor = result->cursor - result->data; \ + void *old_data = result->data; \ + \ + result->data_size += 512 > 2 * needed ? 512 : 2 * needed; \ + result->data = realloc (result->data, result->data_size); \ + \ + if (result->data == NULL) \ + { \ + free (old_data); \ + status = NSS_STATUS_UNAVAIL; \ + goto the_end; \ + } \ + \ + result->cursor = result->data + old_cursor; \ + } \ + while (0) + + +enum nss_status +_nss_files_setnetgrent (const char *group, struct __netgrent *result) +{ + FILE *fp; + enum nss_status status; + + if (group[0] == '\0') + return NSS_STATUS_UNAVAIL; + + /* Find the netgroups file and open it. */ + fp = fopen (DATAFILE, "rce"); + if (fp == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + else + { + /* Read the file line by line and try to find the description + GROUP. We must take care for long lines. */ + char *line = NULL; + size_t line_len = 0; + const ssize_t group_len = strlen (group); + + status = NSS_STATUS_NOTFOUND; + result->cursor = result->data; + + __fsetlocking (fp, FSETLOCKING_BYCALLER); + + while (!feof_unlocked (fp)) + { + ssize_t curlen = getline (&line, &line_len, fp); + int found; + + if (curlen < 0) + { + status = NSS_STATUS_NOTFOUND; + break; + } + + found = (curlen > group_len && strncmp (line, group, group_len) == 0 + && isspace (line[group_len])); + + /* Read the whole line (including continuation) and store it + if FOUND in nonzero. Otherwise we don't need it. */ + if (found) + { + /* Store the data from the first line. */ + EXPAND (curlen - group_len); + memcpy (result->cursor, &line[group_len + 1], + curlen - group_len); + result->cursor += (curlen - group_len) - 1; + } + + while (curlen > 1 && line[curlen - 1] == '\n' + && line[curlen - 2] == '\\') + { + /* Yes, we have a continuation line. */ + if (found) + /* Remove these characters from the stored line. */ + result->cursor -= 2; + + /* Get next line. */ + curlen = getline (&line, &line_len, fp); + if (curlen <= 0) + break; + + if (found) + { + /* Make sure we have enough room. */ + EXPAND (1 + curlen + 1); + + /* Add separator in case next line starts immediately. */ + *result->cursor++ = ' '; + + /* Copy new line. */ + memcpy (result->cursor, line, curlen + 1); + result->cursor += curlen; + } + } + + if (found) + { + /* Now we have read the line. */ + status = NSS_STATUS_SUCCESS; + result->cursor = result->data; + result->first = 1; + break; + } + } + + the_end: + /* We don't need the file and the line buffer anymore. */ + free (line); + fclose (fp); + + if (status != NSS_STATUS_SUCCESS) + _nss_files_endnetgrent (result); + } + + return status; +} + + +enum nss_status +_nss_files_endnetgrent (struct __netgrent *result) +{ + /* Free allocated memory for data if some is present. */ + free (result->data); + result->data = NULL; + result->data_size = 0; + result->cursor = NULL; + return NSS_STATUS_SUCCESS; +} +libnss_files_hidden_def (_nss_files_endnetgrent) + +static char * +strip_whitespace (char *str) +{ + char *cp = str; + + /* Skip leading spaces. */ + while (isspace (*cp)) + cp++; + + str = cp; + while (*cp != '\0' && ! isspace(*cp)) + cp++; + + /* Null-terminate, stripping off any trailing spaces. */ + *cp = '\0'; + + return *str == '\0' ? NULL : str; +} + +enum nss_status +_nss_netgroup_parseline (char **cursor, struct __netgrent *result, + char *buffer, size_t buflen, int *errnop) +{ + enum nss_status status; + const char *host, *user, *domain; + char *cp = *cursor; + + /* Some sanity checks. */ + if (cp == NULL) + return NSS_STATUS_NOTFOUND; + + /* First skip leading spaces. */ + while (isspace (*cp)) + ++cp; + + if (*cp != '(') + { + /* We have a list of other netgroups. */ + char *name = cp; + + while (*cp != '\0' && ! isspace (*cp)) + ++cp; + + if (name != cp) + { + /* It is another netgroup name. */ + int last = *cp == '\0'; + + result->type = group_val; + result->val.group = name; + *cp = '\0'; + if (! last) + ++cp; + *cursor = cp; + result->first = 0; + + return NSS_STATUS_SUCCESS; + } + + return result->first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN; + } + + /* Match host name. */ + host = ++cp; + while (*cp != ',') + if (*cp++ == '\0') + return result->first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN; + + /* Match user name. */ + user = ++cp; + while (*cp != ',') + if (*cp++ == '\0') + return result->first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN; + + /* Match domain name. */ + domain = ++cp; + while (*cp != ')') + if (*cp++ == '\0') + return result->first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN; + ++cp; + + + /* When we got here we have found an entry. Before we can copy it + to the private buffer we have to make sure it is big enough. */ + if (cp - host > buflen) + { + *errnop = ERANGE; + status = NSS_STATUS_TRYAGAIN; + } + else + { + memcpy (buffer, host, cp - host); + result->type = triple_val; + + buffer[(user - host) - 1] = '\0'; /* Replace ',' with '\0'. */ + result->val.triple.host = strip_whitespace (buffer); + + buffer[(domain - host) - 1] = '\0'; /* Replace ',' with '\0'. */ + result->val.triple.user = strip_whitespace (buffer + (user - host)); + + buffer[(cp - host) - 1] = '\0'; /* Replace ')' with '\0'. */ + result->val.triple.domain = strip_whitespace (buffer + (domain - host)); + + status = NSS_STATUS_SUCCESS; + + /* Remember where we stopped reading. */ + *cursor = cp; + + result->first = 0; + } + + return status; +} +libnss_files_hidden_def (_nss_netgroup_parseline) + + +enum nss_status +_nss_files_getnetgrent_r (struct __netgrent *result, char *buffer, + size_t buflen, int *errnop) +{ + enum nss_status status; + + status = _nss_netgroup_parseline (&result->cursor, result, buffer, buflen, + errnop); + + return status; +} diff --git a/REORG.TODO/nss/nss_files/files-network.c b/REORG.TODO/nss/nss_files/files-network.c new file mode 100644 index 0000000000..1fbd60fcf2 --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-network.c @@ -0,0 +1,88 @@ +/* Networks file parser in nss_files module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <stdint.h> + +#define ENTNAME netent +#define DATABASE "networks" +#define NEED_H_ERRNO + +struct netent_data {}; + +#define TRAILING_LIST_MEMBER n_aliases +#define TRAILING_LIST_SEPARATOR_P isspace +#include "files-parse.c" +LINE_PARSER +("#", + { + char *addr; + char *cp; + int n = 1; + + STRING_FIELD (result->n_name, isspace, 1); + + STRING_FIELD (addr, isspace, 1); + /* 'inet_network' does not add zeroes at the end if the network number + does not four byte values. We add them outselves if necessary. */ + cp = strchr (addr, '.'); + if (cp != NULL) + { + ++n; + cp = strchr (cp + 1, '.'); + if (cp != NULL) + { + ++n; + cp = strchr (cp + 1, '.'); + if (cp != NULL) + ++n; + } + } + if (n < 4) + { + char *newp = (char *) alloca (strlen (addr) + (4 - n) * 2 + 1); + cp = stpcpy (newp, addr); + do + { + *cp++ = '.'; + *cp++ = '0'; + } + while (++n < 4); + *cp = '\0'; + addr = newp; + } + result->n_net = inet_network (addr); + result->n_addrtype = AF_INET; + + }) + +#include "files-XXX.c" + +DB_LOOKUP (netbyname, ,,, + LOOKUP_NAME_CASE (n_name, n_aliases), + const char *name) + +DB_LOOKUP (netbyaddr, ,,, + { + if ((type == AF_UNSPEC || result->n_addrtype == type) + && result->n_net == net) + /* Bingo! */ + break; + }, uint32_t net, int type) diff --git a/REORG.TODO/nss/nss_files/files-parse.c b/REORG.TODO/nss/nss_files/files-parse.c new file mode 100644 index 0000000000..b31ff9e17b --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-parse.c @@ -0,0 +1,335 @@ +/* Common code for file-based database parsers in nss_files module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <stdint.h> + +/* These symbols are defined by the including source file: + + ENTNAME -- database name of the structure and functions (hostent, pwent). + STRUCTURE -- struct name, define only if not ENTNAME (passwd, group). + DATABASE -- string of the database file's name ("hosts", "passwd"). + + ENTDATA -- if defined, `struct ENTDATA' is used by the parser to store + things pointed to by the resultant `struct STRUCTURE'. + + NEED_H_ERRNO - defined iff an arg `int *herrnop' is used. + + EXTRA_ARGS -- defined iff extra parameters must be passed to the parser + EXTRA_ARGS_DECL -- declaration for these extra parameters + EXTRA_ARGS_VALUE -- values to be passed for these parameters + + Also see files-XXX.c. */ + +#ifndef EXTRA_ARGS +# define EXTRA_ARGS +# define EXTRA_ARGS_DECL +# define EXTRA_ARGS_VALUE +#endif + +#define CONCAT(a,b) CONCAT1(a,b) +#define CONCAT1(a,b) a##b + +#ifndef STRUCTURE +# define STRUCTURE ENTNAME +#endif + + +struct parser_data + { +#ifdef ENTDATA + struct ENTDATA entdata; +# define ENTDATA_DECL(data) struct ENTDATA *const entdata = &data->entdata; +#else +# define ENTDATA_DECL(data) +#endif + char linebuffer[0]; + }; + +#ifdef ENTDATA +/* The function can't be exported, because the entdata structure + is defined only in files-foo.c. */ +# define parser_stclass static +# define nss_files_parse_hidden_def(name) +#else +/* Export the line parser function so it can be used in nss_db. */ +# define parser_stclass /* Global */ +# define parse_line CONCAT(_nss_files_parse_,ENTNAME) +# if IS_IN (libc) +/* We are defining one of the functions that actually lives in libc + because it is used to implement fget*ent and suchlike. */ +# define nss_files_parse_hidden_def(name) libc_hidden_def (name) +# else +# define nss_files_parse_hidden_def(name) libnss_files_hidden_def (name) +# endif +#endif + + +#ifdef EXTERN_PARSER + +/* The parser is defined in a different module. */ +extern int parse_line (char *line, struct STRUCTURE *result, + struct parser_data *data, size_t datalen, int *errnop + EXTRA_ARGS_DECL); + +# define LINE_PARSER(EOLSET, BODY) /* Do nothing */ + +#else + +/* Define a line parsing function. */ + +# define LINE_PARSER(EOLSET, BODY) \ +parser_stclass int \ +parse_line (char *line, struct STRUCTURE *result, \ + struct parser_data *data, size_t datalen, int *errnop \ + EXTRA_ARGS_DECL) \ +{ \ + ENTDATA_DECL (data) \ + BUFFER_PREPARE \ + char *p = strpbrk (line, EOLSET "\n"); \ + if (p != NULL) \ + *p = '\0'; \ + BODY; \ + TRAILING_LIST_PARSER; \ + return 1; \ +} \ +nss_files_parse_hidden_def (parse_line) + + +# define STRING_FIELD(variable, terminator_p, swallow) \ + { \ + variable = line; \ + while (*line != '\0' && !terminator_p (*line)) \ + ++line; \ + if (*line != '\0') \ + { \ + *line = '\0'; \ + do \ + ++line; \ + while (swallow && terminator_p (*line)); \ + } \ + } + +# define STRING_LIST(variable, terminator_c) \ + { \ + char **list = parse_list (&line, buf_start, buf_end, terminator_c, \ + errnop); \ + if (list) \ + variable = list; \ + else \ + return -1; /* -1 indicates we ran out of space. */ \ + \ + /* Determine the new end of the buffer. */ \ + while (*list != NULL) \ + ++list; \ + buf_start = (char *) (list + 1); \ + } + +/* Helper function. */ +static inline uint32_t +__attribute__ ((always_inline)) +strtou32 (const char *nptr, char **endptr, int base) +{ + unsigned long int val = strtoul (nptr, endptr, base); + + /* Match the 32-bit behavior on 64-bit platforms. */ + if (sizeof (long int) > 4 && val > 0xffffffff) + val = 0xffffffff; + + return val; +} + +# define INT_FIELD(variable, terminator_p, swallow, base, convert) \ + { \ + char *endp; \ + variable = convert (strtou32 (line, &endp, base)); \ + if (endp == line) \ + return 0; \ + else if (terminator_p (*endp)) \ + do \ + ++endp; \ + while (swallow && terminator_p (*endp)); \ + else if (*endp != '\0') \ + return 0; \ + line = endp; \ + } + +# define INT_FIELD_MAYBE_NULL(variable, terminator_p, swallow, base, convert, default) \ + { \ + char *endp; \ + if (*line == '\0') \ + /* We expect some more input, so don't allow the string to end here. */ \ + return 0; \ + variable = convert (strtou32 (line, &endp, base)); \ + if (endp == line) \ + variable = default; \ + if (terminator_p (*endp)) \ + do \ + ++endp; \ + while (swallow && terminator_p (*endp)); \ + else if (*endp != '\0') \ + return 0; \ + line = endp; \ + } + +# define ISCOLON(c) ((c) == ':') + + +# ifndef TRAILING_LIST_MEMBER +# define BUFFER_PREPARE /* Nothing to do. */ +# define TRAILING_LIST_PARSER /* Nothing to do. */ +# else + +# define BUFFER_PREPARE \ + char *buf_start = NULL; \ + char *buf_end = (char *) data + datalen; \ + if (line >= data->linebuffer && line < buf_end) \ + /* Find the end of the line buffer, we will use the space in \ + DATA after it for storing the vector of pointers. */ \ + buf_start = strchr (line, '\0') + 1; \ + else \ + /* LINE does not point within DATA->linebuffer, so that space is \ + not being used for scratch space right now. We can use all of \ + it for the pointer vector storage. */ \ + buf_start = data->linebuffer; \ + +# define TRAILING_LIST_PARSER \ +{ \ + if (buf_start == NULL) \ + { \ + if (line >= data->linebuffer && line < buf_end) \ + /* Find the end of the line buffer, we will use the space in \ + DATA after it for storing the vector of pointers. */ \ + buf_start = strchr (line, '\0') + 1; \ + else \ + /* LINE does not point within DATA->linebuffer, so that space is \ + not being used for scratch space right now. We can use all of \ + it for the pointer vector storage. */ \ + buf_start = data->linebuffer; \ + } \ + \ + char **list = parse_list (&line, buf_start, buf_end, '\0', errnop); \ + if (list) \ + result->TRAILING_LIST_MEMBER = list; \ + else \ + return -1; /* -1 indicates we ran out of space. */ \ +} + +static inline char ** +__attribute ((always_inline)) +parse_list (char **linep, char *eol, char *buf_end, int terminator_c, + int *errnop) +{ + char *line = *linep; + char **list, **p; + + /* Adjust the pointer so it is aligned for storing pointers. */ + eol += __alignof__ (char *) - 1; + eol -= (eol - (char *) 0) % __alignof__ (char *); + /* We will start the storage here for the vector of pointers. */ + list = (char **) eol; + + p = list; + while (1) + { + if ((char *) (p + 2) > buf_end) + { + /* We cannot fit another pointer in the buffer. */ + *errnop = ERANGE; + return NULL; + } + + if (*line == '\0') + break; + if (*line == terminator_c) + { + ++line; + break; + } + + /* Skip leading white space. This might not be portable but useful. */ + while (isspace (*line)) + ++line; + + char *elt = line; + while (1) + { + if (*line == '\0' || *line == terminator_c + || TRAILING_LIST_SEPARATOR_P (*line)) + { + /* End of the next entry. */ + if (line > elt) + /* We really found some data. */ + *p++ = elt; + + /* Terminate string if necessary. */ + if (*line != '\0') + { + char endc = *line; + *line++ = '\0'; + if (endc == terminator_c) + goto out; + } + break; + } + ++line; + } + } + out: + *p = NULL; + *linep = line; + + return list; +} + +# endif /* TRAILING_LIST_MEMBER */ +#endif /* EXTERN_PARSER */ + + +#define LOOKUP_NAME(nameelt, aliaselt) \ +{ \ + char **ap; \ + if (! strcmp (name, result->nameelt)) \ + break; \ + for (ap = result->aliaselt; *ap; ++ap) \ + if (! strcmp (name, *ap)) \ + break; \ + if (*ap) \ + break; \ +} + +#define LOOKUP_NAME_CASE(nameelt, aliaselt) \ +{ \ + char **ap; \ + if (! __strcasecmp (name, result->nameelt)) \ + break; \ + for (ap = result->aliaselt; *ap; ++ap) \ + if (! __strcasecmp (name, *ap)) \ + break; \ + if (*ap) \ + break; \ +} + + +/* This is defined by db-*.c to include "../nss_db/db-XXX.c" instead. */ +#ifndef GENERIC +# define GENERIC "files-XXX.c" +#endif diff --git a/REORG.TODO/nss/nss_files/files-proto.c b/REORG.TODO/nss/nss_files/files-proto.c new file mode 100644 index 0000000000..5402a7a300 --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-proto.c @@ -0,0 +1,46 @@ +/* Protocols file parser in nss_files module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <netdb.h> + + +#define ENTNAME protoent +#define DATABASE "protocols" + +struct protoent_data {}; + +#define TRAILING_LIST_MEMBER p_aliases +#define TRAILING_LIST_SEPARATOR_P isspace +#include "files-parse.c" +LINE_PARSER +("#", + STRING_FIELD (result->p_name, isspace, 1); + INT_FIELD (result->p_proto, isspace, 1, 10,); + ) + +#include GENERIC + +DB_LOOKUP (protobyname, '.', 0, ("%s", name), + LOOKUP_NAME (p_name, p_aliases), + const char *name) + +DB_LOOKUP (protobynumber, '=', 20, ("%zd", (ssize_t) proto), + { + if (result->p_proto == proto) + break; + }, int proto) diff --git a/REORG.TODO/nss/nss_files/files-pwd.c b/REORG.TODO/nss/nss_files/files-pwd.c new file mode 100644 index 0000000000..62c597703a --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-pwd.c @@ -0,0 +1,44 @@ +/* User file parser in nss_files module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <pwd.h> + +#define STRUCTURE passwd +#define ENTNAME pwent +#define DATABASE "passwd" +struct pwent_data {}; + +/* Our parser function is already defined in fgetpwent_r.c, so use that + to parse lines from the database file. */ +#define EXTERN_PARSER +#include "files-parse.c" +#include GENERIC + +DB_LOOKUP (pwnam, '.', 0, ("%s", name), + { + if (name[0] != '+' && name[0] != '-' + && ! strcmp (name, result->pw_name)) + break; + }, const char *name) + +DB_LOOKUP (pwuid, '=', 20, ("%lu", (unsigned long int) uid), + { + if (result->pw_uid == uid && result->pw_name[0] != '+' + && result->pw_name[0] != '-') + break; + }, uid_t uid) diff --git a/REORG.TODO/nss/nss_files/files-rpc.c b/REORG.TODO/nss/nss_files/files-rpc.c new file mode 100644 index 0000000000..8ee0d19f32 --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-rpc.c @@ -0,0 +1,46 @@ +/* SunRPC program number file parser in nss_files module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <rpc/netdb.h> + + +#define ENTNAME rpcent +#define DATABASE "rpc" + +struct rpcent_data {}; + +#define TRAILING_LIST_MEMBER r_aliases +#define TRAILING_LIST_SEPARATOR_P isspace +#include "files-parse.c" +LINE_PARSER +("#", + STRING_FIELD (result->r_name, isspace, 1); + INT_FIELD (result->r_number, isspace, 1, 10,); + ) + +#include GENERIC + +DB_LOOKUP (rpcbyname, '.', 0, ("%s", name), + LOOKUP_NAME (r_name, r_aliases), + const char *name) + +DB_LOOKUP (rpcbynumber, '=', 20, ("%zd", (ssize_t) number), + { + if (result->r_number == number) + break; + }, int number) diff --git a/REORG.TODO/nss/nss_files/files-service.c b/REORG.TODO/nss/nss_files/files-service.c new file mode 100644 index 0000000000..b6ae51082f --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-service.c @@ -0,0 +1,63 @@ +/* Services file parser in nss_files module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <netinet/in.h> +#include <netdb.h> + + +#define ENTNAME servent +#define DATABASE "services" + +struct servent_data {}; + +#define TRAILING_LIST_MEMBER s_aliases +#define TRAILING_LIST_SEPARATOR_P isspace +#include "files-parse.c" +#define ISSLASH(c) ((c) == '/') +LINE_PARSER +("#", + STRING_FIELD (result->s_name, isspace, 1); + INT_FIELD (result->s_port, ISSLASH, 10, 0, htons); + STRING_FIELD (result->s_proto, isspace, 1); + ) + +#include GENERIC + +DB_LOOKUP (servbyname, ':', + strlen (name) + 2 + (proto == NULL ? 0 : strlen (proto)), + ("%s/%s", name, proto ?: ""), + { + /* Must match both protocol (if specified) and name. */ + if (proto != NULL && strcmp (result->s_proto, proto)) + /* A continue statement here breaks nss_db, because it + bypasses advancing to the next db entry, and it + doesn't make nss_files any more efficient. */; + else + LOOKUP_NAME (s_name, s_aliases) + }, + const char *name, const char *proto) + +DB_LOOKUP (servbyport, '=', 21 + (proto ? strlen (proto) : 0), + ("%zd/%s", (ssize_t) ntohs (port), proto ?: ""), + { + /* Must match both port and protocol. */ + if (result->s_port == port + && (proto == NULL + || strcmp (result->s_proto, proto) == 0)) + break; + }, int port, const char *proto) diff --git a/REORG.TODO/nss/nss_files/files-sgrp.c b/REORG.TODO/nss/nss_files/files-sgrp.c new file mode 100644 index 0000000000..03b7da5e2f --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-sgrp.c @@ -0,0 +1,37 @@ +/* User file parser in nss_files module. + Copyright (C) 2009-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <gshadow.h> + +#define STRUCTURE sgrp +#define ENTNAME sgent +#define DATABASE "gshadow" +struct sgent_data {}; + +/* Our parser function is already defined in sgetspent_r.c, so use that + to parse lines from the database file. */ +#define EXTERN_PARSER +#include "files-parse.c" +#include GENERIC + +DB_LOOKUP (sgnam, '.', 0, ("%s", name), + { + if (name[0] != '+' && name[0] != '-' + && ! strcmp (name, result->sg_namp)) + break; + }, const char *name) diff --git a/REORG.TODO/nss/nss_files/files-spwd.c b/REORG.TODO/nss/nss_files/files-spwd.c new file mode 100644 index 0000000000..7f13562acb --- /dev/null +++ b/REORG.TODO/nss/nss_files/files-spwd.c @@ -0,0 +1,37 @@ +/* User file parser in nss_files module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <shadow.h> + +#define STRUCTURE spwd +#define ENTNAME spent +#define DATABASE "shadow" +struct spent_data {}; + +/* Our parser function is already defined in sgetspent_r.c, so use that + to parse lines from the database file. */ +#define EXTERN_PARSER +#include "files-parse.c" +#include GENERIC + +DB_LOOKUP (spnam, '.', 0, ("%s", name), + { + if (name[0] != '+' && name[0] != '-' + && ! strcmp (name, result->sp_namp)) + break; + }, const char *name) |