/* Common code for file-based databases in nss_files module.
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997 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
#include <ctype.h>
#include <assert.h>
#include <errno.h>
-#include <libc-lock.h>
+#include <fcntl.h>
+#include <bits/libc-lock.h>
#include "nsswitch.h"
/* These symbols are defined by the including source file:
#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))
stream = fopen (DATAFILE, "r");
if (stream == NULL)
- status = NSS_STATUS_UNAVAIL;
+ status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
+ else
+ {
+ /* We have to make sure the file is `closed on exec'. */
+ int result, flags;
+
+ result = flags = fcntl (fileno (stream), F_GETFD, 0);
+ if (result >= 0)
+ {
+ flags |= FD_CLOEXEC;
+ result = fcntl (fileno (stream), F_SETFD, flags);
+ }
+ if (result < 0)
+ {
+ /* Something went wrong. Close the stream and return a
+ failure. */
+ fclose (stream);
+ stream = NULL;
+ status = NSS_STATUS_UNAVAIL;
+ }
+ }
}
else
rewind (stream);
static enum nss_status
internal_getent (struct STRUCTURE *result,
- char *buffer, int buflen H_ERRNO_PROTO)
+ char *buffer, int buflen, int *errnop H_ERRNO_PROTO)
{
char *p;
struct parser_data *data = (void *) buffer;
int linebuflen = buffer + buflen - data->linebuffer;
+ int parse_result;
if (buflen < (int) sizeof *data + 1)
{
- __set_errno (ERANGE);
+ *errnop = ERANGE;
+ H_ERRNO_SET (NETDB_INTERNAL);
return NSS_STATUS_TRYAGAIN;
}
if (p == NULL)
{
/* End of file or read error. */
+ *errnop = errno;
H_ERRNO_SET (HOST_NOT_FOUND);
return NSS_STATUS_NOTFOUND;
}
{
/* The line is too long. Give the user the opportunity to
enlarge the buffer. */
- __set_errno (ERANGE);
+ *errnop = ERANGE;
H_ERRNO_SET (NETDB_INTERNAL);
return NSS_STATUS_TRYAGAIN;
}
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_line (p, result, data, buflen));
+ || ! (parse_result = parse_line (p, result, data, buflen, errnop)));
/* Filled in RESULT with the next entry from the database file. */
- return NSS_STATUS_SUCCESS;
+ return parse_result == -1 ? NSS_STATUS_TRYAGAIN : 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 H_ERRNO_PROTO)
+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;
if (status == NSS_STATUS_SUCCESS)
{
- status = internal_getent (result, buffer, buflen H_ERRNO_ARG);
+ status = internal_getent (result, buffer, buflen, errnop
+ H_ERRNO_ARG);
/* Remember this position if we were successful. If the
operation failed we give the user a chance to repeat the
#define DB_LOOKUP(name, keysize, keypattern, break_if_match, proto...) \
enum nss_status \
_nss_files_get##name##_r (proto, \
- struct STRUCTURE *result, \
- char *buffer, size_t buflen H_ERRNO_PROTO) \
+ struct STRUCTURE *result, char *buffer, \
+ size_t buflen, int *errnop H_ERRNO_PROTO) \
{ \
enum nss_status status; \
\
/* Tell getent function that we have repositioned the file pointer. */ \
last_use = getby; \
\
- while ((status = internal_getent (result, buffer, buflen H_ERRNO_ARG)) \
+ while ((status = internal_getent (result, buffer, buflen, errnop \
+ H_ERRNO_ARG)) \
== NSS_STATUS_SUCCESS) \
{ break_if_match } \
\