]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - hesiod/hesservbyname.c
new upstream version
[1ts-debian.git] / hesiod / hesservbyname.c
1 /*
2  * Copyright (c) 1983, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 /* Copyright 1988, 1996 by the Massachusetts Institute of Technology.
35  *
36  * Permission to use, copy, modify, and distribute this
37  * software and its documentation for any purpose and without
38  * fee is hereby granted, provided that the above copyright
39  * notice appear in all copies and that both that copyright
40  * notice and this permission notice appear in supporting
41  * documentation, and that the name of M.I.T. not be used in
42  * advertising or publicity pertaining to distribution of the
43  * software without specific, written prior permission.
44  * M.I.T. makes no representations about the suitability of
45  * this software for any purpose.  It is provided "as is"
46  * without express or implied warranty.
47  */
48
49 /* This file is part of the Hesiod library.  It contains
50  * hesiod_getservbyname, used to get information about network
51  * services.
52  */
53
54 static const char rcsid[] = "$Id: hesservbyname.c,v 1.7 1999/10/23 19:29:16 danw Exp $";
55
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <ctype.h>
60 #include <errno.h>
61 #include <pwd.h>
62 #include <netdb.h>
63 #include <sys/types.h>
64 #include <netinet/in.h>
65 #include "hesiod.h"
66
67 static int cistrcmp(const char *s1, const char *s2);
68
69 struct servent *hesiod_getservbyname(void *context, const char *name,
70                                      const char *proto)
71 {
72   char **item, **list;
73
74   /* Ask for all entries matching the given service name. */
75   list = hesiod_resolve(context, name, "service");
76   if (!list)
77     return NULL;
78
79   /* Look through the returned list for entries matching the given protocol. */
80   for (item = list; *item; item++)
81     {
82       char **alias, *servicename, *protoname, *port, *p2, *p = *item;
83       int naliases;
84       struct servent *serv;
85
86       /* Find the service name. */
87       while (isspace((unsigned char)*p))
88         p++;
89       servicename = p;
90       while (*p && !isspace((unsigned char)*p) && *p != ';')
91         p++;
92       if (!*p) /* Malformed entry */
93         continue;
94       *p++ = 0;
95
96       /* Find the protocol name and check it. */
97       while (isspace((unsigned char)*p))
98         p++;
99       protoname = p;
100       while (*p && !isspace((unsigned char)*p) && *p != ';')
101         p++;
102       if (!*p) /* Malformed entry */
103         continue;
104       *p++ = 0;
105       if (cistrcmp(proto, protoname)) /* Wrong protocol */
106         continue;
107
108       /* Find the port number. */
109       while (isspace((unsigned char)*p) || *p == ';')
110         p++;
111       if (!*p) /* Malformed entry */
112         continue;
113       port = p;
114
115       while (*p && !isspace((unsigned char)*p) && *p != ';')
116         p++;
117       while (isspace((unsigned char)*p) || *p == ';')
118         p++;
119
120       /* Count the number of aliases. */
121       naliases = 0;
122       p2 = p;
123       while (*p2)
124         {
125           naliases++;
126           while (*p2 && !isspace((unsigned char)*p2))
127             p2++;
128           while (isspace((unsigned char)*p2))
129             p2++;
130         }
131
132       /* Allocate space for the answer. */
133       serv = (struct servent *) malloc(sizeof(struct servent));
134       if (serv)
135         {
136           serv->s_name = malloc(strlen(servicename) + strlen(proto)
137                                  + strlen(p) + 3);
138           if (serv->s_name)
139             serv->s_aliases = (char **)
140               malloc((naliases + 1) * sizeof(char *));
141           if (serv->s_name && !serv->s_aliases)
142             free(serv->s_name);
143           if (!serv->s_name || !serv->s_aliases)
144             free(serv);
145         }
146       if (!serv || !serv->s_name || !serv->s_aliases)
147         {
148           errno = ENOMEM;
149           return NULL;
150         }
151
152       /* Copy the information we found into the answer. */
153       serv->s_port = htons(atoi(port));
154       strcpy(serv->s_name, name);
155       serv->s_proto = serv->s_name + strlen(name) + 1;
156       strcpy(serv->s_proto, proto);
157       p2 = serv->s_proto + strlen(proto) + 1;
158       strcpy(p2, p);
159       alias = serv->s_aliases;
160       while (*p2)
161         {
162           *alias++ = p2;
163           while (*p2 && !isspace((unsigned char)*p2))
164             p2++;
165           if (*p2)
166             {
167               *p2++ = 0;
168               while (isspace((unsigned char)*p2))
169                 p2++;
170             }
171         }
172       *alias = NULL;
173
174       hesiod_free_list(context, list);
175       return serv;
176     }
177   hesiod_free_list(context, list);
178   return NULL;
179 }
180
181 void hesiod_free_servent(void *context, struct servent *serv)
182 {
183     free(serv->s_name);
184     free(serv->s_aliases);
185     free(serv);
186 }
187
188 static int cistrcmp(const char *s1, const char *s2)
189 {
190   while (*s1 && tolower(*s1) == tolower(*s2))
191     {
192       s1++;
193       s2++;
194     }
195   return tolower(*s1) - tolower(*s2);
196 }