xref: /illumos-gate/usr/src/lib/libnsl/nss/parse.c (revision 34e48580)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <strings.h>
33 
34 char *_strpbrk_escape(char *, char *);
35 
36 /*
37  * _strtok_escape()
38  *   Like strtok_r, except we don't break on a token if it is escaped
39  *   with the escape character (\).
40  */
41 char *
42 _strtok_escape(char *string, char *sepset, char **lasts)
43 {
44 	char	*r;
45 
46 	/* first or subsequent call */
47 	if (string == NULL)
48 		string = *lasts;
49 
50 	if (string == 0)		/* return if no tokens remaining */
51 		return (NULL);
52 
53 	if (*string == '\0')		/* return if no tokens remaining */
54 		return (NULL);
55 
56 	/* move past token */
57 	if ((r = _strpbrk_escape(string, sepset)) == NULL)
58 		*lasts = 0;	/* indicate this is last token */
59 	else {
60 		*r = '\0';
61 		*lasts = r+1;
62 	}
63 	return (string);
64 }
65 
66 /*
67  * Return ptr to first occurrence of any non-escaped character from `brkset'
68  * in the character string `string'; NULL if none exists.
69  */
70 char *
71 _strpbrk_escape(char *string, char *brkset)
72 {
73 	const char *p;
74 
75 	do {
76 		for (p = brkset; *p != '\0' && *p != *string; ++p)
77 			;
78 		if (p == string)
79 			return ((char *)string);
80 		if (*p != '\0') {
81 			if (*(string-1) != '\\')
82 				return ((char *)string);
83 		}
84 	} while (*string++);
85 
86 	return (NULL);
87 }
88 
89 
90 char   *
91 _escape(char *s, char *esc)
92 {
93 	int	nescs = 0;	/* number of escapes to place in s */
94 	int	i, j;
95 	int	len_s;
96 	char	*tmp;
97 
98 	if (s == NULL || esc == NULL)
99 		return (NULL);
100 
101 	len_s = strlen(s);
102 	for (i = 0; i < len_s; i++)
103 		if (strchr(esc, s[i]))
104 			nescs++;
105 	if ((tmp = malloc(nescs + len_s + 1)) == NULL)
106 		return (NULL);
107 	for (i = 0, j = 0; i < len_s; i++) {
108 		if (strchr(esc, s[i])) {
109 			tmp[j++] = '\\';
110 		}
111 		tmp[j++] = s[i];
112 	}
113 	tmp[len_s + nescs] = '\0';
114 	return (tmp);
115 }
116 
117 
118 char *
119 _unescape(char *s, char *esc)
120 {
121 	int	len_s;
122 	int	i, j;
123 	char	*tmp;
124 
125 	if (s == NULL || esc == NULL)
126 		return (NULL);
127 
128 	len_s = strlen(s);
129 	if ((tmp = malloc(len_s + 1)) == NULL)
130 		return (NULL);
131 	for (i = 0, j = 0; i < len_s; i++) {
132 		if (s[i] == '\\' && strchr(esc, s[i + 1]))
133 			tmp[j++] = s[++i];
134 		else
135 			tmp[j++] = s[i];
136 	}
137 	tmp[j] = NULL;
138 	return (tmp);
139 }
140 
141 char *
142 _strdup_null(char *s)
143 {
144 	return (strdup(s ? s : ""));
145 }
146 
147 
148 /*
149  * read a line into buffer from a mmap'ed file.
150  * return length of line read.
151  */
152 int
153 _readbufline(char *mapbuf,	/* input mmap buffer */
154     int mapsize,		/* input size */
155     char *buffer,		/* output storage */
156     int buflen,			/* output size */
157     int *lastlen)		/* input read till here last time */
158 {
159 	int	linelen;
160 
161 	for (;;) {
162 		linelen = 0;
163 		while (linelen < buflen - 1) {	/* "- 1" saves room for \n\0 */
164 			if (*lastlen >= mapsize) {
165 				if (linelen == 0 ||
166 					buffer[linelen - 1] == '\\') {
167 						return (-1);
168 					} else {
169 						buffer[linelen] = '\n';
170 						buffer[linelen + 1] = '\0';
171 						return (linelen);
172 					}
173 			}
174 			switch (mapbuf[*lastlen]) {
175 			case '\n':
176 				(*lastlen)++;
177 				if (linelen > 0 &&
178 				    buffer[linelen - 1] == '\\') {
179 					--linelen;	/* remove the '\\' */
180 				} else {
181 					buffer[linelen] = '\n';
182 					buffer[linelen + 1] = '\0';
183 					return (linelen);
184 				}
185 				break;
186 			default:
187 				buffer[linelen] = mapbuf[*lastlen];
188 				(*lastlen)++;
189 				linelen++;
190 			}
191 		}
192 		/* Buffer overflow -- eat rest of line and loop again */
193 		while (mapbuf[*lastlen] != '\n') {
194 			if (mapbuf[*lastlen] == EOF) {
195 				return (-1);
196 			}
197 			(*lastlen)++;
198 		};
199 	}
200 	/* NOTREACHED */
201 }
202