(root)/
glibc-2.38/
nss/
getXXbyYY.c
       1  /* Copyright (C) 1996-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <assert.h>
      19  #include <errno.h>
      20  #include <libc-lock.h>
      21  #include <stdlib.h>
      22  #include <resolv.h>
      23  #include <set-freeres.h>
      24  
      25  #include "nsswitch.h"
      26  
      27  /*******************************************************************\
      28  |* Here we assume several symbols to be defined:		   *|
      29  |*								   *|
      30  |* LOOKUP_TYPE   - the return type of the function		   *|
      31  |*								   *|
      32  |* FUNCTION_NAME - name of the non-reentrant function		   *|
      33  |*								   *|
      34  |* DATABASE_NAME - name of the database the function accesses	   *|
      35  |*		   (e.g., host, services, ...)			   *|
      36  |*								   *|
      37  |* ADD_PARAMS    - additional parameter, can vary in number	   *|
      38  |*								   *|
      39  |* ADD_VARIABLES - names of additional parameter		   *|
      40  |*								   *|
      41  |* BUFLEN	 - length of buffer allocated for the non	   *|
      42  |*		   reentrant version				   *|
      43  |*								   *|
      44  |* Optionally the following vars can be defined:		   *|
      45  |*								   *|
      46  |* NEED_H_ERRNO  - an extra parameter will be passed to point to   *|
      47  |*		   the global `h_errno' variable.		   *|
      48  |*								   *|
      49  \*******************************************************************/
      50  
      51  
      52  #ifdef HANDLE_DIGITS_DOTS
      53  # include <resolv/resolv_context.h>
      54  #endif
      55  
      56  /* To make the real sources a bit prettier.  */
      57  #define REENTRANT_NAME APPEND_R (FUNCTION_NAME)
      58  #define APPEND_R(name) APPEND_R1 (name)
      59  #define APPEND_R1(name) name##_r
      60  #define INTERNAL(name) INTERNAL1 (name)
      61  #define INTERNAL1(name) __##name
      62  #define APPEND_FREEMEM_NAME1(name) __libc_##name##_freemem_ptr
      63  #define APPEND_FREEMEM_NAME(name) APPEND_FREEMEM_NAME1(name)
      64  #define FREEMEM_NAME APPEND_FREEMEM_NAME (FUNCTION_NAME)
      65  
      66  /* Sometimes we need to store error codes in the `h_errno' variable.  */
      67  #ifdef NEED_H_ERRNO
      68  # define H_ERRNO_PARM , int *h_errnop
      69  # define H_ERRNO_VAR , &h_errno_tmp
      70  # define H_ERRNO_VAR_P &h_errno_tmp
      71  #else
      72  # define H_ERRNO_PARM
      73  # define H_ERRNO_VAR
      74  # define H_ERRNO_VAR_P NULL
      75  #endif
      76  
      77  #ifdef HAVE_AF
      78  # define AF_VAL af
      79  #else
      80  # define AF_VAL AF_INET
      81  #endif
      82  
      83  /* Prototype for reentrant version we use here.  */
      84  extern int INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf,
      85  				      char *buffer, size_t buflen,
      86  				      LOOKUP_TYPE **result H_ERRNO_PARM)
      87       attribute_hidden;
      88  
      89  /* We need to protect the dynamic buffer handling.  */
      90  __libc_lock_define_initialized (static, lock);
      91  
      92  /* This points to the static buffer used.  */
      93  static char *buffer;
      94  
      95  weak_alias (buffer, FREEMEM_NAME)
      96  
      97  LOOKUP_TYPE *
      98  FUNCTION_NAME (ADD_PARAMS)
      99  {
     100    static size_t buffer_size;
     101    static LOOKUP_TYPE resbuf;
     102    LOOKUP_TYPE *result;
     103  #ifdef NEED_H_ERRNO
     104    int h_errno_tmp = 0;
     105  #endif
     106  
     107  #ifdef HANDLE_DIGITS_DOTS
     108    /* Wrap both __nss_hostname_digits_dots and the actual lookup
     109       function call in the same context.  */
     110    struct resolv_context *res_ctx = __resolv_context_get ();
     111    if (res_ctx == NULL)
     112      {
     113  # if NEED_H_ERRNO
     114        __set_h_errno (NETDB_INTERNAL);
     115  # endif
     116        return NULL;
     117      }
     118  #endif
     119  
     120    /* Get lock.  */
     121    __libc_lock_lock (lock);
     122  
     123    if (buffer == NULL)
     124      {
     125        buffer_size = BUFLEN;
     126        buffer = (char *) malloc (buffer_size);
     127      }
     128  
     129  #ifdef HANDLE_DIGITS_DOTS
     130    if (buffer != NULL)
     131      {
     132        if (__nss_hostname_digits_dots_context
     133  	  (res_ctx, name, &resbuf, &buffer, &buffer_size, 0, &result, NULL,
     134  	   AF_VAL, H_ERRNO_VAR_P))
     135  	goto done;
     136      }
     137  #endif
     138  
     139    while (buffer != NULL
     140  	 && (INTERNAL (REENTRANT_NAME) (ADD_VARIABLES, &resbuf, buffer,
     141  					buffer_size, &result H_ERRNO_VAR)
     142  	     == ERANGE)
     143  #ifdef NEED_H_ERRNO
     144  	 && h_errno_tmp == NETDB_INTERNAL
     145  #endif
     146  	 )
     147      {
     148        char *new_buf;
     149        buffer_size *= 2;
     150        new_buf = (char *) realloc (buffer, buffer_size);
     151        if (new_buf == NULL)
     152  	{
     153  	  /* We are out of memory.  Free the current buffer so that the
     154  	     process gets a chance for a normal termination.  */
     155  	  free (buffer);
     156  	  __set_errno (ENOMEM);
     157  	}
     158        buffer = new_buf;
     159      }
     160  
     161    if (buffer == NULL)
     162      result = NULL;
     163  
     164  #ifdef HANDLE_DIGITS_DOTS
     165  done:
     166  #endif
     167    /* Release lock.  */
     168    __libc_lock_unlock (lock);
     169  
     170  #ifdef HANDLE_DIGITS_DOTS
     171    __resolv_context_put (res_ctx);
     172  #endif
     173  
     174  #ifdef NEED_H_ERRNO
     175    if (h_errno_tmp != 0)
     176      __set_h_errno (h_errno_tmp);
     177  #endif
     178  
     179    return result;
     180  }
     181  
     182  nss_interface_function (FUNCTION_NAME)