xref: /openbsd/lib/libc/net/getprotoent.c (revision a6445c1d)
1 /*	$OpenBSD: getprotoent.c,v 1.12 2014/10/11 03:12:13 doug Exp $ */
2 /*
3  * Copyright (c) 1983, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 
34 #include <errno.h>
35 #include <limits.h>
36 #include <netdb.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 void
42 setprotoent_r(int f, struct protoent_data *pd)
43 {
44 	if (pd->fp == NULL)
45 		pd->fp = fopen(_PATH_PROTOCOLS, "re" );
46 	else
47 		rewind(pd->fp);
48 	pd->stayopen |= f;
49 }
50 
51 void
52 endprotoent_r(struct protoent_data *pd)
53 {
54 	if (pd->fp) {
55 		fclose(pd->fp);
56 		pd->fp = NULL;
57 	}
58 	free(pd->aliases);
59 	pd->aliases = NULL;
60 	pd->maxaliases = 0;
61 	free(pd->line);
62 	pd->line = NULL;
63 	pd->stayopen = 0;
64 }
65 
66 int
67 getprotoent_r(struct protoent *pe, struct protoent_data *pd)
68 {
69 	char *p, *cp, **q, *endp;
70 	size_t len;
71 	long l;
72 	int serrno;
73 
74 	if (pd->fp == NULL && (pd->fp = fopen(_PATH_PROTOCOLS, "re" )) == NULL)
75 		return (-1);
76 again:
77 	if ((p = fgetln(pd->fp, &len)) == NULL)
78 		return (-1);
79 	if (len == 0 || *p == '#' || *p == '\n')
80 		goto again;
81 	if (p[len-1] == '\n')
82 		len--;
83 	if ((cp = memchr(p, '#', len)) != NULL)
84 		len = cp - p;
85 	cp = realloc(pd->line, len + 1);
86 	if (cp == NULL)
87 		return (-1);
88 	pd->line = pe->p_name = memcpy(cp, p, len);
89 	cp[len] = '\0';
90 	cp = strpbrk(cp, " \t");
91 	if (cp == NULL)
92 		goto again;
93 	*cp++ = '\0';
94 	while (*cp == ' ' || *cp == '\t')
95 		cp++;
96 	p = strpbrk(cp, " \t");
97 	if (p != NULL)
98 		*p++ = '\0';
99 	l = strtol(cp, &endp, 10);
100 	if (endp == cp || *endp != '\0' || l < 0 || l >= INT_MAX)
101 		goto again;
102 	pe->p_proto = l;
103 	if (pd->aliases == NULL) {
104 		pd->maxaliases = 5;
105 		pd->aliases = calloc(pd->maxaliases, sizeof(char *));
106 		if (pd->aliases == NULL) {
107 			serrno = errno;
108 			endprotoent_r(pd);
109 			errno = serrno;
110 			return (-1);
111 		}
112 	}
113 	q = pe->p_aliases = pd->aliases;
114 	if (p != NULL) {
115 		cp = p;
116 		while (cp && *cp) {
117 			if (*cp == ' ' || *cp == '\t') {
118 				cp++;
119 				continue;
120 			}
121 			if (q == &pe->p_aliases[pd->maxaliases - 1]) {
122 				p = reallocarray(pe->p_aliases,
123 				    pd->maxaliases, 2 * sizeof(char *));
124 				if (p == NULL) {
125 					serrno = errno;
126 					endprotoent_r(pd);
127 					errno = serrno;
128 					return (-1);
129 				}
130 				pd->maxaliases *= 2;
131 				q = (char **)p + (q - pe->p_aliases);
132 				pe->p_aliases = pd->aliases = (char **)p;
133 			}
134 			*q++ = cp;
135 			cp = strpbrk(cp, " \t");
136 			if (cp != NULL)
137 				*cp++ = '\0';
138 		}
139 	}
140 	*q = NULL;
141 	return (0);
142 }
143 
144 struct protoent_data _protoent_data;	/* shared with getproto{,name}.c */
145 
146 void
147 setprotoent(int f)
148 {
149 	setprotoent_r(f, &_protoent_data);
150 }
151 
152 void
153 endprotoent(void)
154 {
155 	endprotoent_r(&_protoent_data);
156 }
157 
158 struct protoent *
159 getprotoent(void)
160 {
161 	static struct protoent proto;
162 
163 	if (getprotoent_r(&proto, &_protoent_data) != 0)
164 		return (NULL);
165 	return (&proto);
166 }
167