xref: /illumos-gate/usr/src/lib/libnsl/nss/parse.c (revision c3937c08b16d32677a7dc955a81325f2e7a61b5d)
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 2006 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #include "mt.h"
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <strings.h>
32 
33 char *_strpbrk_escape(char *, char *);
34 
35 /*
36  * _strtok_escape()
37  *   Like strtok_r, except we don't break on a token if it is escaped
38  *   with the escape character (\).
39  */
40 char *
41 _strtok_escape(char *string, char *sepset, char **lasts)
42 {
43 	char	*r;
44 
45 	/* first or subsequent call */
46 	if (string == NULL)
47 		string = *lasts;
48 
49 	if (string == 0)		/* return if no tokens remaining */
50 		return (NULL);
51 
52 	if (*string == '\0')		/* return if no tokens remaining */
53 		return (NULL);
54 
55 	/* move past token */
56 	if ((r = _strpbrk_escape(string, sepset)) == NULL)
57 		*lasts = 0;	/* indicate this is last token */
58 	else {
59 		*r = '\0';
60 		*lasts = r+1;
61 	}
62 	return (string);
63 }
64 
65 /*
66  * Return ptr to first occurrence of any non-escaped character from `brkset'
67  * in the character string `string'; NULL if none exists.
68  */
69 char *
70 _strpbrk_escape(char *string, char *brkset)
71 {
72 	const char *p;
73 
74 	do {
75 		for (p = brkset; *p != '\0' && *p != *string; ++p)
76 			;
77 		if (p == string)
78 			return ((char *)string);
79 		if (*p != '\0') {
80 			if (*(string-1) != '\\')
81 				return ((char *)string);
82 		}
83 	} while (*string++);
84 
85 	return (NULL);
86 }
87 
88 
89 char   *
90 _escape(char *s, char *esc)
91 {
92 	int	nescs = 0;	/* number of escapes to place in s */
93 	int	i, j;
94 	int	len_s;
95 	char	*tmp;
96 
97 	if (s == NULL || esc == NULL)
98 		return (NULL);
99 
100 	len_s = strlen(s);
101 	for (i = 0; i < len_s; i++)
102 		if (strchr(esc, s[i]))
103 			nescs++;
104 	if ((tmp = malloc(nescs + len_s + 1)) == NULL)
105 		return (NULL);
106 	for (i = 0, j = 0; i < len_s; i++) {
107 		if (strchr(esc, s[i])) {
108 			tmp[j++] = '\\';
109 		}
110 		tmp[j++] = s[i];
111 	}
112 	tmp[len_s + nescs] = '\0';
113 	return (tmp);
114 }
115 
116 
117 char *
118 _unescape(char *s, char *esc)
119 {
120 	int	len_s;
121 	int	i, j;
122 	char	*tmp;
123 
124 	if (s == NULL || esc == NULL)
125 		return (NULL);
126 
127 	len_s = strlen(s);
128 	if ((tmp = malloc(len_s + 1)) == NULL)
129 		return (NULL);
130 	for (i = 0, j = 0; i < len_s; i++) {
131 		if (s[i] == '\\' && strchr(esc, s[i + 1]))
132 			tmp[j++] = s[++i];
133 		else
134 			tmp[j++] = s[i];
135 	}
136 	tmp[j] = '\0';
137 	return (tmp);
138 }
139 
140 char *
141 _strdup_null(char *s)
142 {
143 	return (strdup(s ? s : ""));
144 }
145 
146 
147 /*
148  * read a line into buffer from a mmap'ed file.
149  * return length of line read.
150  */
151 int
152 _readbufline(char *mapbuf,	/* input mmap buffer */
153     int mapsize,		/* input size */
154     char *buffer,		/* output storage */
155     int buflen,			/* output size */
156     int *lastlen)		/* input read till here last time */
157 {
158 	int	linelen;
159 
160 	for (;;) {
161 		linelen = 0;
162 		while (linelen < buflen - 1) {	/* "- 1" saves room for \n\0 */
163 			if (*lastlen >= mapsize) {
164 				if (linelen == 0 ||
165 					buffer[linelen - 1] == '\\') {
166 						return (-1);
167 					} else {
168 						buffer[linelen] = '\n';
169 						buffer[linelen + 1] = '\0';
170 						return (linelen);
171 					}
172 			}
173 			switch (mapbuf[*lastlen]) {
174 			case '\n':
175 				(*lastlen)++;
176 				if (linelen > 0 &&
177 				    buffer[linelen - 1] == '\\') {
178 					--linelen;	/* remove the '\\' */
179 				} else {
180 					buffer[linelen] = '\n';
181 					buffer[linelen + 1] = '\0';
182 					return (linelen);
183 				}
184 				break;
185 			default:
186 				buffer[linelen] = mapbuf[*lastlen];
187 				(*lastlen)++;
188 				linelen++;
189 			}
190 		}
191 		/* Buffer overflow -- eat rest of line and loop again */
192 		while (mapbuf[*lastlen] != '\n') {
193 			if (mapbuf[*lastlen] == EOF) {
194 				return (-1);
195 			}
196 			(*lastlen)++;
197 		};
198 	}
199 	/* NOTREACHED */
200 }
201