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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Helper functions to skip white spaces, find tokens, find separators and free
29  * memory.
30  */
31 
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 
37 #include "commp_util.h"
38 
39 
40 /*
41  * Skip to the next non-whitespace
42  */
43 int
commp_skip_white_space(const char ** begin,const char * end)44 commp_skip_white_space(const char **begin, const char *end)
45 {
46 	while (*begin < end) {
47 		if (!isspace(**begin))
48 			return (0);
49 		(*begin)++;
50 	}
51 	return (1);
52 }
53 
54 /*
55  * Finds the token in the char buffer. *current will be pointing to the
56  * token when function returns. If the char buffer has leading token,
57  * it returns 1.
58  */
59 int
commp_find_token(const char ** begin,const char ** current,const char * end,char token,boolean_t last)60 commp_find_token(const char **begin, const char **current,  const char *end,
61     char token, boolean_t last)
62 {
63 	*current = *begin;
64 	while (*current < end) {
65 		if (!last && (**current == token))
66 			break;
67 		else if (isspace(**current))
68 			return (1);
69 		(*current)++;
70 	}
71 	/* Checks for leading white space */
72 	if (*current == *begin)
73 		return (1);
74 	else
75 		return (0);
76 }
77 
78 /*
79  * atoi function
80  */
81 int
commp_atoi(const char * begin,const char * end,int * num)82 commp_atoi(const char *begin, const char *end, int *num)
83 {
84 	boolean_t	num_found = B_FALSE;
85 
86 	*num = 0;
87 	while (begin < end) {
88 		if (isdigit(*begin)) {
89 			*num = (*num * 10) + (*begin - '0');
90 			num_found = B_TRUE;
91 			begin++;
92 		} else {
93 			break;
94 		}
95 	}
96 	if (!num_found || (begin != end))
97 		return (EINVAL);
98 	return (0);
99 }
100 
101 /*
102  * Given a string converts it to unsigned long long int.
103  */
104 int
commp_strtoull(const char * begin,const char * end,uint64_t * num)105 commp_strtoull(const char *begin, const char *end, uint64_t *num)
106 {
107 	boolean_t	num_found = B_FALSE;
108 
109 	*num = 0;
110 	while (begin < end) {
111 		if (isdigit(*begin)) {
112 			*num = (*num * 10) + (*begin - '0');
113 			num_found = B_TRUE;
114 			begin++;
115 		} else {
116 			break;
117 		}
118 	}
119 	if (!num_found || (begin != end))
120 		return (EINVAL);
121 	return (0);
122 }
123 
124 /*
125  * Given a string converts it to unsigned byte
126  */
127 int
commp_strtoub(const char * begin,const char * end,uint8_t * num)128 commp_strtoub(const char *begin, const char *end, uint8_t *num)
129 {
130 	boolean_t	num_found = B_FALSE;
131 
132 	*num = 0;
133 	while (begin < end) {
134 		if (isdigit(*begin)) {
135 			*num = (*num * 10) + (*begin - '0');
136 			num_found = B_TRUE;
137 			begin++;
138 		} else {
139 			break;
140 		}
141 	}
142 	if (!num_found || (begin != end))
143 		return (EINVAL);
144 	return (0);
145 }
146 
147 /*
148  * Given a string converts it to unsigned int
149  */
150 int
commp_atoui(const char * begin,const char * end,uint_t * num)151 commp_atoui(const char *begin, const char *end, uint_t *num)
152 {
153 	boolean_t	num_found = B_FALSE;
154 
155 	*num = 0;
156 	while (begin < end) {
157 		if (isdigit(*begin)) {
158 			*num = (*num * 10) + (*begin - '0');
159 			num_found = B_TRUE;
160 			begin++;
161 		} else {
162 			break;
163 		}
164 	}
165 	if (!num_found || (begin != end))
166 		return (EINVAL);
167 	return (0);
168 }
169 
170 /*
171  * allocates memory and copies string to new memory
172  */
173 int
commp_add_str(char ** dest,const char * src,int len)174 commp_add_str(char **dest, const char *src, int len)
175 {
176 	if (len == 0)
177 		return (EINVAL);
178 	(*dest) = calloc(1, len + 1);
179 	if (*dest == NULL)
180 		return (ENOMEM);
181 	(void) strncpy(*dest, src, len);
182 	return (0);
183 }
184 
185 /*
186  * This function converts strings like "5d" to equivalent time in secs.
187  * For eg. 1h = 3600, 10d = 86400
188  */
189 int
commp_time_to_secs(const char * begin,const char * end,uint64_t * num)190 commp_time_to_secs(const char *begin, const char *end, uint64_t *num)
191 {
192 	uint_t		factor = 0;
193 
194 	if (!isdigit(*(end - 1))) {
195 		switch (*(end - 1)) {
196 			case 'd':
197 				factor = COMMP_SECS_IN_DAY;
198 				break;
199 			case 'h':
200 				factor = COMMP_SECS_IN_HOUR;
201 				break;
202 			case 'm':
203 				factor = COMMP_SECS_IN_MIN;
204 				break;
205 			case 's':
206 				factor = 1;
207 				break;
208 			default:
209 				return (EINVAL);
210 		}
211 		--end;
212 	}
213 	if (commp_strtoull(begin, end, num) != 0)
214 		return (EINVAL);
215 	if (factor != 0)
216 		(*num) = (*num) * factor;
217 	return (0);
218 }
219