Back to index

glibc  2.9
hesiod-service.c
Go to the documentation of this file.
00001 /* Copyright (C) 1997, 2000, 2002 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <errno.h>
00021 #include <hesiod.h>
00022 #include <netdb.h>
00023 #include <netinet/in.h>
00024 #include <nss.h>
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 
00029 #include "nss_hesiod.h"
00030 
00031 /* Hesiod uses a format for service entries that differs from the
00032    traditional format.  We therefore declare our own parser.  */
00033 
00034 #define ENTNAME servent
00035 
00036 struct servent_data {};
00037 
00038 #define TRAILING_LIST_MEMBER              s_aliases
00039 #define TRAILING_LIST_SEPARATOR_P  isspace
00040 #include <nss/nss_files/files-parse.c>
00041 #define ISSC_OR_SPACE(c)    ((c) ==  ';' || isspace (c))
00042 LINE_PARSER
00043 ("#",
00044  STRING_FIELD (result->s_name, ISSC_OR_SPACE, 1);
00045  STRING_FIELD (result->s_proto, ISSC_OR_SPACE, 1);
00046  INT_FIELD (result->s_port, ISSC_OR_SPACE, 10, 0, htons);
00047  )
00048 
00049 enum nss_status
00050 _nss_hesiod_setservent (int stayopen)
00051 {
00052   return NSS_STATUS_SUCCESS;
00053 }
00054 
00055 enum nss_status
00056 _nss_hesiod_endservent (void)
00057 {
00058   return NSS_STATUS_SUCCESS;
00059 }
00060 
00061 static enum nss_status
00062 lookup (const char *name, const char *type, const char *protocol,
00063        struct servent *serv, char *buffer, size_t buflen, int *errnop)
00064 {
00065   struct parser_data *data = (void *) buffer;
00066   size_t linebuflen;
00067   void *context;
00068   char **list, **item;
00069   int parse_res;
00070   int found;
00071   int olderr = errno;
00072 
00073   context = _nss_hesiod_init ();
00074   if (context == NULL)
00075     return NSS_STATUS_UNAVAIL;
00076 
00077   list = hesiod_resolve (context, name, type);
00078   if (list == NULL)
00079     {
00080       int err = errno;
00081       hesiod_end (context);
00082       __set_errno (olderr);
00083       return err == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
00084     }
00085 
00086   linebuflen = buffer + buflen - data->linebuffer;
00087 
00088   item = list;
00089   found = 0;
00090   do
00091     {
00092       size_t len = strlen (*item) + 1;
00093 
00094       if (linebuflen < len)
00095        {
00096          hesiod_free_list (context, list);
00097          hesiod_end (context);
00098          *errnop = ERANGE;
00099          return NSS_STATUS_TRYAGAIN;
00100        }
00101 
00102       memcpy (data->linebuffer, *item, len);
00103 
00104       parse_res = parse_line (buffer, serv, data, buflen, errnop);
00105       if (parse_res == -1)
00106        {
00107          hesiod_free_list (context, list);
00108          hesiod_end (context);
00109          return NSS_STATUS_TRYAGAIN;
00110        }
00111 
00112       if (parse_res > 0)
00113        found = protocol == NULL || strcasecmp (serv->s_proto, protocol) == 0;
00114 
00115       ++item;
00116     }
00117   while (*item != NULL && !found);
00118 
00119   hesiod_free_list (context, list);
00120   hesiod_end (context);
00121 
00122   if (found == 0)
00123     {
00124       __set_errno (olderr);
00125       return NSS_STATUS_NOTFOUND;
00126     }
00127 
00128   return NSS_STATUS_SUCCESS;
00129 }
00130 
00131 enum nss_status
00132 _nss_hesiod_getservbyname_r (const char *name, const char *protocol,
00133                           struct servent *serv,
00134                           char *buffer, size_t buflen, int *errnop)
00135 {
00136   return lookup (name, "service", protocol, serv, buffer, buflen, errnop);
00137 }
00138 
00139 enum nss_status
00140 _nss_hesiod_getservbyport_r (const int port, const char *protocol,
00141                           struct servent *serv,
00142                           char *buffer, size_t buflen, int *errnop)
00143 {
00144   char portstr[6];       /* Port numbers are restricted to 16 bits. */
00145 
00146   snprintf (portstr, sizeof portstr, "%d", ntohs (port));
00147 
00148   return lookup (portstr, "port", protocol, serv, buffer, buflen, errnop);
00149 }