xref: /illumos-gate/usr/src/cmd/lp/lib/lp/getlist.c (revision 00208914)
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 2015 Gary Mills
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
32 
33 #include "string.h"
34 #include "errno.h"
35 #include "stdlib.h"
36 
37 #include "lp.h"
38 
39 #if	defined(__STDC__)
40 static char		*unq_strdup ( char * , char * );
41 #else
42 static char		*unq_strdup();
43 #endif
44 
45 /**
46  ** getlist() - CONSTRUCT LIST FROM STRING
47  **/
48 
49 /*
50  * Any number of characters from "ws", or a single
51  * character from "hardsep", can separate items in the list.
52  */
53 
54 char **
55 #if	defined(__STDC__)
getlist(char * str,char * ws,char * hardsep)56 getlist (
57 	char *			str,
58 	char *			ws,
59 	char *			hardsep
60 )
61 #else
62 getlist (str, ws, hardsep)
63 	register char		*str,
64 				*ws;
65 	char			*hardsep;
66 #endif
67 {
68 	register char		**list,
69 				*p,
70 				*sep,
71 				c;
72 
73 	int			n,
74 				len;
75 
76 	char			buf[10];
77 
78 
79 	char			*copy,
80 				*begin;
81 
82 	if (!str || !*str)
83 		return (0);
84 
85 	/*
86 	 * Construct in "sep" the full list of characters that
87 	 * can separate items in the list. Avoid a "malloc()"
88 	 * if possible.
89 	 */
90 	len = strlen(ws) + strlen(hardsep) + 1;
91 	if (len > sizeof(buf)) {
92 		if (!(sep = Malloc(len))) {
93 			errno = ENOMEM;
94 			return (0);
95 		}
96 	} else
97 		sep = buf;
98 	strcpy (sep, hardsep);
99 	strcat (sep, ws);
100 
101 	/*
102 	 * Copy the input string because getlist() sometimes writes to it.
103 	 */
104 	if (!(begin = Strdup(str))) {
105 		errno = ENOMEM;
106 		return (0);
107 	}
108 	copy = begin;
109 
110 	/*
111 	 * Skip leading white-space.
112 	 */
113 	copy += strspn(copy, ws);
114 	if (!*copy) {
115 		Free (begin);
116 		return (0);
117 	}
118 
119 	/*
120 	 * Strip trailing white-space.
121 	 */
122 	p = strchr(copy, '\0');
123 	while (--p != copy && strchr(ws, *p))
124 		;
125 	*++p = 0;
126 
127 	/*
128 	 * Pass 1: Count the number of items in the list.
129 	 */
130 	for (n = 0, p = copy; *p; ) {
131 		if ((c = *p++) == '\\')
132 			p++;
133 		else
134 			if (strchr(sep, c)) {
135 				n++;
136 				p += strspn(p, ws);
137 				if (
138 					!strchr(hardsep, c)
139 				     && strchr(hardsep, *p)
140 				) {
141 					p++;
142 					p += strspn(p, ws);
143 				}
144 			}
145 	}
146 
147 	/*
148 	 * Pass 2: Create the list.
149 	 */
150 
151 	/*
152 	 * Pass 1 counted the number of list separaters, so
153 	 * add 2 to the count (includes 1 for terminating null).
154 	 */
155 	if (!(list = (char **)Malloc((n+2) * sizeof(char *)))) {
156 		errno = ENOMEM;
157 		goto Done;
158 	}
159 
160 	/*
161 	 * This loop will copy all but the last item.
162 	 */
163 	for (n = 0, p = copy; *p; )
164 		if ((c = *p++) == '\\')
165 			p++;
166 		else
167 			if (strchr(sep, c)) {
168 
169 				p[-1] = 0;
170 				list[n++] = unq_strdup(copy, sep);
171 				p[-1] = c;
172 
173 				p += strspn(p, ws);
174 				if (
175 					!strchr(hardsep, c)
176 				     && strchr(hardsep, *p)
177 				) {
178 					p++;
179 					p += strspn(p, ws);
180 				}
181 				copy = p;
182 
183 			}
184 
185 	list[n++] = unq_strdup(copy, sep);
186 
187 	list[n] = 0;
188 
189 Done:	if (sep != buf)
190 		Free (sep);
191 	Free (begin);
192 	return (list);
193 }
194 
195 /**
196  ** unq_strdup()
197  **/
198 
199 static char *
200 #if	defined(__STDC__)
unq_strdup(char * str,char * sep)201 unq_strdup (
202 	char *			str,
203 	char *			sep
204 )
205 #else
206 unq_strdup (str, sep)
207 	char			*str,
208 				*sep;
209 #endif
210 {
211 	register int		len	= 0;
212 
213 	register char		*p,
214 				*q,
215 				*ret;
216 
217 
218 	for (p = str; *p; p++)
219 		if (*p != '\\' || !p[1] || !strchr(sep, p[1]))
220 			len++;
221 	if (!(q = ret = Malloc(len + 1)))
222 		return (0);
223 	for (p = str; *p; p++)
224 		if (*p != '\\' || !p[1] || !strchr(sep, p[1]))
225 			*q++ = *p;
226 	*q = 0;
227 	return (ret);
228 }
229