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