xref: /titanic_50/usr/src/cmd/prctl/utils.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
30*7c478bd9Sstevel@tonic-gate #include <libintl.h>
31*7c478bd9Sstevel@tonic-gate #include <string.h>
32*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
33*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
34*7c478bd9Sstevel@tonic-gate #include <stdio.h>
35*7c478bd9Sstevel@tonic-gate #include <errno.h>
36*7c478bd9Sstevel@tonic-gate #include <strings.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
38*7c478bd9Sstevel@tonic-gate #include <limits.h>
39*7c478bd9Sstevel@tonic-gate #include "utils.h"
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate static char PNAME_FMT[] = "%s: ";
42*7c478bd9Sstevel@tonic-gate static char ERRNO_FMT[] = ": %s\n";
43*7c478bd9Sstevel@tonic-gate static char EOL_FMT[] = "\n";
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate static char *pname;
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate char *
48*7c478bd9Sstevel@tonic-gate setprogname(char *arg0)
49*7c478bd9Sstevel@tonic-gate {
50*7c478bd9Sstevel@tonic-gate 	char *p = strrchr(arg0, '/');
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate 	if (p == NULL)
53*7c478bd9Sstevel@tonic-gate 		p = arg0;
54*7c478bd9Sstevel@tonic-gate 	else
55*7c478bd9Sstevel@tonic-gate 		p++;
56*7c478bd9Sstevel@tonic-gate 	pname = p;
57*7c478bd9Sstevel@tonic-gate 	return (pname);
58*7c478bd9Sstevel@tonic-gate }
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
61*7c478bd9Sstevel@tonic-gate void
62*7c478bd9Sstevel@tonic-gate warn(char *format, ...)
63*7c478bd9Sstevel@tonic-gate {
64*7c478bd9Sstevel@tonic-gate 	int err = errno;
65*7c478bd9Sstevel@tonic-gate 	va_list alist;
66*7c478bd9Sstevel@tonic-gate 	if (pname != NULL)
67*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(PNAME_FMT), pname);
68*7c478bd9Sstevel@tonic-gate 	va_start(alist, format);
69*7c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, format, alist);
70*7c478bd9Sstevel@tonic-gate 	va_end(alist);
71*7c478bd9Sstevel@tonic-gate 	if (strchr(format, '\n') == NULL)
72*7c478bd9Sstevel@tonic-gate 		if (err)
73*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
74*7c478bd9Sstevel@tonic-gate 			    gettext(ERRNO_FMT), strerror(err));
75*7c478bd9Sstevel@tonic-gate 		else
76*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(EOL_FMT));
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate }
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate static char *__metric_modifiers[] = { "K", "M", "G", "T", "P", "E", NULL };
82*7c478bd9Sstevel@tonic-gate static uint64_t __metric_scales[] = {
83*7c478bd9Sstevel@tonic-gate     1000LLU,
84*7c478bd9Sstevel@tonic-gate     1000LLU * 1000,
85*7c478bd9Sstevel@tonic-gate     1000LLU * 1000 * 1000,
86*7c478bd9Sstevel@tonic-gate     1000LLU * 1000 * 1000 * 1000,
87*7c478bd9Sstevel@tonic-gate     1000LLU * 1000 * 1000 * 1000 * 1000,
88*7c478bd9Sstevel@tonic-gate     1000LLU * 1000 * 1000 * 1000 * 1000 * 1000
89*7c478bd9Sstevel@tonic-gate };
90*7c478bd9Sstevel@tonic-gate static scale_t __metric_scale = { __metric_modifiers, __metric_scales };
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate static char *__binary_modifiers[] = {"K", "M", "G", "T", "P", "E", NULL};
93*7c478bd9Sstevel@tonic-gate static uint64_t __binary_scales[] = {
94*7c478bd9Sstevel@tonic-gate     1024LLU,
95*7c478bd9Sstevel@tonic-gate     1024LLU * 1024,
96*7c478bd9Sstevel@tonic-gate     1024LLU * 1024 * 1024,
97*7c478bd9Sstevel@tonic-gate     1024LLU * 1024 * 1024 * 1024,
98*7c478bd9Sstevel@tonic-gate     1024LLU * 1024 * 1024 * 1024 * 1024,
99*7c478bd9Sstevel@tonic-gate     1024LLU * 1024 * 1024 * 1024 * 1024 * 1024
100*7c478bd9Sstevel@tonic-gate };
101*7c478bd9Sstevel@tonic-gate static scale_t __binary_scale = { __binary_modifiers, __binary_scales };
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate scale_t *scale_metric = &__metric_scale;
104*7c478bd9Sstevel@tonic-gate scale_t *scale_binary = &__binary_scale;
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate int
107*7c478bd9Sstevel@tonic-gate scaledtouint64(char *scaledin,
108*7c478bd9Sstevel@tonic-gate     uint64_t *uint64out,
109*7c478bd9Sstevel@tonic-gate     int *widthout, char **modifierout, char **unitout,
110*7c478bd9Sstevel@tonic-gate     scale_t *scale, char *unit, int flags) {
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	double result;
113*7c478bd9Sstevel@tonic-gate 	double value;
114*7c478bd9Sstevel@tonic-gate 	int index = 0;
115*7c478bd9Sstevel@tonic-gate 	uint64_t multiplier = 1;
116*7c478bd9Sstevel@tonic-gate 	char string[SCALED_STRLEN];
117*7c478bd9Sstevel@tonic-gate 	char *endptr;
118*7c478bd9Sstevel@tonic-gate 	int cmp;
119*7c478bd9Sstevel@tonic-gate 	int hasmodifier = 0;
120*7c478bd9Sstevel@tonic-gate 	char **modifiers = scale->modifers;
121*7c478bd9Sstevel@tonic-gate 	uint64_t *scales = scale->scales;
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate 	if (modifierout)
124*7c478bd9Sstevel@tonic-gate 		*modifierout = NULL;
125*7c478bd9Sstevel@tonic-gate 	if (unitout)
126*7c478bd9Sstevel@tonic-gate 		*unitout = NULL;
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	/*
129*7c478bd9Sstevel@tonic-gate 	 * first check for hex value, which cannot be scaled, as
130*7c478bd9Sstevel@tonic-gate 	 * hex letters cannot be disserned from modifier or unit letters
131*7c478bd9Sstevel@tonic-gate 	 */
132*7c478bd9Sstevel@tonic-gate 	if ((strncmp("0x", scaledin, 2) == 0) ||
133*7c478bd9Sstevel@tonic-gate 	    (strncmp("0X", scaledin, 2) == 0)) {
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate 		/* unit cannot be required on hex values */
136*7c478bd9Sstevel@tonic-gate 		if ((unit && *unit != '\0') &&
137*7c478bd9Sstevel@tonic-gate 		    !(flags & SCALED_UNIT_OPTIONAL_FLAG))
138*7c478bd9Sstevel@tonic-gate 			return (SCALED_INVALID_UNIT);
139*7c478bd9Sstevel@tonic-gate 
140*7c478bd9Sstevel@tonic-gate 		errno = 0;
141*7c478bd9Sstevel@tonic-gate 		*uint64out = strtoull(scaledin, &endptr, 16);
142*7c478bd9Sstevel@tonic-gate 		if (errno) {
143*7c478bd9Sstevel@tonic-gate 			if (errno == ERANGE)
144*7c478bd9Sstevel@tonic-gate 				return (SCALED_OVERFLOW);
145*7c478bd9Sstevel@tonic-gate 			else
146*7c478bd9Sstevel@tonic-gate 				return (SCALED_INVALID_NUMBER);
147*7c478bd9Sstevel@tonic-gate 		}
148*7c478bd9Sstevel@tonic-gate 		if (*endptr != '\0')
149*7c478bd9Sstevel@tonic-gate 			return (SCALED_INVALID_NUMBER);
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 		/* compute width of decimal equivalent */
152*7c478bd9Sstevel@tonic-gate 		if (widthout) {
153*7c478bd9Sstevel@tonic-gate 			(void) snprintf(
154*7c478bd9Sstevel@tonic-gate 			    string, SCALED_STRLEN, "%llu", *uint64out);
155*7c478bd9Sstevel@tonic-gate 			*widthout = strlen(string);
156*7c478bd9Sstevel@tonic-gate 		}
157*7c478bd9Sstevel@tonic-gate 		return (0);
158*7c478bd9Sstevel@tonic-gate 	}
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	/* scan out numeric value */
161*7c478bd9Sstevel@tonic-gate 	errno = 0;
162*7c478bd9Sstevel@tonic-gate 	value = strtod(scaledin, &endptr);
163*7c478bd9Sstevel@tonic-gate 	if (errno) {
164*7c478bd9Sstevel@tonic-gate 		if (errno == ERANGE)
165*7c478bd9Sstevel@tonic-gate 			return (SCALED_OVERFLOW);
166*7c478bd9Sstevel@tonic-gate 		else
167*7c478bd9Sstevel@tonic-gate 			return (SCALED_INVALID_NUMBER);
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 	}
170*7c478bd9Sstevel@tonic-gate 	if (endptr == scaledin)
171*7c478bd9Sstevel@tonic-gate 		return (SCALED_INVALID_NUMBER);
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	/* no negative values */
174*7c478bd9Sstevel@tonic-gate 	if (strchr(scaledin, '-'))
175*7c478bd9Sstevel@tonic-gate 		return (SCALED_INVALID_NUMBER);
176*7c478bd9Sstevel@tonic-gate 	if (value < 0.0)
177*7c478bd9Sstevel@tonic-gate 		return (SCALED_INVALID_NUMBER);
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	/* compute width of number string */
181*7c478bd9Sstevel@tonic-gate 	if (widthout)
182*7c478bd9Sstevel@tonic-gate 		*widthout = (int)(endptr - scaledin);
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 	/* check possible modifier */
185*7c478bd9Sstevel@tonic-gate 	if (*endptr != '\0') {
186*7c478bd9Sstevel@tonic-gate 		index = 0;
187*7c478bd9Sstevel@tonic-gate 		while (modifiers[index] != NULL) {
188*7c478bd9Sstevel@tonic-gate 			if (flags & SCALED_MODIFIER_CASE_INSENSITIVE_FLAG)
189*7c478bd9Sstevel@tonic-gate 				cmp = strncasecmp(modifiers[index], endptr,
190*7c478bd9Sstevel@tonic-gate 				    strlen(modifiers[index]));
191*7c478bd9Sstevel@tonic-gate 			else
192*7c478bd9Sstevel@tonic-gate 				cmp = strncmp(modifiers[index], endptr,
193*7c478bd9Sstevel@tonic-gate 				    strlen(modifiers[index]));
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 			if (cmp == 0) {
196*7c478bd9Sstevel@tonic-gate 				if (modifierout)
197*7c478bd9Sstevel@tonic-gate 					*modifierout = modifiers[index];
198*7c478bd9Sstevel@tonic-gate 				endptr += strlen(modifiers[index]);
199*7c478bd9Sstevel@tonic-gate 				multiplier = scales[index];
200*7c478bd9Sstevel@tonic-gate 				result = value * multiplier;
201*7c478bd9Sstevel@tonic-gate 				if (result > UINT64_MAX)
202*7c478bd9Sstevel@tonic-gate 					return (SCALED_OVERFLOW);
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 				*uint64out = (uint64_t)result;
205*7c478bd9Sstevel@tonic-gate 				hasmodifier = 1;
206*7c478bd9Sstevel@tonic-gate 				break;
207*7c478bd9Sstevel@tonic-gate 			}
208*7c478bd9Sstevel@tonic-gate 			index++;
209*7c478bd9Sstevel@tonic-gate 		}
210*7c478bd9Sstevel@tonic-gate 	}
211*7c478bd9Sstevel@tonic-gate 	/* if there is no modifier, value must be an integer */
212*7c478bd9Sstevel@tonic-gate 	if (!hasmodifier) {
213*7c478bd9Sstevel@tonic-gate 		errno = 0;
214*7c478bd9Sstevel@tonic-gate 		*uint64out = strtoull(scaledin, &endptr, 0);
215*7c478bd9Sstevel@tonic-gate 		if (errno) {
216*7c478bd9Sstevel@tonic-gate 			if (errno == ERANGE)
217*7c478bd9Sstevel@tonic-gate 				return (SCALED_OVERFLOW);
218*7c478bd9Sstevel@tonic-gate 			else
219*7c478bd9Sstevel@tonic-gate 				return (SCALED_INVALID_NUMBER);
220*7c478bd9Sstevel@tonic-gate 		}
221*7c478bd9Sstevel@tonic-gate 		if (endptr == scaledin)
222*7c478bd9Sstevel@tonic-gate 			return (SCALED_INVALID_NUMBER);
223*7c478bd9Sstevel@tonic-gate 	}
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	/* if unit is present when no unit is allowed, fail */
226*7c478bd9Sstevel@tonic-gate 	if ((unit == NULL || *unit == '\0') && (*endptr != '\0'))
227*7c478bd9Sstevel@tonic-gate 		return (SCALED_INVALID_UNIT);
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 	/* check for missing unit when unit is required */
230*7c478bd9Sstevel@tonic-gate 	if ((unit && *unit != '\0') &&
231*7c478bd9Sstevel@tonic-gate 	    !(flags & SCALED_UNIT_OPTIONAL_FLAG) &&
232*7c478bd9Sstevel@tonic-gate 	    (*endptr == '\0'))
233*7c478bd9Sstevel@tonic-gate 		return (SCALED_INVALID_UNIT);
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	/* validate unit */
236*7c478bd9Sstevel@tonic-gate 	if (unit && *unit != '\0') {
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 		/* allow for missing unit if it is optional */
239*7c478bd9Sstevel@tonic-gate 		if ((flags & SCALED_UNIT_OPTIONAL_FLAG) &&
240*7c478bd9Sstevel@tonic-gate 		    (*endptr == '\0'))
241*7c478bd9Sstevel@tonic-gate 			return (0);
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 		if (flags & SCALED_UNIT_CASE_INSENSITIVE_FLAG)
244*7c478bd9Sstevel@tonic-gate 			cmp = strncasecmp(unit, endptr, strlen(unit));
245*7c478bd9Sstevel@tonic-gate 		else
246*7c478bd9Sstevel@tonic-gate 			cmp = strncmp(unit, endptr, strlen(unit));
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 		if (cmp != 0)
249*7c478bd9Sstevel@tonic-gate 			return (SCALED_INVALID_UNIT);
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 		if (*(endptr + strlen(unit)) != '\0')
252*7c478bd9Sstevel@tonic-gate 			return (SCALED_INVALID_UNIT);
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 		if (unitout)
255*7c478bd9Sstevel@tonic-gate 			*unitout = unit;
256*7c478bd9Sstevel@tonic-gate 	}
257*7c478bd9Sstevel@tonic-gate 	return (0);
258*7c478bd9Sstevel@tonic-gate }
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate int
262*7c478bd9Sstevel@tonic-gate uint64toscaled(uint64_t uint64in, int widthin, char *maxmodifierin,
263*7c478bd9Sstevel@tonic-gate     char *scaledout, int *widthout, char **modifierout,
264*7c478bd9Sstevel@tonic-gate     scale_t *scale, char *unit, int flags) {
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	int index = 0;
267*7c478bd9Sstevel@tonic-gate 	int count;
268*7c478bd9Sstevel@tonic-gate 	int width;
269*7c478bd9Sstevel@tonic-gate 	int decimals = 0;
270*7c478bd9Sstevel@tonic-gate 	char string[SCALED_STRLEN];
271*7c478bd9Sstevel@tonic-gate 	double value;
272*7c478bd9Sstevel@tonic-gate 	char **modifiers = scale->modifers;
273*7c478bd9Sstevel@tonic-gate 	uint64_t *scales = scale->scales;
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	/* don't scale if there is no reason to */
276*7c478bd9Sstevel@tonic-gate 	if (uint64in < scales[0] || maxmodifierin == NULL) {
277*7c478bd9Sstevel@tonic-gate 		if (flags & SCALED_PAD_WIDTH_FLAG)
278*7c478bd9Sstevel@tonic-gate 			width = widthin;
279*7c478bd9Sstevel@tonic-gate 		else
280*7c478bd9Sstevel@tonic-gate 			width = 0;
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 		(void) snprintf(string, SCALED_STRLEN, "%%%dllu", width);
283*7c478bd9Sstevel@tonic-gate 		/* LINTED */
284*7c478bd9Sstevel@tonic-gate 		count = snprintf(scaledout, SCALED_STRLEN, string, uint64in);
285*7c478bd9Sstevel@tonic-gate 		if (unit && *unit != '\0')
286*7c478bd9Sstevel@tonic-gate 			(void) strcat(scaledout, unit);
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 		if (widthout)
289*7c478bd9Sstevel@tonic-gate 			*widthout = count;
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 		if (modifierout)
292*7c478bd9Sstevel@tonic-gate 			*modifierout = NULL;
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 		return (0);
295*7c478bd9Sstevel@tonic-gate 	}
296*7c478bd9Sstevel@tonic-gate 
297*7c478bd9Sstevel@tonic-gate 	for (index = 0; modifiers[index + 1] != NULL; index++) {
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 		if (uint64in >= scales[index] &&
300*7c478bd9Sstevel@tonic-gate 		    uint64in < scales[index + 1])
301*7c478bd9Sstevel@tonic-gate 			break;
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 		if ((strncmp(modifiers[index], maxmodifierin,
304*7c478bd9Sstevel@tonic-gate 		    strlen(modifiers[index])) == 0) &&
305*7c478bd9Sstevel@tonic-gate 		    (strlen(modifiers[index]) == strlen(maxmodifierin)))
306*7c478bd9Sstevel@tonic-gate 			break;
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 	}
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 	value = ((double)(uint64in)) / scales[index];
311*7c478bd9Sstevel@tonic-gate 	if (modifierout)
312*7c478bd9Sstevel@tonic-gate 		*modifierout = modifiers[index];
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate 	count = snprintf(string, SCALED_STRLEN, "%0.0lf", value);
315*7c478bd9Sstevel@tonic-gate 	while (count < widthin) {
316*7c478bd9Sstevel@tonic-gate 		decimals++;
317*7c478bd9Sstevel@tonic-gate 		(void) snprintf(string, SCALED_STRLEN, "%%0.%dlf", decimals);
318*7c478bd9Sstevel@tonic-gate 		/* LINTED */
319*7c478bd9Sstevel@tonic-gate 		count = snprintf(scaledout, SCALED_STRLEN, string, value);
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate 		/* reduce decimal places if we've overshot the desired width */
322*7c478bd9Sstevel@tonic-gate 		if (count > widthin) {
323*7c478bd9Sstevel@tonic-gate 			decimals--;
324*7c478bd9Sstevel@tonic-gate 			break;
325*7c478bd9Sstevel@tonic-gate 		}
326*7c478bd9Sstevel@tonic-gate 	}
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate 	if (flags & SCALED_PAD_WIDTH_FLAG)
329*7c478bd9Sstevel@tonic-gate 		width = widthin;
330*7c478bd9Sstevel@tonic-gate 	else
331*7c478bd9Sstevel@tonic-gate 		width = 0;
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate 	(void) snprintf(string, SCALED_STRLEN, "%%%d.%dlf", width, decimals);
334*7c478bd9Sstevel@tonic-gate 	/* LINTED */
335*7c478bd9Sstevel@tonic-gate 	count = snprintf(scaledout, SCALED_STRLEN, string, value);
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	(void) strcat(scaledout, modifiers[index]);
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	if (unit && *unit != '\0')
340*7c478bd9Sstevel@tonic-gate 		(void) strcat(scaledout, unit);
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate 	if (widthout)
343*7c478bd9Sstevel@tonic-gate 		*widthout = count;
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate 	return (0);
346*7c478bd9Sstevel@tonic-gate }
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate int
349*7c478bd9Sstevel@tonic-gate scaledtoscaled(char *scaledin, int widthin, char *maxmodifierin,
350*7c478bd9Sstevel@tonic-gate     char *scaledout, int *widthout, char **modifierout,
351*7c478bd9Sstevel@tonic-gate     scale_t *scale, char *unit, int flags) {
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 	int ret;
354*7c478bd9Sstevel@tonic-gate 	uint64_t val;
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate 	ret = scaledtouint64(scaledin, &val, NULL, NULL, NULL,
357*7c478bd9Sstevel@tonic-gate 	    scale, unit, flags);
358*7c478bd9Sstevel@tonic-gate 	if (ret)
359*7c478bd9Sstevel@tonic-gate 		return (ret);
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 	ret = uint64toscaled(val, widthin, maxmodifierin,
362*7c478bd9Sstevel@tonic-gate 	    scaledout, widthout, modifierout,
363*7c478bd9Sstevel@tonic-gate 	    scale, unit, flags);
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 	return (ret);
366*7c478bd9Sstevel@tonic-gate }
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate int
369*7c478bd9Sstevel@tonic-gate scaledeqscaled(char *scaled1, char *scaled2,
370*7c478bd9Sstevel@tonic-gate     scale_t *scale, char *unit, int flags) {
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate 	int ret;
373*7c478bd9Sstevel@tonic-gate 	uint64_t uint64;
374*7c478bd9Sstevel@tonic-gate 	char *modifier1;
375*7c478bd9Sstevel@tonic-gate 	char *modifier2;
376*7c478bd9Sstevel@tonic-gate 	char *modifier = NULL;
377*7c478bd9Sstevel@tonic-gate 	int i;
378*7c478bd9Sstevel@tonic-gate 	int width;
379*7c478bd9Sstevel@tonic-gate 	int width1;
380*7c478bd9Sstevel@tonic-gate 	int width2;
381*7c478bd9Sstevel@tonic-gate 	char scaledA[SCALED_STRLEN];
382*7c478bd9Sstevel@tonic-gate 	char scaledB[SCALED_STRLEN];
383*7c478bd9Sstevel@tonic-gate 	char **modifiers = scale->modifers;
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate 	/*
386*7c478bd9Sstevel@tonic-gate 	 * remove padding flag, so strings to compare will not have
387*7c478bd9Sstevel@tonic-gate 	 * whitespace
388*7c478bd9Sstevel@tonic-gate 	 */
389*7c478bd9Sstevel@tonic-gate 	flags = flags & (~SCALED_PAD_WIDTH_FLAG);
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 	/* determine each number's width and modifier */
392*7c478bd9Sstevel@tonic-gate 	ret = scaledtouint64(scaled1, &uint64, &width1, &modifier1, NULL,
393*7c478bd9Sstevel@tonic-gate 	    scale, unit, flags);
394*7c478bd9Sstevel@tonic-gate 	if (ret)
395*7c478bd9Sstevel@tonic-gate 		return (0);
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	ret = scaledtouint64(scaled2, &uint64, &width2, &modifier2, NULL,
398*7c478bd9Sstevel@tonic-gate 	    scale, unit, flags);
399*7c478bd9Sstevel@tonic-gate 	if (ret)
400*7c478bd9Sstevel@tonic-gate 		return (0);
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate 	/*
403*7c478bd9Sstevel@tonic-gate 	 * determine the width and modifier to use for comparison.
404*7c478bd9Sstevel@tonic-gate 	 * Use widest width and smallest modifier.
405*7c478bd9Sstevel@tonic-gate 	 * Rescale to new width and modifier
406*7c478bd9Sstevel@tonic-gate 	 */
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 	if (modifier1 == NULL || modifier2 == NULL)
409*7c478bd9Sstevel@tonic-gate 		modifier = NULL;
410*7c478bd9Sstevel@tonic-gate 	else {
411*7c478bd9Sstevel@tonic-gate 		for (i = 0; modifiers[i] != NULL; i++) {
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate 			if (strcmp(modifier1, modifiers[i]) == 0) {
414*7c478bd9Sstevel@tonic-gate 				modifier = modifiers[i];
415*7c478bd9Sstevel@tonic-gate 				break;
416*7c478bd9Sstevel@tonic-gate 			}
417*7c478bd9Sstevel@tonic-gate 			if (strcmp(modifier2, modifiers[i]) == 0) {
418*7c478bd9Sstevel@tonic-gate 				modifier = modifiers[i];
419*7c478bd9Sstevel@tonic-gate 				break;
420*7c478bd9Sstevel@tonic-gate 			}
421*7c478bd9Sstevel@tonic-gate 		}
422*7c478bd9Sstevel@tonic-gate 	}
423*7c478bd9Sstevel@tonic-gate 	width = 0;
424*7c478bd9Sstevel@tonic-gate 	if (width1 > width)
425*7c478bd9Sstevel@tonic-gate 		width = width1;
426*7c478bd9Sstevel@tonic-gate 	if (width2 > width)
427*7c478bd9Sstevel@tonic-gate 		width = width2;
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate 	/*
430*7c478bd9Sstevel@tonic-gate 	 * Convert first number to width and modifier.
431*7c478bd9Sstevel@tonic-gate 	 * This is done for the following reasons:
432*7c478bd9Sstevel@tonic-gate 	 *	1. In case first number is hecadecimal.  This will convert
433*7c478bd9Sstevel@tonic-gate 	 *	   it to decimal
434*7c478bd9Sstevel@tonic-gate 	 *	2. In case the first number has < the minimum number of
435*7c478bd9Sstevel@tonic-gate 	 *	   columns.
436*7c478bd9Sstevel@tonic-gate 	 *	3. The first number is missing an optional unit string.
437*7c478bd9Sstevel@tonic-gate 	 *	4. Fix casing of modifier and unit.
438*7c478bd9Sstevel@tonic-gate 	 */
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 	ret = scaledtoscaled(scaled1, width, modifier,
441*7c478bd9Sstevel@tonic-gate 	    scaledA, NULL, NULL, scale, unit, flags);
442*7c478bd9Sstevel@tonic-gate 	if (ret)
443*7c478bd9Sstevel@tonic-gate 		return (0);
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate 	/* convert second number to width and modifier matching first number */
446*7c478bd9Sstevel@tonic-gate 	ret = scaledtoscaled(scaled2, width, modifier,
447*7c478bd9Sstevel@tonic-gate 	    scaledB, NULL, NULL, scale, unit, flags);
448*7c478bd9Sstevel@tonic-gate 	if (ret)
449*7c478bd9Sstevel@tonic-gate 		return (0);
450*7c478bd9Sstevel@tonic-gate 
451*7c478bd9Sstevel@tonic-gate 	/* numbers are equal if strings match */
452*7c478bd9Sstevel@tonic-gate 	return ((strncmp(scaledA, scaledB, strlen(scaledA)) == 0) &&
453*7c478bd9Sstevel@tonic-gate 	    (strlen(scaledA) == strlen(scaledB)));
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate }
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate int
458*7c478bd9Sstevel@tonic-gate scaledequint64(char *scaled, uint64_t uint64, int minwidth,
459*7c478bd9Sstevel@tonic-gate     scale_t *scale, char *unit, int flags) {
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 	int ret;
462*7c478bd9Sstevel@tonic-gate 	uint64_t tmpuint64;
463*7c478bd9Sstevel@tonic-gate 	char *modifier;
464*7c478bd9Sstevel@tonic-gate 	int width;
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 	char scaledA[SCALED_STRLEN];
467*7c478bd9Sstevel@tonic-gate 	char scaledB[SCALED_STRLEN];
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 	/* determine for number's width and modifier */
470*7c478bd9Sstevel@tonic-gate 	ret = scaledtouint64(scaled, &tmpuint64, &width, &modifier, NULL,
471*7c478bd9Sstevel@tonic-gate 	    scale, unit, flags);
472*7c478bd9Sstevel@tonic-gate 	if (ret)
473*7c478bd9Sstevel@tonic-gate 		return (0);
474*7c478bd9Sstevel@tonic-gate 
475*7c478bd9Sstevel@tonic-gate 	if (width < minwidth)
476*7c478bd9Sstevel@tonic-gate 		width = minwidth;
477*7c478bd9Sstevel@tonic-gate 
478*7c478bd9Sstevel@tonic-gate 	/*
479*7c478bd9Sstevel@tonic-gate 	 * Convert first number to width and modifier.
480*7c478bd9Sstevel@tonic-gate 	 * This is done for the following reasons:
481*7c478bd9Sstevel@tonic-gate 	 *	1. In case first number is hecadecimal.  This will convert
482*7c478bd9Sstevel@tonic-gate 	 *	   it to decimal
483*7c478bd9Sstevel@tonic-gate 	 *	2. In case the first number has < the minimum number of
484*7c478bd9Sstevel@tonic-gate 	 *	   columns.
485*7c478bd9Sstevel@tonic-gate 	 *	3. The first number is missing an optional unit string.
486*7c478bd9Sstevel@tonic-gate 	 *	4. Fix casing of modifier and unit.
487*7c478bd9Sstevel@tonic-gate 	 */
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 	ret = scaledtoscaled(scaled, width, modifier,
490*7c478bd9Sstevel@tonic-gate 	    scaledA, NULL, NULL, scale, unit, flags);
491*7c478bd9Sstevel@tonic-gate 	if (ret)
492*7c478bd9Sstevel@tonic-gate 		return (0);
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 	/* convert second number to width and modifier matching first number */
495*7c478bd9Sstevel@tonic-gate 	ret = uint64toscaled(uint64, width, modifier,
496*7c478bd9Sstevel@tonic-gate 	    scaledB, NULL, NULL, scale, unit, flags);
497*7c478bd9Sstevel@tonic-gate 	if (ret)
498*7c478bd9Sstevel@tonic-gate 		return (0);
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate 	/* numbers are equal if strings match */
501*7c478bd9Sstevel@tonic-gate 	return ((strncmp(scaledA, scaledB, strlen(scaledA)) == 0) &&
502*7c478bd9Sstevel@tonic-gate 	    (strlen(scaledA) == strlen(scaledB)));
503*7c478bd9Sstevel@tonic-gate }
504