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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Helper functions to skip white spaces, find tokens, find separators and free
31  * memory.
32  */
33 
34 #include <errno.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <ctype.h>
38 
39 #include "commp_util.h"
40 
41 
42 /*
43  * Skip to the next non-whitespace
44  */
45 int
commp_skip_white_space(const char ** begin,const char * end)46 commp_skip_white_space(const char **begin, const char *end)
47 {
48 	while (*begin < end) {
49 		if (!isspace(**begin))
50 			return (0);
51 		(*begin)++;
52 	}
53 	return (1);
54 }
55 
56 /*
57  * Finds the token in the char buffer. *current will be pointing to the
58  * token when function returns. If the char buffer has leading token,
59  * it returns 1.
60  */
61 int
commp_find_token(const char ** begin,const char ** current,const char * end,char token,boolean_t last)62 commp_find_token(const char **begin, const char **current,  const char *end,
63     char token, boolean_t last)
64 {
65 	*current = *begin;
66 	while (*current < end) {
67 		if (!last && (**current == token))
68 			break;
69 		else if (isspace(**current))
70 			return (1);
71 		(*current)++;
72 	}
73 	/* Checks for leading white space */
74 	if (*current == *begin)
75 		return (1);
76 	else
77 		return (0);
78 }
79 
80 /*
81  * atoi function
82  */
83 int
commp_atoi(const char * begin,const char * end,int * num)84 commp_atoi(const char *begin, const char *end, int *num)
85 {
86 	boolean_t	num_found = B_FALSE;
87 
88 	*num = 0;
89 	while (begin < end) {
90 		if (isdigit(*begin)) {
91 			*num = (*num * 10) + (*begin - '0');
92 			num_found = B_TRUE;
93 			begin++;
94 		} else {
95 			break;
96 		}
97 	}
98 	if (!num_found || (begin != end))
99 		return (EINVAL);
100 	return (0);
101 }
102 
103 /*
104  * Given a string converts it to unsigned long long int.
105  */
106 int
commp_strtoull(const char * begin,const char * end,uint64_t * num)107 commp_strtoull(const char *begin, const char *end, uint64_t *num)
108 {
109 	boolean_t	num_found = B_FALSE;
110 
111 	*num = 0;
112 	while (begin < end) {
113 		if (isdigit(*begin)) {
114 			*num = (*num * 10) + (*begin - '0');
115 			num_found = B_TRUE;
116 			begin++;
117 		} else {
118 			break;
119 		}
120 	}
121 	if (!num_found || (begin != end))
122 		return (EINVAL);
123 	return (0);
124 }
125 
126 /*
127  * Given a string converts it to unsigned byte
128  */
129 int
commp_strtoub(const char * begin,const char * end,uint8_t * num)130 commp_strtoub(const char *begin, const char *end, uint8_t *num)
131 {
132 	boolean_t	num_found = B_FALSE;
133 
134 	*num = 0;
135 	while (begin < end) {
136 		if (isdigit(*begin)) {
137 			*num = (*num * 10) + (*begin - '0');
138 			num_found = B_TRUE;
139 			begin++;
140 		} else {
141 			break;
142 		}
143 	}
144 	if (!num_found || (begin != end))
145 		return (EINVAL);
146 	return (0);
147 }
148 
149 /*
150  * Given a string converts it to unsigned int
151  */
152 int
commp_atoui(const char * begin,const char * end,uint_t * num)153 commp_atoui(const char *begin, const char *end, uint_t *num)
154 {
155 	boolean_t	num_found = B_FALSE;
156 
157 	*num = 0;
158 	while (begin < end) {
159 		if (isdigit(*begin)) {
160 			*num = (*num * 10) + (*begin - '0');
161 			num_found = B_TRUE;
162 			begin++;
163 		} else {
164 			break;
165 		}
166 	}
167 	if (!num_found || (begin != end))
168 		return (EINVAL);
169 	return (0);
170 }
171 
172 /*
173  * allocates memory and copies string to new memory
174  */
175 int
commp_add_str(char ** dest,const char * src,int len)176 commp_add_str(char **dest, const char *src, int len)
177 {
178 	if (len == 0)
179 		return (EINVAL);
180 	(*dest) = calloc(1, len + 1);
181 	if (*dest == NULL)
182 		return (ENOMEM);
183 	(void) strncpy(*dest, src, len);
184 	return (0);
185 }
186 
187 /*
188  * This function converts strings like "5d" to equivalent time in secs.
189  * For eg. 1h = 3600, 10d = 86400
190  */
191 int
commp_time_to_secs(const char * begin,const char * end,uint64_t * num)192 commp_time_to_secs(const char *begin, const char *end, uint64_t *num)
193 {
194 	uint_t		factor = 0;
195 
196 	if (!isdigit(*(end - 1))) {
197 		switch (*(end - 1)) {
198 			case 'd':
199 				factor = COMMP_SECS_IN_DAY;
200 				break;
201 			case 'h':
202 				factor = COMMP_SECS_IN_HOUR;
203 				break;
204 			case 'm':
205 				factor = COMMP_SECS_IN_MIN;
206 				break;
207 			case 's':
208 				factor = 1;
209 				break;
210 			default:
211 				return (EINVAL);
212 		}
213 		--end;
214 	}
215 	if (commp_strtoull(begin, end, num) != 0)
216 		return (EINVAL);
217 	if (factor != 0)
218 		(*num) = (*num) * factor;
219 	return (0);
220 }
221