xref: /titanic_53/usr/src/cmd/format/io.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 2005 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 /*
30*7c478bd9Sstevel@tonic-gate  * This file contains I/O related functions.
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate #include "global.h"
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <unistd.h>
35*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
36*7c478bd9Sstevel@tonic-gate #include <string.h>
37*7c478bd9Sstevel@tonic-gate #include <signal.h>
38*7c478bd9Sstevel@tonic-gate #include <ctype.h>
39*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/tty.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/termio.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/termios.h>
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate #include "startup.h"
45*7c478bd9Sstevel@tonic-gate #include "misc.h"
46*7c478bd9Sstevel@tonic-gate #include "menu_partition.h"
47*7c478bd9Sstevel@tonic-gate #include "param.h"
48*7c478bd9Sstevel@tonic-gate #include "menu.h"
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate extern int	data_lineno;
52*7c478bd9Sstevel@tonic-gate extern char	*space2str();
53*7c478bd9Sstevel@tonic-gate extern long	strtol();
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate /*
56*7c478bd9Sstevel@tonic-gate  * This variable is used to determine whether a token is present in the pipe
57*7c478bd9Sstevel@tonic-gate  * already.
58*7c478bd9Sstevel@tonic-gate  */
59*7c478bd9Sstevel@tonic-gate static	char	token_present = 0;
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate /*
62*7c478bd9Sstevel@tonic-gate  * This variable always gives us access to the most recent token type
63*7c478bd9Sstevel@tonic-gate  */
64*7c478bd9Sstevel@tonic-gate int	last_token_type = 0;
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate #ifdef	__STDC__
67*7c478bd9Sstevel@tonic-gate /*
68*7c478bd9Sstevel@tonic-gate  * Prototypes for ANSI C compilers
69*7c478bd9Sstevel@tonic-gate  */
70*7c478bd9Sstevel@tonic-gate static int	sup_get_token(char *);
71*7c478bd9Sstevel@tonic-gate static void	pushchar(int c);
72*7c478bd9Sstevel@tonic-gate static int	checkeof(void);
73*7c478bd9Sstevel@tonic-gate static void	flushline(void);
74*7c478bd9Sstevel@tonic-gate static int	strcnt(char *s1, char *s2);
75*7c478bd9Sstevel@tonic-gate static int	getbn(char *str, daddr_t *iptr);
76*7c478bd9Sstevel@tonic-gate static void	print_input_choices(int type, u_ioparam_t *param);
77*7c478bd9Sstevel@tonic-gate static int	slist_widest_str(slist_t *slist);
78*7c478bd9Sstevel@tonic-gate static void	ljust_print(char *str, int width);
79*7c478bd9Sstevel@tonic-gate static int	sup_inputchar(void);
80*7c478bd9Sstevel@tonic-gate static void	sup_pushchar(int c);
81*7c478bd9Sstevel@tonic-gate static int	geti64(char *str, uint64_t *iptr, uint64_t *wild);
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate #else	/* __STDC__ */
84*7c478bd9Sstevel@tonic-gate /*
85*7c478bd9Sstevel@tonic-gate  * Prototypes for non-ANSI C compilers
86*7c478bd9Sstevel@tonic-gate  */
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate static int	sup_get_token();
89*7c478bd9Sstevel@tonic-gate static void	pushchar(int c);
90*7c478bd9Sstevel@tonic-gate static int	checkeof(void);
91*7c478bd9Sstevel@tonic-gate static void	flushline(void);
92*7c478bd9Sstevel@tonic-gate static int	strcnt(char *s1, char *s2);
93*7c478bd9Sstevel@tonic-gate static int	getbn(char *str, daddr_t *iptr);
94*7c478bd9Sstevel@tonic-gate static void	print_input_choices(int type, u_ioparam_t *param);
95*7c478bd9Sstevel@tonic-gate static int	slist_widest_str(slist_t *slist);
96*7c478bd9Sstevel@tonic-gate static void	ljust_print(char *str, int width);
97*7c478bd9Sstevel@tonic-gate static int	sup_inputchar(void);
98*7c478bd9Sstevel@tonic-gate static void	sup_pushchar(int c);
99*7c478bd9Sstevel@tonic-gate static int	geti64(char *str, uint64_t *iptr, uint64_t *wild);
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate #endif	/* __STDC__ */
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate /*
105*7c478bd9Sstevel@tonic-gate  * This routine pushes the given character back onto the input stream.
106*7c478bd9Sstevel@tonic-gate  */
107*7c478bd9Sstevel@tonic-gate static void
108*7c478bd9Sstevel@tonic-gate pushchar(c)
109*7c478bd9Sstevel@tonic-gate 	int	c;
110*7c478bd9Sstevel@tonic-gate {
111*7c478bd9Sstevel@tonic-gate 	(void) ungetc(c, stdin);
112*7c478bd9Sstevel@tonic-gate }
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate /*
115*7c478bd9Sstevel@tonic-gate  * This routine checks the input stream for an eof condition.
116*7c478bd9Sstevel@tonic-gate  */
117*7c478bd9Sstevel@tonic-gate static int
118*7c478bd9Sstevel@tonic-gate checkeof()
119*7c478bd9Sstevel@tonic-gate {
120*7c478bd9Sstevel@tonic-gate 	return (feof(stdin));
121*7c478bd9Sstevel@tonic-gate }
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate /*
124*7c478bd9Sstevel@tonic-gate  * This routine gets the next token off the input stream.  A token is
125*7c478bd9Sstevel@tonic-gate  * basically any consecutive non-white characters.
126*7c478bd9Sstevel@tonic-gate  */
127*7c478bd9Sstevel@tonic-gate char *
128*7c478bd9Sstevel@tonic-gate gettoken(inbuf)
129*7c478bd9Sstevel@tonic-gate 	char	*inbuf;
130*7c478bd9Sstevel@tonic-gate {
131*7c478bd9Sstevel@tonic-gate 	char	*ptr = inbuf;
132*7c478bd9Sstevel@tonic-gate 	int	c, quoted = 0;
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate retoke:
135*7c478bd9Sstevel@tonic-gate 	/*
136*7c478bd9Sstevel@tonic-gate 	 * Remove any leading white-space.
137*7c478bd9Sstevel@tonic-gate 	 */
138*7c478bd9Sstevel@tonic-gate 	while ((isspace(c = getchar())) && (c != '\n'))
139*7c478bd9Sstevel@tonic-gate 		;
140*7c478bd9Sstevel@tonic-gate 	/*
141*7c478bd9Sstevel@tonic-gate 	 * If we are at the beginning of a line and hit the comment character,
142*7c478bd9Sstevel@tonic-gate 	 * flush the line and start again.
143*7c478bd9Sstevel@tonic-gate 	 */
144*7c478bd9Sstevel@tonic-gate 	if (!token_present && c == COMMENT_CHAR) {
145*7c478bd9Sstevel@tonic-gate 		token_present = 1;
146*7c478bd9Sstevel@tonic-gate 		flushline();
147*7c478bd9Sstevel@tonic-gate 		goto retoke;
148*7c478bd9Sstevel@tonic-gate 	}
149*7c478bd9Sstevel@tonic-gate 	/*
150*7c478bd9Sstevel@tonic-gate 	 * Loop on each character until we hit unquoted white-space.
151*7c478bd9Sstevel@tonic-gate 	 */
152*7c478bd9Sstevel@tonic-gate 	while (!isspace(c) || quoted && (c != '\n')) {
153*7c478bd9Sstevel@tonic-gate 		/*
154*7c478bd9Sstevel@tonic-gate 		 * If we hit eof, get out.
155*7c478bd9Sstevel@tonic-gate 		 */
156*7c478bd9Sstevel@tonic-gate 		if (checkeof())
157*7c478bd9Sstevel@tonic-gate 			return (NULL);
158*7c478bd9Sstevel@tonic-gate 		/*
159*7c478bd9Sstevel@tonic-gate 		 * If we hit a double quote, change the state of quotedness.
160*7c478bd9Sstevel@tonic-gate 		 */
161*7c478bd9Sstevel@tonic-gate 		if (c == '"')
162*7c478bd9Sstevel@tonic-gate 			quoted = !quoted;
163*7c478bd9Sstevel@tonic-gate 		/*
164*7c478bd9Sstevel@tonic-gate 		 * If there's room in the buffer, add the character to the end.
165*7c478bd9Sstevel@tonic-gate 		 */
166*7c478bd9Sstevel@tonic-gate 		else if (ptr - inbuf < TOKEN_SIZE)
167*7c478bd9Sstevel@tonic-gate 			*ptr++ = (char)c;
168*7c478bd9Sstevel@tonic-gate 		/*
169*7c478bd9Sstevel@tonic-gate 		 * Get the next character.
170*7c478bd9Sstevel@tonic-gate 		 */
171*7c478bd9Sstevel@tonic-gate 		c = getchar();
172*7c478bd9Sstevel@tonic-gate 	}
173*7c478bd9Sstevel@tonic-gate 	/*
174*7c478bd9Sstevel@tonic-gate 	 * Null terminate the token.
175*7c478bd9Sstevel@tonic-gate 	 */
176*7c478bd9Sstevel@tonic-gate 	*ptr = '\0';
177*7c478bd9Sstevel@tonic-gate 	/*
178*7c478bd9Sstevel@tonic-gate 	 * Peel off white-space still in the pipe.
179*7c478bd9Sstevel@tonic-gate 	 */
180*7c478bd9Sstevel@tonic-gate 	while (isspace(c) && (c != '\n'))
181*7c478bd9Sstevel@tonic-gate 		c = getchar();
182*7c478bd9Sstevel@tonic-gate 	/*
183*7c478bd9Sstevel@tonic-gate 	 * If we hit another token, push it back and set state.
184*7c478bd9Sstevel@tonic-gate 	 */
185*7c478bd9Sstevel@tonic-gate 	if (c != '\n') {
186*7c478bd9Sstevel@tonic-gate 		pushchar(c);
187*7c478bd9Sstevel@tonic-gate 		token_present = 1;
188*7c478bd9Sstevel@tonic-gate 	} else
189*7c478bd9Sstevel@tonic-gate 		token_present = 0;
190*7c478bd9Sstevel@tonic-gate 	/*
191*7c478bd9Sstevel@tonic-gate 	 * Return the token.
192*7c478bd9Sstevel@tonic-gate 	 */
193*7c478bd9Sstevel@tonic-gate 	return (inbuf);
194*7c478bd9Sstevel@tonic-gate }
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate /*
197*7c478bd9Sstevel@tonic-gate  * This routine removes the leading and trailing spaces from a token.
198*7c478bd9Sstevel@tonic-gate  */
199*7c478bd9Sstevel@tonic-gate void
200*7c478bd9Sstevel@tonic-gate clean_token(cleantoken, token)
201*7c478bd9Sstevel@tonic-gate 	char	*cleantoken, *token;
202*7c478bd9Sstevel@tonic-gate {
203*7c478bd9Sstevel@tonic-gate 	char	*ptr;
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 	/*
206*7c478bd9Sstevel@tonic-gate 	 * Strip off leading white-space.
207*7c478bd9Sstevel@tonic-gate 	 */
208*7c478bd9Sstevel@tonic-gate 	for (ptr = token; isspace(*ptr); ptr++)
209*7c478bd9Sstevel@tonic-gate 		;
210*7c478bd9Sstevel@tonic-gate 	/*
211*7c478bd9Sstevel@tonic-gate 	 * Copy it into the clean buffer.
212*7c478bd9Sstevel@tonic-gate 	 */
213*7c478bd9Sstevel@tonic-gate 	(void) strcpy(cleantoken, ptr);
214*7c478bd9Sstevel@tonic-gate 	/*
215*7c478bd9Sstevel@tonic-gate 	 * Strip off trailing white-space.
216*7c478bd9Sstevel@tonic-gate 	 */
217*7c478bd9Sstevel@tonic-gate 	for (ptr = cleantoken + strlen(cleantoken) - 1;
218*7c478bd9Sstevel@tonic-gate 		isspace(*ptr) && (ptr >= cleantoken); ptr--) {
219*7c478bd9Sstevel@tonic-gate 		*ptr = '\0';
220*7c478bd9Sstevel@tonic-gate 	}
221*7c478bd9Sstevel@tonic-gate }
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate /*
224*7c478bd9Sstevel@tonic-gate  * This routine checks if a token is already present on the input line
225*7c478bd9Sstevel@tonic-gate  */
226*7c478bd9Sstevel@tonic-gate int
227*7c478bd9Sstevel@tonic-gate istokenpresent()
228*7c478bd9Sstevel@tonic-gate {
229*7c478bd9Sstevel@tonic-gate 	return (token_present);
230*7c478bd9Sstevel@tonic-gate }
231*7c478bd9Sstevel@tonic-gate 
232*7c478bd9Sstevel@tonic-gate /*
233*7c478bd9Sstevel@tonic-gate  * This routine flushes the rest of an input line if there is known
234*7c478bd9Sstevel@tonic-gate  * to be data in it.  The flush has to be qualified because the newline
235*7c478bd9Sstevel@tonic-gate  * may have already been swallowed by the last gettoken.
236*7c478bd9Sstevel@tonic-gate  */
237*7c478bd9Sstevel@tonic-gate static void
238*7c478bd9Sstevel@tonic-gate flushline()
239*7c478bd9Sstevel@tonic-gate {
240*7c478bd9Sstevel@tonic-gate 	if (token_present) {
241*7c478bd9Sstevel@tonic-gate 		/*
242*7c478bd9Sstevel@tonic-gate 		 * Flush the pipe to eol or eof.
243*7c478bd9Sstevel@tonic-gate 		 */
244*7c478bd9Sstevel@tonic-gate 		while ((getchar() != '\n') && !checkeof())
245*7c478bd9Sstevel@tonic-gate 			;
246*7c478bd9Sstevel@tonic-gate 		/*
247*7c478bd9Sstevel@tonic-gate 		 * Mark the pipe empty.
248*7c478bd9Sstevel@tonic-gate 		 */
249*7c478bd9Sstevel@tonic-gate 		token_present = 0;
250*7c478bd9Sstevel@tonic-gate 	}
251*7c478bd9Sstevel@tonic-gate }
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate /*
254*7c478bd9Sstevel@tonic-gate  * This routine returns the number of characters that are identical
255*7c478bd9Sstevel@tonic-gate  * between s1 and s2, stopping as soon as a mismatch is found.
256*7c478bd9Sstevel@tonic-gate  */
257*7c478bd9Sstevel@tonic-gate static int
258*7c478bd9Sstevel@tonic-gate strcnt(s1, s2)
259*7c478bd9Sstevel@tonic-gate 	char	*s1, *s2;
260*7c478bd9Sstevel@tonic-gate {
261*7c478bd9Sstevel@tonic-gate 	int	i = 0;
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	while ((*s1 != '\0') && (*s1++ == *s2++))
264*7c478bd9Sstevel@tonic-gate 		i++;
265*7c478bd9Sstevel@tonic-gate 	return (i);
266*7c478bd9Sstevel@tonic-gate }
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate /*
269*7c478bd9Sstevel@tonic-gate  * This routine converts the given token into an integer.  The token
270*7c478bd9Sstevel@tonic-gate  * must convert cleanly into an integer with no unknown characters.
271*7c478bd9Sstevel@tonic-gate  * If the token is the wildcard string, and the wildcard parameter
272*7c478bd9Sstevel@tonic-gate  * is present, the wildcard value will be returned.
273*7c478bd9Sstevel@tonic-gate  */
274*7c478bd9Sstevel@tonic-gate int
275*7c478bd9Sstevel@tonic-gate geti(str, iptr, wild)
276*7c478bd9Sstevel@tonic-gate 	char	*str;
277*7c478bd9Sstevel@tonic-gate 	int	*iptr, *wild;
278*7c478bd9Sstevel@tonic-gate {
279*7c478bd9Sstevel@tonic-gate 	char	*str2;
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate 	/*
282*7c478bd9Sstevel@tonic-gate 	 * If there's a wildcard value and the string is wild, return the
283*7c478bd9Sstevel@tonic-gate 	 * wildcard value.
284*7c478bd9Sstevel@tonic-gate 	 */
285*7c478bd9Sstevel@tonic-gate 	if (wild != NULL && strcmp(str, WILD_STRING) == 0)
286*7c478bd9Sstevel@tonic-gate 		*iptr = *wild;
287*7c478bd9Sstevel@tonic-gate 	else {
288*7c478bd9Sstevel@tonic-gate 		/*
289*7c478bd9Sstevel@tonic-gate 		 * Conver the string to an integer.
290*7c478bd9Sstevel@tonic-gate 		 */
291*7c478bd9Sstevel@tonic-gate 		*iptr = (int)strtol(str, &str2, 0);
292*7c478bd9Sstevel@tonic-gate 		/*
293*7c478bd9Sstevel@tonic-gate 		 * If any characters didn't convert, it's an error.
294*7c478bd9Sstevel@tonic-gate 		 */
295*7c478bd9Sstevel@tonic-gate 		if (*str2 != '\0') {
296*7c478bd9Sstevel@tonic-gate 			err_print("`%s' is not an integer.\n", str);
297*7c478bd9Sstevel@tonic-gate 			return (-1);
298*7c478bd9Sstevel@tonic-gate 		}
299*7c478bd9Sstevel@tonic-gate 	}
300*7c478bd9Sstevel@tonic-gate 	return (0);
301*7c478bd9Sstevel@tonic-gate }
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate /*
304*7c478bd9Sstevel@tonic-gate  * This routine converts the given token into a long long.  The token
305*7c478bd9Sstevel@tonic-gate  * must convert cleanly into a 64-bit integer with no unknown characters.
306*7c478bd9Sstevel@tonic-gate  * If the token is the wildcard string, and the wildcard parameter
307*7c478bd9Sstevel@tonic-gate  * is present, the wildcard value will be returned.
308*7c478bd9Sstevel@tonic-gate  */
309*7c478bd9Sstevel@tonic-gate static int
310*7c478bd9Sstevel@tonic-gate geti64(str, iptr, wild)
311*7c478bd9Sstevel@tonic-gate 	char		*str;
312*7c478bd9Sstevel@tonic-gate 	uint64_t	*iptr, *wild;
313*7c478bd9Sstevel@tonic-gate {
314*7c478bd9Sstevel@tonic-gate 	char	*str2;
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate 	/*
317*7c478bd9Sstevel@tonic-gate 	 * If there's a wildcard value and the string is wild, return the
318*7c478bd9Sstevel@tonic-gate 	 * wildcard value.
319*7c478bd9Sstevel@tonic-gate 	 */
320*7c478bd9Sstevel@tonic-gate 	if ((wild != NULL) && (strcmp(str, WILD_STRING)) == 0) {
321*7c478bd9Sstevel@tonic-gate 		*iptr = *wild;
322*7c478bd9Sstevel@tonic-gate 	} else {
323*7c478bd9Sstevel@tonic-gate 		/*
324*7c478bd9Sstevel@tonic-gate 		 * Conver the string to an integer.
325*7c478bd9Sstevel@tonic-gate 		 */
326*7c478bd9Sstevel@tonic-gate 		*iptr = (uint64_t)strtoll(str, &str2, 0);
327*7c478bd9Sstevel@tonic-gate 		/*
328*7c478bd9Sstevel@tonic-gate 		 * If any characters didn't convert, it's an error.
329*7c478bd9Sstevel@tonic-gate 		 */
330*7c478bd9Sstevel@tonic-gate 		if (*str2 != '\0') {
331*7c478bd9Sstevel@tonic-gate 			err_print("`%s' is not an integer.\n", str);
332*7c478bd9Sstevel@tonic-gate 			return (-1);
333*7c478bd9Sstevel@tonic-gate 		}
334*7c478bd9Sstevel@tonic-gate 	}
335*7c478bd9Sstevel@tonic-gate 	return (0);
336*7c478bd9Sstevel@tonic-gate }
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate /*
339*7c478bd9Sstevel@tonic-gate  * This routine converts the given string into a block number on the
340*7c478bd9Sstevel@tonic-gate  * current disk.  The format of a block number is either a self-based
341*7c478bd9Sstevel@tonic-gate  * number, or a series of self-based numbers separated by slashes.
342*7c478bd9Sstevel@tonic-gate  * Any number preceeding the first slash is considered a cylinder value.
343*7c478bd9Sstevel@tonic-gate  * Any number succeeding the first slash but preceeding the second is
344*7c478bd9Sstevel@tonic-gate  * considered a head value.  Any number succeeding the second slash is
345*7c478bd9Sstevel@tonic-gate  * considered a sector value.  Any of these numbers can be wildcarded
346*7c478bd9Sstevel@tonic-gate  * to the highest possible legal value.
347*7c478bd9Sstevel@tonic-gate  */
348*7c478bd9Sstevel@tonic-gate static int
349*7c478bd9Sstevel@tonic-gate getbn(str, iptr)
350*7c478bd9Sstevel@tonic-gate 	char	*str;
351*7c478bd9Sstevel@tonic-gate 	daddr_t	*iptr;
352*7c478bd9Sstevel@tonic-gate {
353*7c478bd9Sstevel@tonic-gate 	char	*cptr, *hptr, *sptr;
354*7c478bd9Sstevel@tonic-gate 	int	cyl, head, sect, wild;
355*7c478bd9Sstevel@tonic-gate 	TOKEN	buf;
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate 	/*
358*7c478bd9Sstevel@tonic-gate 	 * Set cylinder pointer to beginning of string.
359*7c478bd9Sstevel@tonic-gate 	 */
360*7c478bd9Sstevel@tonic-gate 	cptr = str;
361*7c478bd9Sstevel@tonic-gate 	/*
362*7c478bd9Sstevel@tonic-gate 	 * Look for the first slash.
363*7c478bd9Sstevel@tonic-gate 	 */
364*7c478bd9Sstevel@tonic-gate 	while ((*str != '\0') && (*str != '/'))
365*7c478bd9Sstevel@tonic-gate 		str++;
366*7c478bd9Sstevel@tonic-gate 	/*
367*7c478bd9Sstevel@tonic-gate 	 * If there wasn't one, convert string to an integer and return it.
368*7c478bd9Sstevel@tonic-gate 	 */
369*7c478bd9Sstevel@tonic-gate 	if (*str == '\0') {
370*7c478bd9Sstevel@tonic-gate 		wild = physsects() - 1;
371*7c478bd9Sstevel@tonic-gate 		if (geti(cptr, (int *)iptr, &wild))
372*7c478bd9Sstevel@tonic-gate 			return (-1);
373*7c478bd9Sstevel@tonic-gate 		return (0);
374*7c478bd9Sstevel@tonic-gate 	}
375*7c478bd9Sstevel@tonic-gate 	/*
376*7c478bd9Sstevel@tonic-gate 	 * Null out the slash and set head pointer just beyond it.
377*7c478bd9Sstevel@tonic-gate 	 */
378*7c478bd9Sstevel@tonic-gate 	*str++ = '\0';
379*7c478bd9Sstevel@tonic-gate 	hptr = str;
380*7c478bd9Sstevel@tonic-gate 	/*
381*7c478bd9Sstevel@tonic-gate 	 * Look for the second slash.
382*7c478bd9Sstevel@tonic-gate 	 */
383*7c478bd9Sstevel@tonic-gate 	while ((*str != '\0') && (*str != '/'))
384*7c478bd9Sstevel@tonic-gate 		str++;
385*7c478bd9Sstevel@tonic-gate 	/*
386*7c478bd9Sstevel@tonic-gate 	 * If there wasn't one, sector pointer points to a .
387*7c478bd9Sstevel@tonic-gate 	 */
388*7c478bd9Sstevel@tonic-gate 	if (*str == '\0')
389*7c478bd9Sstevel@tonic-gate 		sptr = str;
390*7c478bd9Sstevel@tonic-gate 	/*
391*7c478bd9Sstevel@tonic-gate 	 * If there was, null it out and set sector point just beyond it.
392*7c478bd9Sstevel@tonic-gate 	 */
393*7c478bd9Sstevel@tonic-gate 	else {
394*7c478bd9Sstevel@tonic-gate 		*str++ = '\0';
395*7c478bd9Sstevel@tonic-gate 		sptr = str;
396*7c478bd9Sstevel@tonic-gate 	}
397*7c478bd9Sstevel@tonic-gate 	/*
398*7c478bd9Sstevel@tonic-gate 	 * Convert the cylinder part to an integer and store it.
399*7c478bd9Sstevel@tonic-gate 	 */
400*7c478bd9Sstevel@tonic-gate 	clean_token(buf, cptr);
401*7c478bd9Sstevel@tonic-gate 	wild = ncyl + acyl - 1;
402*7c478bd9Sstevel@tonic-gate 	if (geti(buf, &cyl, &wild))
403*7c478bd9Sstevel@tonic-gate 		return (-1);
404*7c478bd9Sstevel@tonic-gate 	if ((cyl < 0) || (cyl >= (ncyl + acyl))) {
405*7c478bd9Sstevel@tonic-gate 		err_print("`%d' is out of range.\n", cyl);
406*7c478bd9Sstevel@tonic-gate 		return (-1);
407*7c478bd9Sstevel@tonic-gate 	}
408*7c478bd9Sstevel@tonic-gate 	/*
409*7c478bd9Sstevel@tonic-gate 	 * Convert the head part to an integer and store it.
410*7c478bd9Sstevel@tonic-gate 	 */
411*7c478bd9Sstevel@tonic-gate 	clean_token(buf, hptr);
412*7c478bd9Sstevel@tonic-gate 	wild = nhead - 1;
413*7c478bd9Sstevel@tonic-gate 	if (geti(buf, &head, &wild))
414*7c478bd9Sstevel@tonic-gate 		return (-1);
415*7c478bd9Sstevel@tonic-gate 	if ((head < 0) || (head >= nhead)) {
416*7c478bd9Sstevel@tonic-gate 		err_print("`%d' is out of range.\n", head);
417*7c478bd9Sstevel@tonic-gate 		return (-1);
418*7c478bd9Sstevel@tonic-gate 	}
419*7c478bd9Sstevel@tonic-gate 	/*
420*7c478bd9Sstevel@tonic-gate 	 * Convert the sector part to an integer and store it.
421*7c478bd9Sstevel@tonic-gate 	 */
422*7c478bd9Sstevel@tonic-gate 	clean_token(buf, sptr);
423*7c478bd9Sstevel@tonic-gate 	wild = sectors(head) - 1;
424*7c478bd9Sstevel@tonic-gate 	if (geti(buf, &sect, &wild))
425*7c478bd9Sstevel@tonic-gate 		return (-1);
426*7c478bd9Sstevel@tonic-gate 	if ((sect < 0) || (sect >= sectors(head))) {
427*7c478bd9Sstevel@tonic-gate 		err_print("`%d' is out of range.\n", sect);
428*7c478bd9Sstevel@tonic-gate 		return (-1);
429*7c478bd9Sstevel@tonic-gate 	}
430*7c478bd9Sstevel@tonic-gate 	/*
431*7c478bd9Sstevel@tonic-gate 	 * Combine the pieces into a block number and return it.
432*7c478bd9Sstevel@tonic-gate 	 */
433*7c478bd9Sstevel@tonic-gate 	*iptr = chs2bn(cyl, head, sect);
434*7c478bd9Sstevel@tonic-gate 	return (0);
435*7c478bd9Sstevel@tonic-gate }
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate /*
438*7c478bd9Sstevel@tonic-gate  * This routine is the basis for all input into the program.  It
439*7c478bd9Sstevel@tonic-gate  * understands the semantics of a set of input types, and provides
440*7c478bd9Sstevel@tonic-gate  * consistent error messages for all input.  It allows for default
441*7c478bd9Sstevel@tonic-gate  * values and prompt strings.
442*7c478bd9Sstevel@tonic-gate  */
443*7c478bd9Sstevel@tonic-gate uint64_t
444*7c478bd9Sstevel@tonic-gate input(type, promptstr, delim, param, deflt, cmdflag)
445*7c478bd9Sstevel@tonic-gate 	int		type;
446*7c478bd9Sstevel@tonic-gate 	char		*promptstr;
447*7c478bd9Sstevel@tonic-gate 	int		delim;
448*7c478bd9Sstevel@tonic-gate 	u_ioparam_t	*param;
449*7c478bd9Sstevel@tonic-gate 	int		*deflt;
450*7c478bd9Sstevel@tonic-gate 	int		cmdflag;
451*7c478bd9Sstevel@tonic-gate {
452*7c478bd9Sstevel@tonic-gate 	int		interactive, help, i, length, index, tied;
453*7c478bd9Sstevel@tonic-gate 	daddr_t		bn;
454*7c478bd9Sstevel@tonic-gate 	diskaddr_t	bn64;
455*7c478bd9Sstevel@tonic-gate 	char		**str, **strings;
456*7c478bd9Sstevel@tonic-gate 	TOKEN		token, cleantoken;
457*7c478bd9Sstevel@tonic-gate 	TOKEN		token2, cleantoken2;
458*7c478bd9Sstevel@tonic-gate 	struct		bounds *bounds;
459*7c478bd9Sstevel@tonic-gate 	char		*s;
460*7c478bd9Sstevel@tonic-gate 	int		value;
461*7c478bd9Sstevel@tonic-gate 	int		cyls, cylno;
462*7c478bd9Sstevel@tonic-gate 	uint64_t	blokno;
463*7c478bd9Sstevel@tonic-gate 	float		nmegs;
464*7c478bd9Sstevel@tonic-gate 	float		ngigs;
465*7c478bd9Sstevel@tonic-gate 	char		shell_argv[MAXPATHLEN];
466*7c478bd9Sstevel@tonic-gate 	part_deflt_t	*part_deflt;
467*7c478bd9Sstevel@tonic-gate 	efi_deflt_t	*efi_deflt;
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 	/*
470*7c478bd9Sstevel@tonic-gate 	 * Optional integer input has been added as a hack.
471*7c478bd9Sstevel@tonic-gate 	 * Function result is 1 if user typed anything.
472*7c478bd9Sstevel@tonic-gate 	 * Whatever they typed is returned in *deflt.
473*7c478bd9Sstevel@tonic-gate 	 * This permits us to distinguish between "no value",
474*7c478bd9Sstevel@tonic-gate 	 * and actually entering in some value, for instance.
475*7c478bd9Sstevel@tonic-gate 	 */
476*7c478bd9Sstevel@tonic-gate 	if (type == FIO_OPINT) {
477*7c478bd9Sstevel@tonic-gate 		assert(deflt != NULL);
478*7c478bd9Sstevel@tonic-gate 	}
479*7c478bd9Sstevel@tonic-gate reprompt:
480*7c478bd9Sstevel@tonic-gate 	help = interactive = 0;
481*7c478bd9Sstevel@tonic-gate 	/*
482*7c478bd9Sstevel@tonic-gate 	 * If we are inputting a command, flush any current input in the pipe.
483*7c478bd9Sstevel@tonic-gate 	 */
484*7c478bd9Sstevel@tonic-gate 	if (cmdflag == CMD_INPUT)
485*7c478bd9Sstevel@tonic-gate 		flushline();
486*7c478bd9Sstevel@tonic-gate 	/*
487*7c478bd9Sstevel@tonic-gate 	 * Note whether the token is already present.
488*7c478bd9Sstevel@tonic-gate 	 */
489*7c478bd9Sstevel@tonic-gate 	if (!token_present)
490*7c478bd9Sstevel@tonic-gate 		interactive = 1;
491*7c478bd9Sstevel@tonic-gate 	/*
492*7c478bd9Sstevel@tonic-gate 	 * Print the prompt.
493*7c478bd9Sstevel@tonic-gate 	 */
494*7c478bd9Sstevel@tonic-gate 	fmt_print(promptstr);
495*7c478bd9Sstevel@tonic-gate 	/*
496*7c478bd9Sstevel@tonic-gate 	 * If there is a default value, print it in a format appropriate
497*7c478bd9Sstevel@tonic-gate 	 * for the input type.
498*7c478bd9Sstevel@tonic-gate 	 */
499*7c478bd9Sstevel@tonic-gate 	if (deflt != NULL) {
500*7c478bd9Sstevel@tonic-gate 		switch (type) {
501*7c478bd9Sstevel@tonic-gate 		case FIO_BN:
502*7c478bd9Sstevel@tonic-gate 			fmt_print("[%d, ", *deflt);
503*7c478bd9Sstevel@tonic-gate 			pr_dblock(fmt_print, (daddr_t)*deflt);
504*7c478bd9Sstevel@tonic-gate 			fmt_print("]");
505*7c478bd9Sstevel@tonic-gate 			break;
506*7c478bd9Sstevel@tonic-gate 		case FIO_INT:
507*7c478bd9Sstevel@tonic-gate 			fmt_print("[%d]", *deflt);
508*7c478bd9Sstevel@tonic-gate 			break;
509*7c478bd9Sstevel@tonic-gate 		case FIO_INT64:
510*7c478bd9Sstevel@tonic-gate #if defined(lint)
511*7c478bd9Sstevel@tonic-gate 			/* caller is longlong aligned specifying FIO_INT64 */
512*7c478bd9Sstevel@tonic-gate 			efi_deflt = NULL;
513*7c478bd9Sstevel@tonic-gate #else
514*7c478bd9Sstevel@tonic-gate 			efi_deflt = (efi_deflt_t *)deflt;
515*7c478bd9Sstevel@tonic-gate #endif
516*7c478bd9Sstevel@tonic-gate 			fmt_print("[%llu]", efi_deflt->start_sector);
517*7c478bd9Sstevel@tonic-gate 			break;
518*7c478bd9Sstevel@tonic-gate 		case FIO_CSTR:
519*7c478bd9Sstevel@tonic-gate 		case FIO_MSTR:
520*7c478bd9Sstevel@tonic-gate 			strings = (char **)param->io_charlist;
521*7c478bd9Sstevel@tonic-gate 			for (i = 0, str = strings; i < *deflt; i++, str++)
522*7c478bd9Sstevel@tonic-gate 				;
523*7c478bd9Sstevel@tonic-gate 			fmt_print("[%s]", *str);
524*7c478bd9Sstevel@tonic-gate 			break;
525*7c478bd9Sstevel@tonic-gate 		case FIO_OSTR:
526*7c478bd9Sstevel@tonic-gate 			fmt_print("[\"%s\"]", (char *)deflt);
527*7c478bd9Sstevel@tonic-gate 			break;
528*7c478bd9Sstevel@tonic-gate 		case FIO_SLIST:
529*7c478bd9Sstevel@tonic-gate 			/*
530*7c478bd9Sstevel@tonic-gate 			 * Search for a string matching the default
531*7c478bd9Sstevel@tonic-gate 			 * value.  If found, use it.  Otherwise
532*7c478bd9Sstevel@tonic-gate 			 * assume the default value is actually
533*7c478bd9Sstevel@tonic-gate 			 * an illegal choice, and default to
534*7c478bd9Sstevel@tonic-gate 			 * the first item in the list.
535*7c478bd9Sstevel@tonic-gate 			 */
536*7c478bd9Sstevel@tonic-gate 			s = find_string(param->io_slist, *deflt);
537*7c478bd9Sstevel@tonic-gate 			if (s == (char *)NULL) {
538*7c478bd9Sstevel@tonic-gate 				s = (param->io_slist)->str;
539*7c478bd9Sstevel@tonic-gate 			}
540*7c478bd9Sstevel@tonic-gate 			fmt_print("[%s]", s);
541*7c478bd9Sstevel@tonic-gate 			break;
542*7c478bd9Sstevel@tonic-gate 		case FIO_CYL:
543*7c478bd9Sstevel@tonic-gate 			/*
544*7c478bd9Sstevel@tonic-gate 			 * Old-style partition size input, used to
545*7c478bd9Sstevel@tonic-gate 			 * modify complete partition tables
546*7c478bd9Sstevel@tonic-gate 			 */
547*7c478bd9Sstevel@tonic-gate 			fmt_print("[%db, %dc, %1.2fmb, %1.2fgb]", *deflt,
548*7c478bd9Sstevel@tonic-gate 			    bn2c(*deflt), bn2mb(*deflt), bn2gb(*deflt));
549*7c478bd9Sstevel@tonic-gate 			break;
550*7c478bd9Sstevel@tonic-gate 		case FIO_ECYL:
551*7c478bd9Sstevel@tonic-gate 			/*
552*7c478bd9Sstevel@tonic-gate 			 * set up pointer to partition defaults
553*7c478bd9Sstevel@tonic-gate 			 * structure
554*7c478bd9Sstevel@tonic-gate 			 */
555*7c478bd9Sstevel@tonic-gate 			part_deflt = (part_deflt_t *)deflt;
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 			/*
558*7c478bd9Sstevel@tonic-gate 			 * Build print format specifier.  We use the
559*7c478bd9Sstevel@tonic-gate 			 * starting cylinder number which was entered
560*7c478bd9Sstevel@tonic-gate 			 * before this call to input(), in case the
561*7c478bd9Sstevel@tonic-gate 			 * user has changed it from the value in the
562*7c478bd9Sstevel@tonic-gate 			 * cur_parts->pinfo_map[].dkl_cylno
563*7c478bd9Sstevel@tonic-gate 			 * field for the current parition
564*7c478bd9Sstevel@tonic-gate 			 */
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 			/*
567*7c478bd9Sstevel@tonic-gate 			 * Determine the proper default end cylinder:
568*7c478bd9Sstevel@tonic-gate 			 * Start Cyl	Default Size	End Cylinder
569*7c478bd9Sstevel@tonic-gate 			 *	0		0	0
570*7c478bd9Sstevel@tonic-gate 			 *	>0		0	Start Cyl
571*7c478bd9Sstevel@tonic-gate 			 *	0		>0	Default Size
572*7c478bd9Sstevel@tonic-gate 			 *				(Cyls) - 1
573*7c478bd9Sstevel@tonic-gate 			 *	>0		>0	(Start +
574*7c478bd9Sstevel@tonic-gate 			 *				Default Size
575*7c478bd9Sstevel@tonic-gate 			 *				(Cyls)) -1
576*7c478bd9Sstevel@tonic-gate 			 */
577*7c478bd9Sstevel@tonic-gate 
578*7c478bd9Sstevel@tonic-gate 			if (part_deflt->deflt_size == 0) {
579*7c478bd9Sstevel@tonic-gate 				cylno = part_deflt->start_cyl;
580*7c478bd9Sstevel@tonic-gate 			} else if (part_deflt->start_cyl == 0) {
581*7c478bd9Sstevel@tonic-gate 				cylno = bn2c(part_deflt->deflt_size)
582*7c478bd9Sstevel@tonic-gate 				    - 1;
583*7c478bd9Sstevel@tonic-gate 			} else {
584*7c478bd9Sstevel@tonic-gate 				cylno = (bn2c(part_deflt->deflt_size) +
585*7c478bd9Sstevel@tonic-gate 					    part_deflt->start_cyl) - 1;
586*7c478bd9Sstevel@tonic-gate 			}
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate 			fmt_print("[%db, %dc, %de, %1.2fmb, %1.2fgb]",
589*7c478bd9Sstevel@tonic-gate 			    part_deflt->deflt_size,
590*7c478bd9Sstevel@tonic-gate 			    bn2c(part_deflt->deflt_size),
591*7c478bd9Sstevel@tonic-gate 			    cylno,
592*7c478bd9Sstevel@tonic-gate 			    bn2mb(part_deflt->deflt_size),
593*7c478bd9Sstevel@tonic-gate 			    bn2gb(part_deflt->deflt_size));
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 			break;
596*7c478bd9Sstevel@tonic-gate 		case FIO_EFI:
597*7c478bd9Sstevel@tonic-gate #if defined(lint)
598*7c478bd9Sstevel@tonic-gate 			/* caller is longlong aligned when specifying FIO_EFI */
599*7c478bd9Sstevel@tonic-gate 			efi_deflt = NULL;
600*7c478bd9Sstevel@tonic-gate #else
601*7c478bd9Sstevel@tonic-gate 			efi_deflt = (efi_deflt_t *)deflt;
602*7c478bd9Sstevel@tonic-gate #endif
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate 			fmt_print("[%llub, %llue, %llumb, %llugb, %llutb]",
605*7c478bd9Sstevel@tonic-gate 			    efi_deflt->end_sector,
606*7c478bd9Sstevel@tonic-gate 			    efi_deflt->start_sector + efi_deflt->end_sector - 1,
607*7c478bd9Sstevel@tonic-gate 			    (efi_deflt->end_sector * DEV_BSIZE) /
608*7c478bd9Sstevel@tonic-gate 				(1024 * 1024),
609*7c478bd9Sstevel@tonic-gate 			    (efi_deflt->end_sector * DEV_BSIZE) /
610*7c478bd9Sstevel@tonic-gate 				(1024 * 1024 * 1024),
611*7c478bd9Sstevel@tonic-gate 			    (efi_deflt->end_sector * DEV_BSIZE) /
612*7c478bd9Sstevel@tonic-gate 				((uint64_t)1024 * 1024 * 1024 * 1024));
613*7c478bd9Sstevel@tonic-gate 			break;
614*7c478bd9Sstevel@tonic-gate 		case FIO_OPINT:
615*7c478bd9Sstevel@tonic-gate 			/* no default value for optional input type */
616*7c478bd9Sstevel@tonic-gate 			fmt_print("[default]");
617*7c478bd9Sstevel@tonic-gate 			break;
618*7c478bd9Sstevel@tonic-gate 		default:
619*7c478bd9Sstevel@tonic-gate 			err_print("Error: unknown input type.\n");
620*7c478bd9Sstevel@tonic-gate 			fullabort();
621*7c478bd9Sstevel@tonic-gate 		}
622*7c478bd9Sstevel@tonic-gate 	}
623*7c478bd9Sstevel@tonic-gate 	/*
624*7c478bd9Sstevel@tonic-gate 	 * Print the delimiter character.
625*7c478bd9Sstevel@tonic-gate 	 */
626*7c478bd9Sstevel@tonic-gate 	fmt_print("%c ", delim);
627*7c478bd9Sstevel@tonic-gate 	/*
628*7c478bd9Sstevel@tonic-gate 	 * Get the token.  If we hit eof, exit the program gracefully.
629*7c478bd9Sstevel@tonic-gate 	 */
630*7c478bd9Sstevel@tonic-gate 	if (gettoken(token) == NULL)
631*7c478bd9Sstevel@tonic-gate 		fullabort();
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate 	/*
634*7c478bd9Sstevel@tonic-gate 	 * check if the user has issued (!) , escape to shell
635*7c478bd9Sstevel@tonic-gate 	 */
636*7c478bd9Sstevel@tonic-gate 	if ((cmdflag == CMD_INPUT) && (token[0] == '!')) {
637*7c478bd9Sstevel@tonic-gate 
638*7c478bd9Sstevel@tonic-gate 	    /* get the list of arguments to shell command */
639*7c478bd9Sstevel@tonic-gate 		(void) memset(shell_argv, 0, MAXPATHLEN);
640*7c478bd9Sstevel@tonic-gate 		if (strlen(token) > 1) {
641*7c478bd9Sstevel@tonic-gate 			if (strlcpy(shell_argv, &token[1], MAXPATHLEN) >=
642*7c478bd9Sstevel@tonic-gate 				MAXPATHLEN) {
643*7c478bd9Sstevel@tonic-gate 				err_print("Error: token length exceeds "
644*7c478bd9Sstevel@tonic-gate 					"MAXPATHLEN\n");
645*7c478bd9Sstevel@tonic-gate 				fullabort();
646*7c478bd9Sstevel@tonic-gate 			}
647*7c478bd9Sstevel@tonic-gate 		}
648*7c478bd9Sstevel@tonic-gate 
649*7c478bd9Sstevel@tonic-gate 		/*
650*7c478bd9Sstevel@tonic-gate 		 * collect all tokens till the end of line as arguments
651*7c478bd9Sstevel@tonic-gate 		 */
652*7c478bd9Sstevel@tonic-gate 		while (token_present && (gettoken(token) != NULL)) {
653*7c478bd9Sstevel@tonic-gate 			(void) strcat(shell_argv, " ");
654*7c478bd9Sstevel@tonic-gate 			(void) strcat(shell_argv, token);
655*7c478bd9Sstevel@tonic-gate 		}
656*7c478bd9Sstevel@tonic-gate 
657*7c478bd9Sstevel@tonic-gate 		/* execute the shell command */
658*7c478bd9Sstevel@tonic-gate 		(void) execute_shell(shell_argv);
659*7c478bd9Sstevel@tonic-gate 		redisplay_menu_list((char **)param->io_charlist);
660*7c478bd9Sstevel@tonic-gate 		if (interactive) {
661*7c478bd9Sstevel@tonic-gate 			goto reprompt;
662*7c478bd9Sstevel@tonic-gate 		}
663*7c478bd9Sstevel@tonic-gate 	}
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 	/*
666*7c478bd9Sstevel@tonic-gate 	 * Certain commands accept up to two tokens
667*7c478bd9Sstevel@tonic-gate 	 * Unfortunately, this is kind of a hack.
668*7c478bd9Sstevel@tonic-gate 	 */
669*7c478bd9Sstevel@tonic-gate 	token2[0] = 0;
670*7c478bd9Sstevel@tonic-gate 	cleantoken2[0] = 0;
671*7c478bd9Sstevel@tonic-gate 	if (type == FIO_CYL || type == FIO_ECYL) {
672*7c478bd9Sstevel@tonic-gate 		if (token_present) {
673*7c478bd9Sstevel@tonic-gate 			if (gettoken(token2) == NULL)
674*7c478bd9Sstevel@tonic-gate 				fullabort();
675*7c478bd9Sstevel@tonic-gate 			clean_token(cleantoken2, token2);
676*7c478bd9Sstevel@tonic-gate 		}
677*7c478bd9Sstevel@tonic-gate 	}
678*7c478bd9Sstevel@tonic-gate 	/*
679*7c478bd9Sstevel@tonic-gate 	 * Echo the token back to the user if it was in the pipe or we
680*7c478bd9Sstevel@tonic-gate 	 * are running out of a command file.
681*7c478bd9Sstevel@tonic-gate 	 */
682*7c478bd9Sstevel@tonic-gate 	if (!interactive || option_f) {
683*7c478bd9Sstevel@tonic-gate 		if (token2[0] == 0) {
684*7c478bd9Sstevel@tonic-gate 			fmt_print("%s\n", token);
685*7c478bd9Sstevel@tonic-gate 		} else {
686*7c478bd9Sstevel@tonic-gate 			fmt_print("%s %s\n", token, token2);
687*7c478bd9Sstevel@tonic-gate 		}
688*7c478bd9Sstevel@tonic-gate 	}
689*7c478bd9Sstevel@tonic-gate 	/*
690*7c478bd9Sstevel@tonic-gate 	 * If we are logging, echo the token to the log file.  The else
691*7c478bd9Sstevel@tonic-gate 	 * is necessary here because the above printf will also put the
692*7c478bd9Sstevel@tonic-gate 	 * token in the log file.
693*7c478bd9Sstevel@tonic-gate 	 */
694*7c478bd9Sstevel@tonic-gate 	else if (log_file) {
695*7c478bd9Sstevel@tonic-gate 		log_print("%s %s\n", token, token2);
696*7c478bd9Sstevel@tonic-gate 	}
697*7c478bd9Sstevel@tonic-gate 	/*
698*7c478bd9Sstevel@tonic-gate 	 * If the token was not in the pipe and it wasn't a command, flush
699*7c478bd9Sstevel@tonic-gate 	 * the rest of the line to keep things in sync.
700*7c478bd9Sstevel@tonic-gate 	 */
701*7c478bd9Sstevel@tonic-gate 	if (interactive && cmdflag != CMD_INPUT)
702*7c478bd9Sstevel@tonic-gate 		flushline();
703*7c478bd9Sstevel@tonic-gate 	/*
704*7c478bd9Sstevel@tonic-gate 	 * Scrub off the white-space.
705*7c478bd9Sstevel@tonic-gate 	 */
706*7c478bd9Sstevel@tonic-gate 	clean_token(cleantoken, token);
707*7c478bd9Sstevel@tonic-gate 	/*
708*7c478bd9Sstevel@tonic-gate 	 * If the input was a blank line and we weren't prompting
709*7c478bd9Sstevel@tonic-gate 	 * specifically for a blank line...
710*7c478bd9Sstevel@tonic-gate 	 */
711*7c478bd9Sstevel@tonic-gate 	if ((strcmp(cleantoken, "") == 0) && (type != FIO_BLNK)) {
712*7c478bd9Sstevel@tonic-gate 		/*
713*7c478bd9Sstevel@tonic-gate 		 * If there's a default, return it.
714*7c478bd9Sstevel@tonic-gate 		 */
715*7c478bd9Sstevel@tonic-gate 		if (deflt != NULL) {
716*7c478bd9Sstevel@tonic-gate 			if (type == FIO_OSTR) {
717*7c478bd9Sstevel@tonic-gate 				/*
718*7c478bd9Sstevel@tonic-gate 				 * Duplicate and return the default string
719*7c478bd9Sstevel@tonic-gate 				 */
720*7c478bd9Sstevel@tonic-gate 				return ((int)alloc_string((char *)deflt));
721*7c478bd9Sstevel@tonic-gate 			} else if (type == FIO_SLIST) {
722*7c478bd9Sstevel@tonic-gate 				/*
723*7c478bd9Sstevel@tonic-gate 				 * If we can find a match for the default
724*7c478bd9Sstevel@tonic-gate 				 * value in the list, return the default
725*7c478bd9Sstevel@tonic-gate 				 * value.  If there's no match for the
726*7c478bd9Sstevel@tonic-gate 				 * default value, it's an illegal
727*7c478bd9Sstevel@tonic-gate 				 * choice.  Return the first value in
728*7c478bd9Sstevel@tonic-gate 				 * the list.
729*7c478bd9Sstevel@tonic-gate 				 */
730*7c478bd9Sstevel@tonic-gate 				s = find_string(param->io_slist, *deflt);
731*7c478bd9Sstevel@tonic-gate 				if ((cur_label == L_TYPE_EFI) &&
732*7c478bd9Sstevel@tonic-gate 				    (s == (char *)NULL)) {
733*7c478bd9Sstevel@tonic-gate 					return (*deflt);
734*7c478bd9Sstevel@tonic-gate 				}
735*7c478bd9Sstevel@tonic-gate 				if (s == (char *)NULL) {
736*7c478bd9Sstevel@tonic-gate 					return ((param->io_slist)->value);
737*7c478bd9Sstevel@tonic-gate 				} else {
738*7c478bd9Sstevel@tonic-gate 					return (*deflt);
739*7c478bd9Sstevel@tonic-gate 				}
740*7c478bd9Sstevel@tonic-gate 			} else if (type == FIO_OPINT) {
741*7c478bd9Sstevel@tonic-gate 				/*
742*7c478bd9Sstevel@tonic-gate 				 * The user didn't enter anything
743*7c478bd9Sstevel@tonic-gate 				 */
744*7c478bd9Sstevel@tonic-gate 				return (0);
745*7c478bd9Sstevel@tonic-gate 			} else if (type == FIO_ECYL) {
746*7c478bd9Sstevel@tonic-gate 				return (part_deflt->deflt_size);
747*7c478bd9Sstevel@tonic-gate 			} else if (type == FIO_INT64) {
748*7c478bd9Sstevel@tonic-gate 				return (efi_deflt->start_sector);
749*7c478bd9Sstevel@tonic-gate 			} else if (type == FIO_EFI) {
750*7c478bd9Sstevel@tonic-gate 				return (efi_deflt->end_sector);
751*7c478bd9Sstevel@tonic-gate 			} else {
752*7c478bd9Sstevel@tonic-gate 				return (*deflt);
753*7c478bd9Sstevel@tonic-gate 			}
754*7c478bd9Sstevel@tonic-gate 		}
755*7c478bd9Sstevel@tonic-gate 		/*
756*7c478bd9Sstevel@tonic-gate 		 * If the blank was not in the pipe, just reprompt.
757*7c478bd9Sstevel@tonic-gate 		 */
758*7c478bd9Sstevel@tonic-gate 		if (interactive) {
759*7c478bd9Sstevel@tonic-gate 			goto reprompt;
760*7c478bd9Sstevel@tonic-gate 		}
761*7c478bd9Sstevel@tonic-gate 		/*
762*7c478bd9Sstevel@tonic-gate 		 * If the blank was in the pipe, it's an error.
763*7c478bd9Sstevel@tonic-gate 		 */
764*7c478bd9Sstevel@tonic-gate 		err_print("No default for this entry.\n");
765*7c478bd9Sstevel@tonic-gate 		cmdabort(SIGINT);
766*7c478bd9Sstevel@tonic-gate 	}
767*7c478bd9Sstevel@tonic-gate 	/*
768*7c478bd9Sstevel@tonic-gate 	 * If token is a '?' or a 'h', it is a request for help.
769*7c478bd9Sstevel@tonic-gate 	 */
770*7c478bd9Sstevel@tonic-gate 	if ((strcmp(cleantoken, "?") == 0) ||
771*7c478bd9Sstevel@tonic-gate 		(strcmp(cleantoken, "h") == 0) ||
772*7c478bd9Sstevel@tonic-gate 			(strcmp(cleantoken, "help") == 0)) {
773*7c478bd9Sstevel@tonic-gate 		help = 1;
774*7c478bd9Sstevel@tonic-gate 	}
775*7c478bd9Sstevel@tonic-gate 	/*
776*7c478bd9Sstevel@tonic-gate 	 * Switch on the type of input expected.
777*7c478bd9Sstevel@tonic-gate 	 */
778*7c478bd9Sstevel@tonic-gate 	switch (type) {
779*7c478bd9Sstevel@tonic-gate 	/*
780*7c478bd9Sstevel@tonic-gate 	 * Expecting a disk block number.
781*7c478bd9Sstevel@tonic-gate 	 */
782*7c478bd9Sstevel@tonic-gate 	case FIO_BN:
783*7c478bd9Sstevel@tonic-gate 		/*
784*7c478bd9Sstevel@tonic-gate 		 * Parameter is the bounds of legal block numbers.
785*7c478bd9Sstevel@tonic-gate 		 */
786*7c478bd9Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
787*7c478bd9Sstevel@tonic-gate 		/*
788*7c478bd9Sstevel@tonic-gate 		 * Print help message if required.
789*7c478bd9Sstevel@tonic-gate 		 */
790*7c478bd9Sstevel@tonic-gate 		if (help) {
791*7c478bd9Sstevel@tonic-gate 			fmt_print("Expecting a block number from %llu (",
792*7c478bd9Sstevel@tonic-gate 			    bounds->lower);
793*7c478bd9Sstevel@tonic-gate 			pr_dblock(fmt_print, bounds->lower);
794*7c478bd9Sstevel@tonic-gate 			fmt_print(") to %llu (", bounds->upper);
795*7c478bd9Sstevel@tonic-gate 			pr_dblock(fmt_print, bounds->upper);
796*7c478bd9Sstevel@tonic-gate 			fmt_print(")\n");
797*7c478bd9Sstevel@tonic-gate 			break;
798*7c478bd9Sstevel@tonic-gate 		}
799*7c478bd9Sstevel@tonic-gate 		/*
800*7c478bd9Sstevel@tonic-gate 		 * Convert token to a disk block number.
801*7c478bd9Sstevel@tonic-gate 		 */
802*7c478bd9Sstevel@tonic-gate 		if (cur_label == L_TYPE_EFI) {
803*7c478bd9Sstevel@tonic-gate 		    if (geti64(cleantoken, (uint64_t *)&bn64,
804*7c478bd9Sstevel@tonic-gate 			(uint64_t *)NULL))
805*7c478bd9Sstevel@tonic-gate 			    break;
806*7c478bd9Sstevel@tonic-gate 		} else {
807*7c478bd9Sstevel@tonic-gate 		    if (getbn(cleantoken, &bn))
808*7c478bd9Sstevel@tonic-gate 			break;
809*7c478bd9Sstevel@tonic-gate 		}
810*7c478bd9Sstevel@tonic-gate 		if (cur_label == L_TYPE_EFI) {
811*7c478bd9Sstevel@tonic-gate 		    if ((bn64 < bounds->lower) || (bn64 > bounds->upper)) {
812*7c478bd9Sstevel@tonic-gate 			err_print("`");
813*7c478bd9Sstevel@tonic-gate 			pr_dblock(err_print, bn64);
814*7c478bd9Sstevel@tonic-gate 			err_print("' is out of range.\n");
815*7c478bd9Sstevel@tonic-gate 			break;
816*7c478bd9Sstevel@tonic-gate 		    }
817*7c478bd9Sstevel@tonic-gate 		    return (bn64);
818*7c478bd9Sstevel@tonic-gate 		}
819*7c478bd9Sstevel@tonic-gate 		/*
820*7c478bd9Sstevel@tonic-gate 		 * Check to be sure it is within the legal bounds.
821*7c478bd9Sstevel@tonic-gate 		 */
822*7c478bd9Sstevel@tonic-gate 		if ((bn < bounds->lower) || (bn > bounds->upper)) {
823*7c478bd9Sstevel@tonic-gate 			err_print("`");
824*7c478bd9Sstevel@tonic-gate 			pr_dblock(err_print, bn);
825*7c478bd9Sstevel@tonic-gate 			err_print("' is out of range.\n");
826*7c478bd9Sstevel@tonic-gate 			break;
827*7c478bd9Sstevel@tonic-gate 		}
828*7c478bd9Sstevel@tonic-gate 		/*
829*7c478bd9Sstevel@tonic-gate 		 * If it's ok, return it.
830*7c478bd9Sstevel@tonic-gate 		 */
831*7c478bd9Sstevel@tonic-gate 		return (bn);
832*7c478bd9Sstevel@tonic-gate 	/*
833*7c478bd9Sstevel@tonic-gate 	 * Expecting an integer.
834*7c478bd9Sstevel@tonic-gate 	 */
835*7c478bd9Sstevel@tonic-gate 	case FIO_INT:
836*7c478bd9Sstevel@tonic-gate 		/*
837*7c478bd9Sstevel@tonic-gate 		 * Parameter is the bounds of legal integers.
838*7c478bd9Sstevel@tonic-gate 		 */
839*7c478bd9Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
840*7c478bd9Sstevel@tonic-gate 		/*
841*7c478bd9Sstevel@tonic-gate 		 * Print help message if required.
842*7c478bd9Sstevel@tonic-gate 		 */
843*7c478bd9Sstevel@tonic-gate 		if (help) {
844*7c478bd9Sstevel@tonic-gate 			fmt_print("Expecting an integer from %llu",
845*7c478bd9Sstevel@tonic-gate 			    bounds->lower);
846*7c478bd9Sstevel@tonic-gate 			fmt_print(" to %llu\n", bounds->upper);
847*7c478bd9Sstevel@tonic-gate 			break;
848*7c478bd9Sstevel@tonic-gate 		}
849*7c478bd9Sstevel@tonic-gate 		/*
850*7c478bd9Sstevel@tonic-gate 		 * Convert the token into an integer.
851*7c478bd9Sstevel@tonic-gate 		 */
852*7c478bd9Sstevel@tonic-gate 		if (geti(cleantoken, (int *)&bn, (int *)NULL))
853*7c478bd9Sstevel@tonic-gate 			break;
854*7c478bd9Sstevel@tonic-gate 		/*
855*7c478bd9Sstevel@tonic-gate 		 * Check to be sure it is within the legal bounds.
856*7c478bd9Sstevel@tonic-gate 		 */
857*7c478bd9Sstevel@tonic-gate 		if ((bn < bounds->lower) || (bn > bounds->upper)) {
858*7c478bd9Sstevel@tonic-gate 			err_print("`%ld' is out of range.\n", bn);
859*7c478bd9Sstevel@tonic-gate 			break;
860*7c478bd9Sstevel@tonic-gate 		}
861*7c478bd9Sstevel@tonic-gate 		/*
862*7c478bd9Sstevel@tonic-gate 		 * If it's ok, return it.
863*7c478bd9Sstevel@tonic-gate 		 */
864*7c478bd9Sstevel@tonic-gate 		return (bn);
865*7c478bd9Sstevel@tonic-gate 	case FIO_INT64:
866*7c478bd9Sstevel@tonic-gate 		/*
867*7c478bd9Sstevel@tonic-gate 		 * Parameter is the bounds of legal integers.
868*7c478bd9Sstevel@tonic-gate 		 */
869*7c478bd9Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
870*7c478bd9Sstevel@tonic-gate 		/*
871*7c478bd9Sstevel@tonic-gate 		 * Print help message if required.
872*7c478bd9Sstevel@tonic-gate 		 */
873*7c478bd9Sstevel@tonic-gate 		if (help) {
874*7c478bd9Sstevel@tonic-gate 			fmt_print("Expecting an integer from %llu",
875*7c478bd9Sstevel@tonic-gate 			    bounds->lower);
876*7c478bd9Sstevel@tonic-gate 			fmt_print(" to %llu\n", bounds->upper);
877*7c478bd9Sstevel@tonic-gate 			break;
878*7c478bd9Sstevel@tonic-gate 		}
879*7c478bd9Sstevel@tonic-gate 		/*
880*7c478bd9Sstevel@tonic-gate 		 * Convert the token into an integer.
881*7c478bd9Sstevel@tonic-gate 		 */
882*7c478bd9Sstevel@tonic-gate 		if (geti64(cleantoken, (uint64_t *)&bn64, (uint64_t *)NULL)) {
883*7c478bd9Sstevel@tonic-gate 			break;
884*7c478bd9Sstevel@tonic-gate 		}
885*7c478bd9Sstevel@tonic-gate 		/*
886*7c478bd9Sstevel@tonic-gate 		 * Check to be sure it is within the legal bounds.
887*7c478bd9Sstevel@tonic-gate 		 */
888*7c478bd9Sstevel@tonic-gate 		if ((bn64 < bounds->lower) || (bn64 > bounds->upper)) {
889*7c478bd9Sstevel@tonic-gate 			err_print("`%llu' is out of range.\n", bn64);
890*7c478bd9Sstevel@tonic-gate 			break;
891*7c478bd9Sstevel@tonic-gate 		}
892*7c478bd9Sstevel@tonic-gate 		/*
893*7c478bd9Sstevel@tonic-gate 		 * If it's ok, return it.
894*7c478bd9Sstevel@tonic-gate 		 */
895*7c478bd9Sstevel@tonic-gate 		return (bn64);
896*7c478bd9Sstevel@tonic-gate 	/*
897*7c478bd9Sstevel@tonic-gate 	 * Expecting an integer, or no input.
898*7c478bd9Sstevel@tonic-gate 	 */
899*7c478bd9Sstevel@tonic-gate 	case FIO_OPINT:
900*7c478bd9Sstevel@tonic-gate 		/*
901*7c478bd9Sstevel@tonic-gate 		 * Parameter is the bounds of legal integers.
902*7c478bd9Sstevel@tonic-gate 		 */
903*7c478bd9Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
904*7c478bd9Sstevel@tonic-gate 		/*
905*7c478bd9Sstevel@tonic-gate 		 * Print help message if required.
906*7c478bd9Sstevel@tonic-gate 		 */
907*7c478bd9Sstevel@tonic-gate 		if (help) {
908*7c478bd9Sstevel@tonic-gate 			fmt_print("Expecting an integer from %llu",
909*7c478bd9Sstevel@tonic-gate 			    bounds->lower);
910*7c478bd9Sstevel@tonic-gate 			fmt_print(" to %llu, or no input\n", bounds->upper);
911*7c478bd9Sstevel@tonic-gate 			break;
912*7c478bd9Sstevel@tonic-gate 		}
913*7c478bd9Sstevel@tonic-gate 		/*
914*7c478bd9Sstevel@tonic-gate 		 * Convert the token into an integer.
915*7c478bd9Sstevel@tonic-gate 		 */
916*7c478bd9Sstevel@tonic-gate 		if (geti(cleantoken, (int *)&bn, (int *)NULL))
917*7c478bd9Sstevel@tonic-gate 			break;
918*7c478bd9Sstevel@tonic-gate 		/*
919*7c478bd9Sstevel@tonic-gate 		 * Check to be sure it is within the legal bounds.
920*7c478bd9Sstevel@tonic-gate 		 */
921*7c478bd9Sstevel@tonic-gate 		if ((bn < bounds->lower) || (bn > bounds->upper)) {
922*7c478bd9Sstevel@tonic-gate 			err_print("`%ld' is out of range.\n", bn);
923*7c478bd9Sstevel@tonic-gate 			break;
924*7c478bd9Sstevel@tonic-gate 		}
925*7c478bd9Sstevel@tonic-gate 		/*
926*7c478bd9Sstevel@tonic-gate 		 * For optional case, return 1 indicating that
927*7c478bd9Sstevel@tonic-gate 		 * the user actually did enter something.
928*7c478bd9Sstevel@tonic-gate 		 */
929*7c478bd9Sstevel@tonic-gate 		*deflt = bn;
930*7c478bd9Sstevel@tonic-gate 		return (1);
931*7c478bd9Sstevel@tonic-gate 	/*
932*7c478bd9Sstevel@tonic-gate 	 * Expecting a closed string.  This means that the input
933*7c478bd9Sstevel@tonic-gate 	 * string must exactly match one of the strings passed in
934*7c478bd9Sstevel@tonic-gate 	 * as the parameter.
935*7c478bd9Sstevel@tonic-gate 	 */
936*7c478bd9Sstevel@tonic-gate 	case FIO_CSTR:
937*7c478bd9Sstevel@tonic-gate 		/*
938*7c478bd9Sstevel@tonic-gate 		 * The parameter is a null terminated array of character
939*7c478bd9Sstevel@tonic-gate 		 * pointers, each one pointing to a legal input string.
940*7c478bd9Sstevel@tonic-gate 		 */
941*7c478bd9Sstevel@tonic-gate 		strings = (char **)param->io_charlist;
942*7c478bd9Sstevel@tonic-gate 		/*
943*7c478bd9Sstevel@tonic-gate 		 * Walk through the legal strings, seeing if any of them
944*7c478bd9Sstevel@tonic-gate 		 * match the token.  If a match is made, return the index
945*7c478bd9Sstevel@tonic-gate 		 * of the string that was matched.
946*7c478bd9Sstevel@tonic-gate 		 */
947*7c478bd9Sstevel@tonic-gate 		for (str = strings; *str != NULL; str++)
948*7c478bd9Sstevel@tonic-gate 			if (strcmp(cleantoken, *str) == 0)
949*7c478bd9Sstevel@tonic-gate 				return (str - strings);
950*7c478bd9Sstevel@tonic-gate 		/*
951*7c478bd9Sstevel@tonic-gate 		 * Print help message if required.
952*7c478bd9Sstevel@tonic-gate 		 */
953*7c478bd9Sstevel@tonic-gate 		if (help) {
954*7c478bd9Sstevel@tonic-gate 			print_input_choices(type, param);
955*7c478bd9Sstevel@tonic-gate 		} else {
956*7c478bd9Sstevel@tonic-gate 			err_print("`%s' is not expected.\n", cleantoken);
957*7c478bd9Sstevel@tonic-gate 		}
958*7c478bd9Sstevel@tonic-gate 		break;
959*7c478bd9Sstevel@tonic-gate 	/*
960*7c478bd9Sstevel@tonic-gate 	 * Expecting a matched string.  This means that the input
961*7c478bd9Sstevel@tonic-gate 	 * string must either match one of the strings passed in,
962*7c478bd9Sstevel@tonic-gate 	 * or be a unique abbreviation of one of them.
963*7c478bd9Sstevel@tonic-gate 	 */
964*7c478bd9Sstevel@tonic-gate 	case FIO_MSTR:
965*7c478bd9Sstevel@tonic-gate 		/*
966*7c478bd9Sstevel@tonic-gate 		 * The parameter is a null terminated array of character
967*7c478bd9Sstevel@tonic-gate 		 * pointers, each one pointing to a legal input string.
968*7c478bd9Sstevel@tonic-gate 		 */
969*7c478bd9Sstevel@tonic-gate 		strings = (char **)param->io_charlist;
970*7c478bd9Sstevel@tonic-gate 		length = index = tied = 0;
971*7c478bd9Sstevel@tonic-gate 		/*
972*7c478bd9Sstevel@tonic-gate 		 * Loop through the legal input strings.
973*7c478bd9Sstevel@tonic-gate 		 */
974*7c478bd9Sstevel@tonic-gate 		for (str = strings; *str != NULL; str++) {
975*7c478bd9Sstevel@tonic-gate 			/*
976*7c478bd9Sstevel@tonic-gate 			 * See how many characters of the token match
977*7c478bd9Sstevel@tonic-gate 			 * this legal string.
978*7c478bd9Sstevel@tonic-gate 			 */
979*7c478bd9Sstevel@tonic-gate 			i = strcnt(cleantoken, *str);
980*7c478bd9Sstevel@tonic-gate 			/*
981*7c478bd9Sstevel@tonic-gate 			 * If it's not the whole token, then it's not a match.
982*7c478bd9Sstevel@tonic-gate 			 */
983*7c478bd9Sstevel@tonic-gate 			if ((uint_t)i < strlen(cleantoken))
984*7c478bd9Sstevel@tonic-gate 				continue;
985*7c478bd9Sstevel@tonic-gate 			/*
986*7c478bd9Sstevel@tonic-gate 			 * If it ties with another input, remember that.
987*7c478bd9Sstevel@tonic-gate 			 */
988*7c478bd9Sstevel@tonic-gate 			if (i == length)
989*7c478bd9Sstevel@tonic-gate 				tied = 1;
990*7c478bd9Sstevel@tonic-gate 			/*
991*7c478bd9Sstevel@tonic-gate 			 * If it matches the most so far, record that.
992*7c478bd9Sstevel@tonic-gate 			 */
993*7c478bd9Sstevel@tonic-gate 			if (i > length) {
994*7c478bd9Sstevel@tonic-gate 				index = str - strings;
995*7c478bd9Sstevel@tonic-gate 				tied = 0;
996*7c478bd9Sstevel@tonic-gate 				length = i;
997*7c478bd9Sstevel@tonic-gate 			}
998*7c478bd9Sstevel@tonic-gate 		}
999*7c478bd9Sstevel@tonic-gate 		/*
1000*7c478bd9Sstevel@tonic-gate 		 * Print help message if required.
1001*7c478bd9Sstevel@tonic-gate 		 */
1002*7c478bd9Sstevel@tonic-gate 		if (length == 0) {
1003*7c478bd9Sstevel@tonic-gate 			if (help) {
1004*7c478bd9Sstevel@tonic-gate 				print_input_choices(type, param);
1005*7c478bd9Sstevel@tonic-gate 			} else {
1006*7c478bd9Sstevel@tonic-gate 				err_print("`%s' is not expected.\n",
1007*7c478bd9Sstevel@tonic-gate 				    cleantoken);
1008*7c478bd9Sstevel@tonic-gate 			}
1009*7c478bd9Sstevel@tonic-gate 			break;
1010*7c478bd9Sstevel@tonic-gate 		}
1011*7c478bd9Sstevel@tonic-gate 		/*
1012*7c478bd9Sstevel@tonic-gate 		 * If the abbreviation was non-unique, it's an error.
1013*7c478bd9Sstevel@tonic-gate 		 */
1014*7c478bd9Sstevel@tonic-gate 		if (tied) {
1015*7c478bd9Sstevel@tonic-gate 			err_print("`%s' is ambiguous.\n", cleantoken);
1016*7c478bd9Sstevel@tonic-gate 			break;
1017*7c478bd9Sstevel@tonic-gate 		}
1018*7c478bd9Sstevel@tonic-gate 		/*
1019*7c478bd9Sstevel@tonic-gate 		 * We matched one.  Return the index of the string we matched.
1020*7c478bd9Sstevel@tonic-gate 		 */
1021*7c478bd9Sstevel@tonic-gate 		return (index);
1022*7c478bd9Sstevel@tonic-gate 	/*
1023*7c478bd9Sstevel@tonic-gate 	 * Expecting an open string.  This means that any string is legal.
1024*7c478bd9Sstevel@tonic-gate 	 */
1025*7c478bd9Sstevel@tonic-gate 	case FIO_OSTR:
1026*7c478bd9Sstevel@tonic-gate 		/*
1027*7c478bd9Sstevel@tonic-gate 		 * Print a help message if required.
1028*7c478bd9Sstevel@tonic-gate 		 */
1029*7c478bd9Sstevel@tonic-gate 		if (help) {
1030*7c478bd9Sstevel@tonic-gate 			fmt_print("Expecting a string\n");
1031*7c478bd9Sstevel@tonic-gate 			break;
1032*7c478bd9Sstevel@tonic-gate 		}
1033*7c478bd9Sstevel@tonic-gate 		/*
1034*7c478bd9Sstevel@tonic-gate 		 * alloc a copy of the string and return it
1035*7c478bd9Sstevel@tonic-gate 		 */
1036*7c478bd9Sstevel@tonic-gate 		return ((int)alloc_string(token));
1037*7c478bd9Sstevel@tonic-gate 
1038*7c478bd9Sstevel@tonic-gate 	/*
1039*7c478bd9Sstevel@tonic-gate 	 * Expecting a blank line.
1040*7c478bd9Sstevel@tonic-gate 	 */
1041*7c478bd9Sstevel@tonic-gate 	case FIO_BLNK:
1042*7c478bd9Sstevel@tonic-gate 		/*
1043*7c478bd9Sstevel@tonic-gate 		 * We are always in non-echo mode when we are inputting
1044*7c478bd9Sstevel@tonic-gate 		 * this type.  We echo the newline as a carriage return
1045*7c478bd9Sstevel@tonic-gate 		 * only so the prompt string will be covered over.
1046*7c478bd9Sstevel@tonic-gate 		 */
1047*7c478bd9Sstevel@tonic-gate 		nolog_print("\015");
1048*7c478bd9Sstevel@tonic-gate 		/*
1049*7c478bd9Sstevel@tonic-gate 		 * If we are logging, send a newline to the log file.
1050*7c478bd9Sstevel@tonic-gate 		 */
1051*7c478bd9Sstevel@tonic-gate 		if (log_file)
1052*7c478bd9Sstevel@tonic-gate 			log_print("\n");
1053*7c478bd9Sstevel@tonic-gate 		/*
1054*7c478bd9Sstevel@tonic-gate 		 * There is no value returned for this type.
1055*7c478bd9Sstevel@tonic-gate 		 */
1056*7c478bd9Sstevel@tonic-gate 		return (0);
1057*7c478bd9Sstevel@tonic-gate 
1058*7c478bd9Sstevel@tonic-gate 	/*
1059*7c478bd9Sstevel@tonic-gate 	 * Expecting one of the entries in a string list.
1060*7c478bd9Sstevel@tonic-gate 	 * Accept unique abbreviations.
1061*7c478bd9Sstevel@tonic-gate 	 * Return the value associated with the matched string.
1062*7c478bd9Sstevel@tonic-gate 	 */
1063*7c478bd9Sstevel@tonic-gate 	case FIO_SLIST:
1064*7c478bd9Sstevel@tonic-gate 		i = find_value((slist_t *)param->io_slist,
1065*7c478bd9Sstevel@tonic-gate 			cleantoken, &value);
1066*7c478bd9Sstevel@tonic-gate 		if (i == 1) {
1067*7c478bd9Sstevel@tonic-gate 			return (value);
1068*7c478bd9Sstevel@tonic-gate 		} else {
1069*7c478bd9Sstevel@tonic-gate 			/*
1070*7c478bd9Sstevel@tonic-gate 			 * Print help message if required.
1071*7c478bd9Sstevel@tonic-gate 			 */
1072*7c478bd9Sstevel@tonic-gate 
1073*7c478bd9Sstevel@tonic-gate 			if (help) {
1074*7c478bd9Sstevel@tonic-gate 				print_input_choices(type, param);
1075*7c478bd9Sstevel@tonic-gate 			} else {
1076*7c478bd9Sstevel@tonic-gate 				if (i == 0)
1077*7c478bd9Sstevel@tonic-gate 					err_print("`%s' not expected.\n",
1078*7c478bd9Sstevel@tonic-gate 					    cleantoken);
1079*7c478bd9Sstevel@tonic-gate 				else
1080*7c478bd9Sstevel@tonic-gate 					err_print("`%s' is ambiguous.\n",
1081*7c478bd9Sstevel@tonic-gate 					    cleantoken);
1082*7c478bd9Sstevel@tonic-gate 			}
1083*7c478bd9Sstevel@tonic-gate 		}
1084*7c478bd9Sstevel@tonic-gate 		break;
1085*7c478bd9Sstevel@tonic-gate 
1086*7c478bd9Sstevel@tonic-gate 	/*
1087*7c478bd9Sstevel@tonic-gate 	 * Cylinder size input when modifying a complete partition map
1088*7c478bd9Sstevel@tonic-gate 	 */
1089*7c478bd9Sstevel@tonic-gate 	case FIO_CYL:
1090*7c478bd9Sstevel@tonic-gate 		/*
1091*7c478bd9Sstevel@tonic-gate 		 * Parameter is the bounds of legal block numbers.
1092*7c478bd9Sstevel@tonic-gate 		 */
1093*7c478bd9Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
1094*7c478bd9Sstevel@tonic-gate 		assert(bounds->lower == 0);
1095*7c478bd9Sstevel@tonic-gate 		/*
1096*7c478bd9Sstevel@tonic-gate 		 * Print help message if required.
1097*7c478bd9Sstevel@tonic-gate 		 */
1098*7c478bd9Sstevel@tonic-gate 		if (help) {
1099*7c478bd9Sstevel@tonic-gate 			fmt_print("Expecting up to %llu blocks,",
1100*7c478bd9Sstevel@tonic-gate 			    bounds->upper);
1101*7c478bd9Sstevel@tonic-gate 			fmt_print(" %llu cylinders, ", bn2c(bounds->upper));
1102*7c478bd9Sstevel@tonic-gate 			fmt_print(" %1.2f megabytes, ", bn2mb(bounds->upper));
1103*7c478bd9Sstevel@tonic-gate 			fmt_print("or %1.2f gigabytes\n", bn2gb(bounds->upper));
1104*7c478bd9Sstevel@tonic-gate 			break;
1105*7c478bd9Sstevel@tonic-gate 		}
1106*7c478bd9Sstevel@tonic-gate 		/*
1107*7c478bd9Sstevel@tonic-gate 		 * Parse the first token: try to find 'b', 'c' or 'm'
1108*7c478bd9Sstevel@tonic-gate 		 */
1109*7c478bd9Sstevel@tonic-gate 		s = cleantoken;
1110*7c478bd9Sstevel@tonic-gate 		while (*s && (isdigit(*s) || (*s == '.') || (*s == '$'))) {
1111*7c478bd9Sstevel@tonic-gate 			s++;
1112*7c478bd9Sstevel@tonic-gate 		}
1113*7c478bd9Sstevel@tonic-gate 		/*
1114*7c478bd9Sstevel@tonic-gate 		 * If we found a conversion specifier, second token is unused
1115*7c478bd9Sstevel@tonic-gate 		 * Otherwise, the second token should supply it.
1116*7c478bd9Sstevel@tonic-gate 		 */
1117*7c478bd9Sstevel@tonic-gate 		if (*s != 0) {
1118*7c478bd9Sstevel@tonic-gate 			value = *s;
1119*7c478bd9Sstevel@tonic-gate 			*s = 0;
1120*7c478bd9Sstevel@tonic-gate 		} else {
1121*7c478bd9Sstevel@tonic-gate 			value = cleantoken2[0];
1122*7c478bd9Sstevel@tonic-gate 		}
1123*7c478bd9Sstevel@tonic-gate 		/*
1124*7c478bd9Sstevel@tonic-gate 		 * If the token is the wild card, simply supply the max
1125*7c478bd9Sstevel@tonic-gate 		 * This order allows the user to specify the maximum in
1126*7c478bd9Sstevel@tonic-gate 		 * either blocks/cyls/megabytes - a convenient fiction.
1127*7c478bd9Sstevel@tonic-gate 		 */
1128*7c478bd9Sstevel@tonic-gate 		if (strcmp(cleantoken, WILD_STRING) == 0) {
1129*7c478bd9Sstevel@tonic-gate 			return (bounds->upper);
1130*7c478bd9Sstevel@tonic-gate 		}
1131*7c478bd9Sstevel@tonic-gate 		/*
1132*7c478bd9Sstevel@tonic-gate 		 * Allow the user to specify zero with no units,
1133*7c478bd9Sstevel@tonic-gate 		 * by just defaulting to cylinders.
1134*7c478bd9Sstevel@tonic-gate 		 */
1135*7c478bd9Sstevel@tonic-gate 		if (strcmp(cleantoken, "0") == 0) {
1136*7c478bd9Sstevel@tonic-gate 			value = 'c';
1137*7c478bd9Sstevel@tonic-gate 		}
1138*7c478bd9Sstevel@tonic-gate 		/*
1139*7c478bd9Sstevel@tonic-gate 		 * If there's a decimal point, but no unit specification,
1140*7c478bd9Sstevel@tonic-gate 		 * let's assume megabytes.
1141*7c478bd9Sstevel@tonic-gate 		 */
1142*7c478bd9Sstevel@tonic-gate 		if ((value == 0) && (strchr(cleantoken, '.') != NULL)) {
1143*7c478bd9Sstevel@tonic-gate 			value = 'm';
1144*7c478bd9Sstevel@tonic-gate 		}
1145*7c478bd9Sstevel@tonic-gate 		/*
1146*7c478bd9Sstevel@tonic-gate 		 * Handle each unit type we support
1147*7c478bd9Sstevel@tonic-gate 		 */
1148*7c478bd9Sstevel@tonic-gate 		switch (value) {
1149*7c478bd9Sstevel@tonic-gate 		case 'b':
1150*7c478bd9Sstevel@tonic-gate 			/*
1151*7c478bd9Sstevel@tonic-gate 			 * Convert token to a disk block number.
1152*7c478bd9Sstevel@tonic-gate 			 */
1153*7c478bd9Sstevel@tonic-gate 			i = bounds->upper;
1154*7c478bd9Sstevel@tonic-gate 			if (geti(cleantoken, &value, &i))
1155*7c478bd9Sstevel@tonic-gate 				break;
1156*7c478bd9Sstevel@tonic-gate 			bn = value;
1157*7c478bd9Sstevel@tonic-gate 			/*
1158*7c478bd9Sstevel@tonic-gate 			 * Check to be sure it is within the legal bounds.
1159*7c478bd9Sstevel@tonic-gate 			 */
1160*7c478bd9Sstevel@tonic-gate 			if ((bn < bounds->lower) || (bn > bounds->upper)) {
1161*7c478bd9Sstevel@tonic-gate 				err_print(
1162*7c478bd9Sstevel@tonic-gate "`%ldb' is out of the range %llu to %llu\n",
1163*7c478bd9Sstevel@tonic-gate 				    bn, bounds->lower, bounds->upper);
1164*7c478bd9Sstevel@tonic-gate 				break;
1165*7c478bd9Sstevel@tonic-gate 			}
1166*7c478bd9Sstevel@tonic-gate 			/*
1167*7c478bd9Sstevel@tonic-gate 			 * Verify the block lies on a cylinder boundary
1168*7c478bd9Sstevel@tonic-gate 			 */
1169*7c478bd9Sstevel@tonic-gate 			if ((bn % spc()) != 0) {
1170*7c478bd9Sstevel@tonic-gate 				err_print(
1171*7c478bd9Sstevel@tonic-gate "partition size must be a multiple of %d blocks to lie on a cylinder \
1172*7c478bd9Sstevel@tonic-gate boundary\n",
1173*7c478bd9Sstevel@tonic-gate 				    spc());
1174*7c478bd9Sstevel@tonic-gate 				err_print(
1175*7c478bd9Sstevel@tonic-gate "%ld blocks is approximately %ld cylinders, %1.2f megabytes or %1.2f\
1176*7c478bd9Sstevel@tonic-gate gigabytes\n",
1177*7c478bd9Sstevel@tonic-gate 				    bn, bn2c(bn), bn2mb(bn), bn2gb(bn));
1178*7c478bd9Sstevel@tonic-gate 				break;
1179*7c478bd9Sstevel@tonic-gate 			}
1180*7c478bd9Sstevel@tonic-gate 			return (bn);
1181*7c478bd9Sstevel@tonic-gate 		case 'c':
1182*7c478bd9Sstevel@tonic-gate 			/*
1183*7c478bd9Sstevel@tonic-gate 			 * Convert token from a number of cylinders to
1184*7c478bd9Sstevel@tonic-gate 			 * a number of blocks.
1185*7c478bd9Sstevel@tonic-gate 			 */
1186*7c478bd9Sstevel@tonic-gate 			i = bn2c(bounds->upper);
1187*7c478bd9Sstevel@tonic-gate 			if (geti(cleantoken, &cyls, &i))
1188*7c478bd9Sstevel@tonic-gate 				break;
1189*7c478bd9Sstevel@tonic-gate 			/*
1190*7c478bd9Sstevel@tonic-gate 			 * Check the bounds - cyls is number of cylinders
1191*7c478bd9Sstevel@tonic-gate 			 */
1192*7c478bd9Sstevel@tonic-gate 			if (cyls > (bounds->upper/spc())) {
1193*7c478bd9Sstevel@tonic-gate 				err_print("`%dc' is out of range\n", cyls);
1194*7c478bd9Sstevel@tonic-gate 				break;
1195*7c478bd9Sstevel@tonic-gate 			}
1196*7c478bd9Sstevel@tonic-gate 			/*
1197*7c478bd9Sstevel@tonic-gate 			 * Convert cylinders to blocks and return
1198*7c478bd9Sstevel@tonic-gate 			 */
1199*7c478bd9Sstevel@tonic-gate 			return (cyls * spc());
1200*7c478bd9Sstevel@tonic-gate 		case 'm':
1201*7c478bd9Sstevel@tonic-gate 			/*
1202*7c478bd9Sstevel@tonic-gate 			 * Convert token from megabytes to a block number.
1203*7c478bd9Sstevel@tonic-gate 			 */
1204*7c478bd9Sstevel@tonic-gate 			if (sscanf(cleantoken, "%f2", &nmegs) == 0) {
1205*7c478bd9Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
1206*7c478bd9Sstevel@tonic-gate 				    cleantoken);
1207*7c478bd9Sstevel@tonic-gate 				break;
1208*7c478bd9Sstevel@tonic-gate 			}
1209*7c478bd9Sstevel@tonic-gate 			/*
1210*7c478bd9Sstevel@tonic-gate 			 * Check the bounds
1211*7c478bd9Sstevel@tonic-gate 			 */
1212*7c478bd9Sstevel@tonic-gate 			if (nmegs > bn2mb(bounds->upper)) {
1213*7c478bd9Sstevel@tonic-gate 				err_print("`%1.2fmb' is out of range\n", nmegs);
1214*7c478bd9Sstevel@tonic-gate 				break;
1215*7c478bd9Sstevel@tonic-gate 			}
1216*7c478bd9Sstevel@tonic-gate 			/*
1217*7c478bd9Sstevel@tonic-gate 			 * Convert to blocks
1218*7c478bd9Sstevel@tonic-gate 			 */
1219*7c478bd9Sstevel@tonic-gate 			bn = mb2bn(nmegs);
1220*7c478bd9Sstevel@tonic-gate 			/*
1221*7c478bd9Sstevel@tonic-gate 			 * Round value up to nearest cylinder
1222*7c478bd9Sstevel@tonic-gate 			 */
1223*7c478bd9Sstevel@tonic-gate 			i = spc();
1224*7c478bd9Sstevel@tonic-gate 			bn = ((bn + (i-1)) / i) * i;
1225*7c478bd9Sstevel@tonic-gate 			return (bn);
1226*7c478bd9Sstevel@tonic-gate 		case 'g':
1227*7c478bd9Sstevel@tonic-gate 			/*
1228*7c478bd9Sstevel@tonic-gate 			 * Convert token from gigabytes to a block number.
1229*7c478bd9Sstevel@tonic-gate 			 */
1230*7c478bd9Sstevel@tonic-gate 			if (sscanf(cleantoken, "%f2", &ngigs) == 0) {
1231*7c478bd9Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
1232*7c478bd9Sstevel@tonic-gate 				    cleantoken);
1233*7c478bd9Sstevel@tonic-gate 				break;
1234*7c478bd9Sstevel@tonic-gate 			}
1235*7c478bd9Sstevel@tonic-gate 			/*
1236*7c478bd9Sstevel@tonic-gate 			 * Check the bounds
1237*7c478bd9Sstevel@tonic-gate 			 */
1238*7c478bd9Sstevel@tonic-gate 			if (ngigs > bn2gb(bounds->upper)) {
1239*7c478bd9Sstevel@tonic-gate 				err_print("`%1.2fgb' is out of range\n", ngigs);
1240*7c478bd9Sstevel@tonic-gate 				break;
1241*7c478bd9Sstevel@tonic-gate 			}
1242*7c478bd9Sstevel@tonic-gate 			/*
1243*7c478bd9Sstevel@tonic-gate 			 * Convert to blocks
1244*7c478bd9Sstevel@tonic-gate 			 */
1245*7c478bd9Sstevel@tonic-gate 			bn = gb2bn(ngigs);
1246*7c478bd9Sstevel@tonic-gate 			/*
1247*7c478bd9Sstevel@tonic-gate 			 * Round value up to nearest cylinder
1248*7c478bd9Sstevel@tonic-gate 			 */
1249*7c478bd9Sstevel@tonic-gate 			i = spc();
1250*7c478bd9Sstevel@tonic-gate 			bn = ((bn + (i-1)) / i) * i;
1251*7c478bd9Sstevel@tonic-gate 			return (bn);
1252*7c478bd9Sstevel@tonic-gate 		default:
1253*7c478bd9Sstevel@tonic-gate 			err_print(
1254*7c478bd9Sstevel@tonic-gate "Please specify units in either b(blocks), c(cylinders), m(megabytes) \
1255*7c478bd9Sstevel@tonic-gate or g(gigabytes)\n");
1256*7c478bd9Sstevel@tonic-gate 			break;
1257*7c478bd9Sstevel@tonic-gate 		}
1258*7c478bd9Sstevel@tonic-gate 		break;
1259*7c478bd9Sstevel@tonic-gate 
1260*7c478bd9Sstevel@tonic-gate 	case FIO_ECYL:
1261*7c478bd9Sstevel@tonic-gate 		/*
1262*7c478bd9Sstevel@tonic-gate 		 * Parameter is the bounds of legal block numbers.
1263*7c478bd9Sstevel@tonic-gate 		 */
1264*7c478bd9Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
1265*7c478bd9Sstevel@tonic-gate 		assert(bounds->lower == 0);
1266*7c478bd9Sstevel@tonic-gate 
1267*7c478bd9Sstevel@tonic-gate 		/*
1268*7c478bd9Sstevel@tonic-gate 		 * Print help message if required.
1269*7c478bd9Sstevel@tonic-gate 		 */
1270*7c478bd9Sstevel@tonic-gate 		if (help) {
1271*7c478bd9Sstevel@tonic-gate 			fmt_print("Expecting up to %llu blocks,",
1272*7c478bd9Sstevel@tonic-gate 			    bounds->upper);
1273*7c478bd9Sstevel@tonic-gate 			fmt_print(" %llu cylinders, ",
1274*7c478bd9Sstevel@tonic-gate 			    bn2c(bounds->upper));
1275*7c478bd9Sstevel@tonic-gate 			fmt_print(" %llu end cylinder, ",
1276*7c478bd9Sstevel@tonic-gate 			    (bounds->upper / spc()));
1277*7c478bd9Sstevel@tonic-gate 			fmt_print(" %1.2f megabytes, ",
1278*7c478bd9Sstevel@tonic-gate 			    bn2mb(bounds->upper));
1279*7c478bd9Sstevel@tonic-gate 			fmt_print("or %1.2f gigabytes\n",
1280*7c478bd9Sstevel@tonic-gate 			    bn2gb(bounds->upper));
1281*7c478bd9Sstevel@tonic-gate 			break;
1282*7c478bd9Sstevel@tonic-gate 		}
1283*7c478bd9Sstevel@tonic-gate 
1284*7c478bd9Sstevel@tonic-gate 		/*
1285*7c478bd9Sstevel@tonic-gate 		 * Parse the first token: try to find 'b', 'c', 'e'
1286*7c478bd9Sstevel@tonic-gate 		 * or 'm'
1287*7c478bd9Sstevel@tonic-gate 		 */
1288*7c478bd9Sstevel@tonic-gate 		s = cleantoken;
1289*7c478bd9Sstevel@tonic-gate 		while (*s && (isdigit(*s) || (*s == '.') || (*s == '$'))) {
1290*7c478bd9Sstevel@tonic-gate 			s++;
1291*7c478bd9Sstevel@tonic-gate 		}
1292*7c478bd9Sstevel@tonic-gate 
1293*7c478bd9Sstevel@tonic-gate 		/*
1294*7c478bd9Sstevel@tonic-gate 		 * If we found a conversion specifier, second token is
1295*7c478bd9Sstevel@tonic-gate 		 * unused Otherwise, the second token should supply it.
1296*7c478bd9Sstevel@tonic-gate 		 */
1297*7c478bd9Sstevel@tonic-gate 		if (*s != 0) {
1298*7c478bd9Sstevel@tonic-gate 			value = *s;
1299*7c478bd9Sstevel@tonic-gate 			*s = 0;
1300*7c478bd9Sstevel@tonic-gate 		} else {
1301*7c478bd9Sstevel@tonic-gate 			value = cleantoken2[0];
1302*7c478bd9Sstevel@tonic-gate 		}
1303*7c478bd9Sstevel@tonic-gate 
1304*7c478bd9Sstevel@tonic-gate 		/*
1305*7c478bd9Sstevel@tonic-gate 		 * If the token is the wild card, simply supply the max
1306*7c478bd9Sstevel@tonic-gate 		 * This order allows the user to specify the maximum in
1307*7c478bd9Sstevel@tonic-gate 		 * either blocks/cyls/megabytes - a convenient fiction.
1308*7c478bd9Sstevel@tonic-gate 		 */
1309*7c478bd9Sstevel@tonic-gate 		if (strcmp(cleantoken, WILD_STRING) == 0) {
1310*7c478bd9Sstevel@tonic-gate 			return (bounds->upper);
1311*7c478bd9Sstevel@tonic-gate 		}
1312*7c478bd9Sstevel@tonic-gate 
1313*7c478bd9Sstevel@tonic-gate 		/*
1314*7c478bd9Sstevel@tonic-gate 		 * Allow the user to specify zero with no units,
1315*7c478bd9Sstevel@tonic-gate 		 * by just defaulting to cylinders.
1316*7c478bd9Sstevel@tonic-gate 		 */
1317*7c478bd9Sstevel@tonic-gate 
1318*7c478bd9Sstevel@tonic-gate 		if (value != 'e' && strcmp(cleantoken, "0") == 0) {
1319*7c478bd9Sstevel@tonic-gate 			value = 'c';
1320*7c478bd9Sstevel@tonic-gate 		}
1321*7c478bd9Sstevel@tonic-gate 
1322*7c478bd9Sstevel@tonic-gate 
1323*7c478bd9Sstevel@tonic-gate 		/*
1324*7c478bd9Sstevel@tonic-gate 		 * If there's a decimal point, but no unit
1325*7c478bd9Sstevel@tonic-gate 		 * specification, let's assume megabytes.
1326*7c478bd9Sstevel@tonic-gate 		 */
1327*7c478bd9Sstevel@tonic-gate 		if ((value == 0) && (strchr(cleantoken, '.') != NULL)) {
1328*7c478bd9Sstevel@tonic-gate 			value = 'm';
1329*7c478bd9Sstevel@tonic-gate 		}
1330*7c478bd9Sstevel@tonic-gate 
1331*7c478bd9Sstevel@tonic-gate 		/*
1332*7c478bd9Sstevel@tonic-gate 		 * Handle each unit type we support
1333*7c478bd9Sstevel@tonic-gate 		 */
1334*7c478bd9Sstevel@tonic-gate 		switch (value) {
1335*7c478bd9Sstevel@tonic-gate 		case 'b':
1336*7c478bd9Sstevel@tonic-gate 			/*
1337*7c478bd9Sstevel@tonic-gate 			 * Convert token to a disk block number.
1338*7c478bd9Sstevel@tonic-gate 			 */
1339*7c478bd9Sstevel@tonic-gate 			i = bounds->upper;
1340*7c478bd9Sstevel@tonic-gate 			if (geti(cleantoken, &value, &i))
1341*7c478bd9Sstevel@tonic-gate 				break;
1342*7c478bd9Sstevel@tonic-gate 			bn = value;
1343*7c478bd9Sstevel@tonic-gate 			/*
1344*7c478bd9Sstevel@tonic-gate 			 * Check to be sure it is within the
1345*7c478bd9Sstevel@tonic-gate 			 * legal bounds.
1346*7c478bd9Sstevel@tonic-gate 			 */
1347*7c478bd9Sstevel@tonic-gate 			if ((bn < bounds->lower) || (bn > bounds->upper)) {
1348*7c478bd9Sstevel@tonic-gate 				err_print(
1349*7c478bd9Sstevel@tonic-gate "`%ldb' is out of the range %llu to %llu\n",
1350*7c478bd9Sstevel@tonic-gate 				    bn, bounds->lower, bounds->upper);
1351*7c478bd9Sstevel@tonic-gate 				break;
1352*7c478bd9Sstevel@tonic-gate 			}
1353*7c478bd9Sstevel@tonic-gate 
1354*7c478bd9Sstevel@tonic-gate 			/*
1355*7c478bd9Sstevel@tonic-gate 			 * Verify the block lies on a cylinder
1356*7c478bd9Sstevel@tonic-gate 			 * boundary
1357*7c478bd9Sstevel@tonic-gate 			 */
1358*7c478bd9Sstevel@tonic-gate 			if ((bn % spc()) != 0) {
1359*7c478bd9Sstevel@tonic-gate 				err_print(
1360*7c478bd9Sstevel@tonic-gate "partition size must be a multiple of %d blocks to lie on a cylinder \
1361*7c478bd9Sstevel@tonic-gate boundary\n",
1362*7c478bd9Sstevel@tonic-gate 				    spc());
1363*7c478bd9Sstevel@tonic-gate 				err_print(
1364*7c478bd9Sstevel@tonic-gate "%ld blocks is approximately %ld cylinders, %1.2f \
1365*7c478bd9Sstevel@tonic-gate megabytes or %1.2f gigabytes\n",
1366*7c478bd9Sstevel@tonic-gate 				    bn, bn2c(bn), bn2mb(bn), bn2gb(bn));
1367*7c478bd9Sstevel@tonic-gate 				break;
1368*7c478bd9Sstevel@tonic-gate 			}
1369*7c478bd9Sstevel@tonic-gate 
1370*7c478bd9Sstevel@tonic-gate 			return (bn);
1371*7c478bd9Sstevel@tonic-gate 
1372*7c478bd9Sstevel@tonic-gate 		case 'e':
1373*7c478bd9Sstevel@tonic-gate 			/*
1374*7c478bd9Sstevel@tonic-gate 			 * Token is ending cylinder
1375*7c478bd9Sstevel@tonic-gate 			 */
1376*7c478bd9Sstevel@tonic-gate 
1377*7c478bd9Sstevel@tonic-gate 			/* convert token to integer */
1378*7c478bd9Sstevel@tonic-gate 			if (geti(cleantoken, &cylno, (int *)NULL)) {
1379*7c478bd9Sstevel@tonic-gate 				break;
1380*7c478bd9Sstevel@tonic-gate 			}
1381*7c478bd9Sstevel@tonic-gate 
1382*7c478bd9Sstevel@tonic-gate 			/*
1383*7c478bd9Sstevel@tonic-gate 			 * check that input cylno isn't before the current
1384*7c478bd9Sstevel@tonic-gate 			 * starting cylinder number.  Note that we are NOT
1385*7c478bd9Sstevel@tonic-gate 			 * using the starting cylinder from
1386*7c478bd9Sstevel@tonic-gate 			 * cur_parts->pinfo_map[].dkl_cylno!
1387*7c478bd9Sstevel@tonic-gate 			 */
1388*7c478bd9Sstevel@tonic-gate 			if (cylno < part_deflt->start_cyl) {
1389*7c478bd9Sstevel@tonic-gate 				err_print(
1390*7c478bd9Sstevel@tonic-gate "End cylinder must fall on or after start cylinder %d\n",
1391*7c478bd9Sstevel@tonic-gate 				    part_deflt->start_cyl);
1392*7c478bd9Sstevel@tonic-gate 				break;
1393*7c478bd9Sstevel@tonic-gate 			}
1394*7c478bd9Sstevel@tonic-gate 
1395*7c478bd9Sstevel@tonic-gate 			/*
1396*7c478bd9Sstevel@tonic-gate 			 * calculate cylinder number of upper boundary, and
1397*7c478bd9Sstevel@tonic-gate 			 * verify that our input is within range
1398*7c478bd9Sstevel@tonic-gate 			 */
1399*7c478bd9Sstevel@tonic-gate 			i = (bn2c(bounds->upper) + part_deflt->start_cyl - 1);
1400*7c478bd9Sstevel@tonic-gate 
1401*7c478bd9Sstevel@tonic-gate 			if (cylno > i) {
1402*7c478bd9Sstevel@tonic-gate 				err_print(
1403*7c478bd9Sstevel@tonic-gate "End cylinder %d is beyond max cylinder %d\n",
1404*7c478bd9Sstevel@tonic-gate 				    cylno, i);
1405*7c478bd9Sstevel@tonic-gate 				break;
1406*7c478bd9Sstevel@tonic-gate 			}
1407*7c478bd9Sstevel@tonic-gate 
1408*7c478bd9Sstevel@tonic-gate 			/*
1409*7c478bd9Sstevel@tonic-gate 			 * calculate number of cylinders based on input
1410*7c478bd9Sstevel@tonic-gate 			 */
1411*7c478bd9Sstevel@tonic-gate 			cyls = ((cylno - part_deflt->start_cyl) + 1);
1412*7c478bd9Sstevel@tonic-gate 
1413*7c478bd9Sstevel@tonic-gate 			return (cyls * spc());
1414*7c478bd9Sstevel@tonic-gate 
1415*7c478bd9Sstevel@tonic-gate 		case 'c':
1416*7c478bd9Sstevel@tonic-gate 			/*
1417*7c478bd9Sstevel@tonic-gate 			 * Convert token from a number of
1418*7c478bd9Sstevel@tonic-gate 			 * cylinders to a number of blocks.
1419*7c478bd9Sstevel@tonic-gate 			 */
1420*7c478bd9Sstevel@tonic-gate 			i = bn2c(bounds->upper);
1421*7c478bd9Sstevel@tonic-gate 			if (geti(cleantoken, &cyls, &i))
1422*7c478bd9Sstevel@tonic-gate 				break;
1423*7c478bd9Sstevel@tonic-gate 
1424*7c478bd9Sstevel@tonic-gate 			/*
1425*7c478bd9Sstevel@tonic-gate 			 * Check the bounds - cyls is number of
1426*7c478bd9Sstevel@tonic-gate 			 * cylinders
1427*7c478bd9Sstevel@tonic-gate 			 */
1428*7c478bd9Sstevel@tonic-gate 			if (cyls > (bounds->upper/spc())) {
1429*7c478bd9Sstevel@tonic-gate 				err_print("`%dc' is out of range\n", cyls);
1430*7c478bd9Sstevel@tonic-gate 				break;
1431*7c478bd9Sstevel@tonic-gate 			}
1432*7c478bd9Sstevel@tonic-gate 
1433*7c478bd9Sstevel@tonic-gate 			/*
1434*7c478bd9Sstevel@tonic-gate 			 * Convert cylinders to blocks and
1435*7c478bd9Sstevel@tonic-gate 			 * return
1436*7c478bd9Sstevel@tonic-gate 			 */
1437*7c478bd9Sstevel@tonic-gate 			return (cyls * spc());
1438*7c478bd9Sstevel@tonic-gate 
1439*7c478bd9Sstevel@tonic-gate 		case 'm':
1440*7c478bd9Sstevel@tonic-gate 			/*
1441*7c478bd9Sstevel@tonic-gate 			 * Convert token from megabytes to a
1442*7c478bd9Sstevel@tonic-gate 			 * block number.
1443*7c478bd9Sstevel@tonic-gate 			 */
1444*7c478bd9Sstevel@tonic-gate 			if (sscanf(cleantoken, "%f2", &nmegs) == 0) {
1445*7c478bd9Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
1446*7c478bd9Sstevel@tonic-gate 				    cleantoken);
1447*7c478bd9Sstevel@tonic-gate 				break;
1448*7c478bd9Sstevel@tonic-gate 			}
1449*7c478bd9Sstevel@tonic-gate 
1450*7c478bd9Sstevel@tonic-gate 			/*
1451*7c478bd9Sstevel@tonic-gate 			 * Check the bounds
1452*7c478bd9Sstevel@tonic-gate 			 */
1453*7c478bd9Sstevel@tonic-gate 			if (nmegs > bn2mb(bounds->upper)) {
1454*7c478bd9Sstevel@tonic-gate 				err_print("`%1.2fmb' is out of range\n", nmegs);
1455*7c478bd9Sstevel@tonic-gate 				break;
1456*7c478bd9Sstevel@tonic-gate 			}
1457*7c478bd9Sstevel@tonic-gate 
1458*7c478bd9Sstevel@tonic-gate 			/*
1459*7c478bd9Sstevel@tonic-gate 			 * Convert to blocks
1460*7c478bd9Sstevel@tonic-gate 			 */
1461*7c478bd9Sstevel@tonic-gate 			bn = mb2bn(nmegs);
1462*7c478bd9Sstevel@tonic-gate 
1463*7c478bd9Sstevel@tonic-gate 			/*
1464*7c478bd9Sstevel@tonic-gate 			 * Round value up to nearest cylinder
1465*7c478bd9Sstevel@tonic-gate 			 */
1466*7c478bd9Sstevel@tonic-gate 			i = spc();
1467*7c478bd9Sstevel@tonic-gate 			bn = ((bn + (i-1)) / i) * i;
1468*7c478bd9Sstevel@tonic-gate 			return (bn);
1469*7c478bd9Sstevel@tonic-gate 
1470*7c478bd9Sstevel@tonic-gate 		case 'g':
1471*7c478bd9Sstevel@tonic-gate 			/*
1472*7c478bd9Sstevel@tonic-gate 			 * Convert token from gigabytes to a
1473*7c478bd9Sstevel@tonic-gate 			 * block number.
1474*7c478bd9Sstevel@tonic-gate 			 */
1475*7c478bd9Sstevel@tonic-gate 			if (sscanf(cleantoken, "%f2", &ngigs) == 0) {
1476*7c478bd9Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
1477*7c478bd9Sstevel@tonic-gate 				    cleantoken);
1478*7c478bd9Sstevel@tonic-gate 				break;
1479*7c478bd9Sstevel@tonic-gate 			}
1480*7c478bd9Sstevel@tonic-gate 
1481*7c478bd9Sstevel@tonic-gate 			/*
1482*7c478bd9Sstevel@tonic-gate 			 * Check the bounds
1483*7c478bd9Sstevel@tonic-gate 			 */
1484*7c478bd9Sstevel@tonic-gate 			if (ngigs > bn2gb(bounds->upper)) {
1485*7c478bd9Sstevel@tonic-gate 				err_print("`%1.2fgb' is out of range\n", ngigs);
1486*7c478bd9Sstevel@tonic-gate 				break;
1487*7c478bd9Sstevel@tonic-gate 			}
1488*7c478bd9Sstevel@tonic-gate 
1489*7c478bd9Sstevel@tonic-gate 			/*
1490*7c478bd9Sstevel@tonic-gate 			 * Convert to blocks
1491*7c478bd9Sstevel@tonic-gate 			 */
1492*7c478bd9Sstevel@tonic-gate 			bn = gb2bn(ngigs);
1493*7c478bd9Sstevel@tonic-gate 
1494*7c478bd9Sstevel@tonic-gate 			/*
1495*7c478bd9Sstevel@tonic-gate 			 * Round value up to nearest cylinder
1496*7c478bd9Sstevel@tonic-gate 			 */
1497*7c478bd9Sstevel@tonic-gate 			i = spc();
1498*7c478bd9Sstevel@tonic-gate 			bn = ((bn + (i-1)) / i) * i;
1499*7c478bd9Sstevel@tonic-gate 			return (bn);
1500*7c478bd9Sstevel@tonic-gate 
1501*7c478bd9Sstevel@tonic-gate 		default:
1502*7c478bd9Sstevel@tonic-gate 			err_print(
1503*7c478bd9Sstevel@tonic-gate "Please specify units in either b(blocks), c(cylinders), e(end cylinder),\n");
1504*7c478bd9Sstevel@tonic-gate 			err_print("m(megabytes) or g(gigabytes)\n");
1505*7c478bd9Sstevel@tonic-gate 			break;
1506*7c478bd9Sstevel@tonic-gate 		}
1507*7c478bd9Sstevel@tonic-gate 		break;
1508*7c478bd9Sstevel@tonic-gate 	case FIO_EFI:
1509*7c478bd9Sstevel@tonic-gate 		/*
1510*7c478bd9Sstevel@tonic-gate 		 * Parameter is the bounds of legal block numbers.
1511*7c478bd9Sstevel@tonic-gate 		 */
1512*7c478bd9Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
1513*7c478bd9Sstevel@tonic-gate 
1514*7c478bd9Sstevel@tonic-gate 		/*
1515*7c478bd9Sstevel@tonic-gate 		 * Print help message if required.
1516*7c478bd9Sstevel@tonic-gate 		 */
1517*7c478bd9Sstevel@tonic-gate 		if (help) {
1518*7c478bd9Sstevel@tonic-gate 			fmt_print("Expecting up to %llu sectors,",
1519*7c478bd9Sstevel@tonic-gate 			    cur_parts->etoc->efi_last_u_lba);
1520*7c478bd9Sstevel@tonic-gate 			fmt_print("or %llu megabytes,",
1521*7c478bd9Sstevel@tonic-gate 			    (cur_parts->etoc->efi_last_u_lba * DEV_BSIZE)/
1522*7c478bd9Sstevel@tonic-gate 				(1024 * 1024));
1523*7c478bd9Sstevel@tonic-gate 			fmt_print("or %llu gigabytes\n",
1524*7c478bd9Sstevel@tonic-gate 			    (cur_parts->etoc->efi_last_u_lba * DEV_BSIZE)/
1525*7c478bd9Sstevel@tonic-gate 				(1024 * 1024 * 1024));
1526*7c478bd9Sstevel@tonic-gate 			fmt_print("or %llu terabytes\n",
1527*7c478bd9Sstevel@tonic-gate 			    (cur_parts->etoc->efi_last_u_lba * DEV_BSIZE)/
1528*7c478bd9Sstevel@tonic-gate 				((uint64_t)1024 * 1024 * 1024 * 1024));
1529*7c478bd9Sstevel@tonic-gate 			break;
1530*7c478bd9Sstevel@tonic-gate 		}
1531*7c478bd9Sstevel@tonic-gate 
1532*7c478bd9Sstevel@tonic-gate 		/*
1533*7c478bd9Sstevel@tonic-gate 		 * Parse the first token: try to find 'b', 'c', 'e'
1534*7c478bd9Sstevel@tonic-gate 		 * or 'm'
1535*7c478bd9Sstevel@tonic-gate 		 */
1536*7c478bd9Sstevel@tonic-gate 		s = cleantoken;
1537*7c478bd9Sstevel@tonic-gate 		while (*s && (isdigit(*s) || (*s == '.') || (*s == '$'))) {
1538*7c478bd9Sstevel@tonic-gate 			s++;
1539*7c478bd9Sstevel@tonic-gate 		}
1540*7c478bd9Sstevel@tonic-gate 
1541*7c478bd9Sstevel@tonic-gate 		/*
1542*7c478bd9Sstevel@tonic-gate 		 * If we found a conversion specifier, second token is
1543*7c478bd9Sstevel@tonic-gate 		 * unused Otherwise, the second token should supply it.
1544*7c478bd9Sstevel@tonic-gate 		 */
1545*7c478bd9Sstevel@tonic-gate 		if (*s != 0) {
1546*7c478bd9Sstevel@tonic-gate 			value = *s;
1547*7c478bd9Sstevel@tonic-gate 			*s = 0;
1548*7c478bd9Sstevel@tonic-gate 		} else {
1549*7c478bd9Sstevel@tonic-gate 			value = cleantoken2[0];
1550*7c478bd9Sstevel@tonic-gate 		}
1551*7c478bd9Sstevel@tonic-gate 
1552*7c478bd9Sstevel@tonic-gate 		/*
1553*7c478bd9Sstevel@tonic-gate 		 * If the token is the wild card, simply supply the max
1554*7c478bd9Sstevel@tonic-gate 		 * This order allows the user to specify the maximum in
1555*7c478bd9Sstevel@tonic-gate 		 * either blocks/cyls/megabytes - a convenient fiction.
1556*7c478bd9Sstevel@tonic-gate 		 */
1557*7c478bd9Sstevel@tonic-gate 		if (strcmp(cleantoken, WILD_STRING) == 0) {
1558*7c478bd9Sstevel@tonic-gate 			return (bounds->upper - EFI_MIN_RESV_SIZE -
1559*7c478bd9Sstevel@tonic-gate 			    efi_deflt->start_sector);
1560*7c478bd9Sstevel@tonic-gate 		}
1561*7c478bd9Sstevel@tonic-gate 
1562*7c478bd9Sstevel@tonic-gate 		/*
1563*7c478bd9Sstevel@tonic-gate 		 * Allow the user to specify zero with no units,
1564*7c478bd9Sstevel@tonic-gate 		 * by just defaulting to sectors.
1565*7c478bd9Sstevel@tonic-gate 		 */
1566*7c478bd9Sstevel@tonic-gate 
1567*7c478bd9Sstevel@tonic-gate 		if (value != 'e' && strcmp(cleantoken, "0") == 0) {
1568*7c478bd9Sstevel@tonic-gate 			value = 'm';
1569*7c478bd9Sstevel@tonic-gate 		}
1570*7c478bd9Sstevel@tonic-gate 
1571*7c478bd9Sstevel@tonic-gate 
1572*7c478bd9Sstevel@tonic-gate 		/*
1573*7c478bd9Sstevel@tonic-gate 		 * If there's a decimal point, but no unit
1574*7c478bd9Sstevel@tonic-gate 		 * specification, let's assume megabytes.
1575*7c478bd9Sstevel@tonic-gate 		 */
1576*7c478bd9Sstevel@tonic-gate 		if ((value == 0) && (strchr(cleantoken, '.') != NULL)) {
1577*7c478bd9Sstevel@tonic-gate 			value = 'm';
1578*7c478bd9Sstevel@tonic-gate 		}
1579*7c478bd9Sstevel@tonic-gate 
1580*7c478bd9Sstevel@tonic-gate 		/*
1581*7c478bd9Sstevel@tonic-gate 		 * Handle each unit type we support
1582*7c478bd9Sstevel@tonic-gate 		 */
1583*7c478bd9Sstevel@tonic-gate 		switch (value) {
1584*7c478bd9Sstevel@tonic-gate 		case 'b':
1585*7c478bd9Sstevel@tonic-gate 			/*
1586*7c478bd9Sstevel@tonic-gate 			 * Token is number of blocks
1587*7c478bd9Sstevel@tonic-gate 			 */
1588*7c478bd9Sstevel@tonic-gate 			if (geti64(cleantoken, &blokno, (uint64_t *)NULL)) {
1589*7c478bd9Sstevel@tonic-gate 			    break;
1590*7c478bd9Sstevel@tonic-gate 			}
1591*7c478bd9Sstevel@tonic-gate 			if (blokno > bounds->upper) {
1592*7c478bd9Sstevel@tonic-gate 			    err_print(
1593*7c478bd9Sstevel@tonic-gate "Number of blocks must be less that the total available blocks.\n");
1594*7c478bd9Sstevel@tonic-gate 			    break;
1595*7c478bd9Sstevel@tonic-gate 			}
1596*7c478bd9Sstevel@tonic-gate 			return (blokno);
1597*7c478bd9Sstevel@tonic-gate 
1598*7c478bd9Sstevel@tonic-gate 		case 'e':
1599*7c478bd9Sstevel@tonic-gate 			/*
1600*7c478bd9Sstevel@tonic-gate 			 * Token is ending block number
1601*7c478bd9Sstevel@tonic-gate 			 */
1602*7c478bd9Sstevel@tonic-gate 
1603*7c478bd9Sstevel@tonic-gate 			/* convert token to integer */
1604*7c478bd9Sstevel@tonic-gate 			if (geti64(cleantoken, &blokno, (uint64_t *)NULL)) {
1605*7c478bd9Sstevel@tonic-gate 				break;
1606*7c478bd9Sstevel@tonic-gate 			}
1607*7c478bd9Sstevel@tonic-gate 
1608*7c478bd9Sstevel@tonic-gate 			/*
1609*7c478bd9Sstevel@tonic-gate 			 * Some sanity check
1610*7c478bd9Sstevel@tonic-gate 			 */
1611*7c478bd9Sstevel@tonic-gate 			if (blokno < efi_deflt->start_sector) {
1612*7c478bd9Sstevel@tonic-gate 				err_print(
1613*7c478bd9Sstevel@tonic-gate "End Sector must fall on or after start sector %llu\n",
1614*7c478bd9Sstevel@tonic-gate 				    efi_deflt->start_sector);
1615*7c478bd9Sstevel@tonic-gate 				break;
1616*7c478bd9Sstevel@tonic-gate 			}
1617*7c478bd9Sstevel@tonic-gate 
1618*7c478bd9Sstevel@tonic-gate 			/*
1619*7c478bd9Sstevel@tonic-gate 			 * verify that our input is within range
1620*7c478bd9Sstevel@tonic-gate 			 */
1621*7c478bd9Sstevel@tonic-gate 			if (blokno > cur_parts->etoc->efi_last_u_lba) {
1622*7c478bd9Sstevel@tonic-gate 				err_print(
1623*7c478bd9Sstevel@tonic-gate "End Sector %llu is beyond max Sector %llu\n",
1624*7c478bd9Sstevel@tonic-gate 				    blokno, cur_parts->etoc->efi_last_u_lba);
1625*7c478bd9Sstevel@tonic-gate 				break;
1626*7c478bd9Sstevel@tonic-gate 			}
1627*7c478bd9Sstevel@tonic-gate 
1628*7c478bd9Sstevel@tonic-gate 			/*
1629*7c478bd9Sstevel@tonic-gate 			 * calculate number of blocks based on input
1630*7c478bd9Sstevel@tonic-gate 			 */
1631*7c478bd9Sstevel@tonic-gate 
1632*7c478bd9Sstevel@tonic-gate 			return (blokno - efi_deflt->start_sector + 1);
1633*7c478bd9Sstevel@tonic-gate 
1634*7c478bd9Sstevel@tonic-gate 		case 'm':
1635*7c478bd9Sstevel@tonic-gate 			/*
1636*7c478bd9Sstevel@tonic-gate 			 * Convert token from megabytes to a
1637*7c478bd9Sstevel@tonic-gate 			 * block number.
1638*7c478bd9Sstevel@tonic-gate 			 */
1639*7c478bd9Sstevel@tonic-gate 			if (sscanf(cleantoken, "%f2", &nmegs) == 0) {
1640*7c478bd9Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
1641*7c478bd9Sstevel@tonic-gate 				    cleantoken);
1642*7c478bd9Sstevel@tonic-gate 				break;
1643*7c478bd9Sstevel@tonic-gate 			}
1644*7c478bd9Sstevel@tonic-gate 
1645*7c478bd9Sstevel@tonic-gate 			/*
1646*7c478bd9Sstevel@tonic-gate 			 * Check the bounds
1647*7c478bd9Sstevel@tonic-gate 			 */
1648*7c478bd9Sstevel@tonic-gate 			if (nmegs > bn2mb(bounds->upper - bounds->lower)) {
1649*7c478bd9Sstevel@tonic-gate 				err_print("`%1.2fmb' is out of range\n", nmegs);
1650*7c478bd9Sstevel@tonic-gate 				break;
1651*7c478bd9Sstevel@tonic-gate 			}
1652*7c478bd9Sstevel@tonic-gate 
1653*7c478bd9Sstevel@tonic-gate 			return (mb2bn(nmegs));
1654*7c478bd9Sstevel@tonic-gate 
1655*7c478bd9Sstevel@tonic-gate 		case 'g':
1656*7c478bd9Sstevel@tonic-gate 			if (sscanf(cleantoken, "%f2", &nmegs) == 0) {
1657*7c478bd9Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
1658*7c478bd9Sstevel@tonic-gate 				    cleantoken);
1659*7c478bd9Sstevel@tonic-gate 				break;
1660*7c478bd9Sstevel@tonic-gate 			}
1661*7c478bd9Sstevel@tonic-gate 			if (nmegs > bn2gb(bounds->upper - bounds->lower)) {
1662*7c478bd9Sstevel@tonic-gate 				err_print("`%1.2fgb' is out of range\n", nmegs);
1663*7c478bd9Sstevel@tonic-gate 				break;
1664*7c478bd9Sstevel@tonic-gate 			}
1665*7c478bd9Sstevel@tonic-gate 
1666*7c478bd9Sstevel@tonic-gate 			return (gb2bn(nmegs));
1667*7c478bd9Sstevel@tonic-gate 
1668*7c478bd9Sstevel@tonic-gate 		case 't':
1669*7c478bd9Sstevel@tonic-gate 			if (sscanf(cleantoken, "%f2", &nmegs) == 0) {
1670*7c478bd9Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
1671*7c478bd9Sstevel@tonic-gate 				    cleantoken);
1672*7c478bd9Sstevel@tonic-gate 				break;
1673*7c478bd9Sstevel@tonic-gate 			}
1674*7c478bd9Sstevel@tonic-gate 			if (nmegs > bn2tb(bounds->upper - bounds->lower)) {
1675*7c478bd9Sstevel@tonic-gate 				err_print("`%1.2ftb' is out of range\n", nmegs);
1676*7c478bd9Sstevel@tonic-gate 				break;
1677*7c478bd9Sstevel@tonic-gate 			}
1678*7c478bd9Sstevel@tonic-gate 			return (uint64_t)((float)nmegs * 1024.0 *
1679*7c478bd9Sstevel@tonic-gate 				1024.0 * 1024.0 * 1024.0 / DEV_BSIZE);
1680*7c478bd9Sstevel@tonic-gate 
1681*7c478bd9Sstevel@tonic-gate 		default:
1682*7c478bd9Sstevel@tonic-gate 			err_print(
1683*7c478bd9Sstevel@tonic-gate "Please specify units in either b(number of blocks), e(end sector),\n");
1684*7c478bd9Sstevel@tonic-gate 			err_print(" g(gigabytes), m(megabytes)");
1685*7c478bd9Sstevel@tonic-gate 			err_print(" or t(terabytes)\n");
1686*7c478bd9Sstevel@tonic-gate 			break;
1687*7c478bd9Sstevel@tonic-gate 		}
1688*7c478bd9Sstevel@tonic-gate 		break;
1689*7c478bd9Sstevel@tonic-gate 
1690*7c478bd9Sstevel@tonic-gate 	/*
1691*7c478bd9Sstevel@tonic-gate 	 * If we don't recognize the input type, it's bad news.
1692*7c478bd9Sstevel@tonic-gate 	 */
1693*7c478bd9Sstevel@tonic-gate 	default:
1694*7c478bd9Sstevel@tonic-gate 		err_print("Error: unknown input type.\n");
1695*7c478bd9Sstevel@tonic-gate 		fullabort();
1696*7c478bd9Sstevel@tonic-gate 	}
1697*7c478bd9Sstevel@tonic-gate 	/*
1698*7c478bd9Sstevel@tonic-gate 	 * If we get here, it's because some error kept us from accepting
1699*7c478bd9Sstevel@tonic-gate 	 * the token.  If we are running out of a command file, gracefully
1700*7c478bd9Sstevel@tonic-gate 	 * leave the program.  If we are interacting with the user, simply
1701*7c478bd9Sstevel@tonic-gate 	 * reprompt.  If the token was in the pipe, abort the current command.
1702*7c478bd9Sstevel@tonic-gate 	 */
1703*7c478bd9Sstevel@tonic-gate 	if (option_f)
1704*7c478bd9Sstevel@tonic-gate 		fullabort();
1705*7c478bd9Sstevel@tonic-gate 	else if (interactive)
1706*7c478bd9Sstevel@tonic-gate 		goto reprompt;
1707*7c478bd9Sstevel@tonic-gate 	else
1708*7c478bd9Sstevel@tonic-gate 		cmdabort(SIGINT);
1709*7c478bd9Sstevel@tonic-gate 	/*
1710*7c478bd9Sstevel@tonic-gate 	 * Never actually reached.
1711*7c478bd9Sstevel@tonic-gate 	 */
1712*7c478bd9Sstevel@tonic-gate 	return (-1);
1713*7c478bd9Sstevel@tonic-gate }
1714*7c478bd9Sstevel@tonic-gate 
1715*7c478bd9Sstevel@tonic-gate /*
1716*7c478bd9Sstevel@tonic-gate  * Print input choices
1717*7c478bd9Sstevel@tonic-gate  */
1718*7c478bd9Sstevel@tonic-gate static void
1719*7c478bd9Sstevel@tonic-gate print_input_choices(type, param)
1720*7c478bd9Sstevel@tonic-gate 	int		type;
1721*7c478bd9Sstevel@tonic-gate 	u_ioparam_t	*param;
1722*7c478bd9Sstevel@tonic-gate {
1723*7c478bd9Sstevel@tonic-gate 	char		**sp;
1724*7c478bd9Sstevel@tonic-gate 	slist_t		*lp;
1725*7c478bd9Sstevel@tonic-gate 	int		width;
1726*7c478bd9Sstevel@tonic-gate 	int		col;
1727*7c478bd9Sstevel@tonic-gate 	int		ncols;
1728*7c478bd9Sstevel@tonic-gate 
1729*7c478bd9Sstevel@tonic-gate 	switch (type) {
1730*7c478bd9Sstevel@tonic-gate 	case FIO_CSTR:
1731*7c478bd9Sstevel@tonic-gate 		fmt_print("Expecting one of the following:\n");
1732*7c478bd9Sstevel@tonic-gate 		goto common;
1733*7c478bd9Sstevel@tonic-gate 
1734*7c478bd9Sstevel@tonic-gate 	case FIO_MSTR:
1735*7c478bd9Sstevel@tonic-gate 		fmt_print("Expecting one of the following: ");
1736*7c478bd9Sstevel@tonic-gate 		fmt_print("(abbreviations ok):\n");
1737*7c478bd9Sstevel@tonic-gate common:
1738*7c478bd9Sstevel@tonic-gate 		for (sp = (char **)param->io_charlist; *sp != NULL; sp++) {
1739*7c478bd9Sstevel@tonic-gate 			fmt_print("\t%s\n", *sp);
1740*7c478bd9Sstevel@tonic-gate 		}
1741*7c478bd9Sstevel@tonic-gate 		break;
1742*7c478bd9Sstevel@tonic-gate 
1743*7c478bd9Sstevel@tonic-gate 	case FIO_SLIST:
1744*7c478bd9Sstevel@tonic-gate 		fmt_print("Expecting one of the following: ");
1745*7c478bd9Sstevel@tonic-gate 		fmt_print("(abbreviations ok):\n");
1746*7c478bd9Sstevel@tonic-gate 		/*
1747*7c478bd9Sstevel@tonic-gate 		 * Figure out the width of the widest string
1748*7c478bd9Sstevel@tonic-gate 		 */
1749*7c478bd9Sstevel@tonic-gate 		width = slist_widest_str((slist_t *)param->io_slist);
1750*7c478bd9Sstevel@tonic-gate 		width += 4;
1751*7c478bd9Sstevel@tonic-gate 		/*
1752*7c478bd9Sstevel@tonic-gate 		 * If the help messages are empty, print the
1753*7c478bd9Sstevel@tonic-gate 		 * possible choices in left-justified columns
1754*7c478bd9Sstevel@tonic-gate 		 */
1755*7c478bd9Sstevel@tonic-gate 		lp = (slist_t *)param->io_slist;
1756*7c478bd9Sstevel@tonic-gate 		if (*lp->help == 0) {
1757*7c478bd9Sstevel@tonic-gate 			col = 0;
1758*7c478bd9Sstevel@tonic-gate 			ncols = 60 / width;
1759*7c478bd9Sstevel@tonic-gate 			for (; lp->str != NULL; lp++) {
1760*7c478bd9Sstevel@tonic-gate 				if (col == 0)
1761*7c478bd9Sstevel@tonic-gate 					fmt_print("\t");
1762*7c478bd9Sstevel@tonic-gate 				ljust_print(lp->str,
1763*7c478bd9Sstevel@tonic-gate 				    (++col == ncols) ? 0 : width);
1764*7c478bd9Sstevel@tonic-gate 				if (col == ncols) {
1765*7c478bd9Sstevel@tonic-gate 					col = 0;
1766*7c478bd9Sstevel@tonic-gate 					fmt_print("\n");
1767*7c478bd9Sstevel@tonic-gate 				}
1768*7c478bd9Sstevel@tonic-gate 			}
1769*7c478bd9Sstevel@tonic-gate 			if (col != 0)
1770*7c478bd9Sstevel@tonic-gate 				fmt_print("\n");
1771*7c478bd9Sstevel@tonic-gate 		} else {
1772*7c478bd9Sstevel@tonic-gate 			/*
1773*7c478bd9Sstevel@tonic-gate 			 * With help messages, print each choice,
1774*7c478bd9Sstevel@tonic-gate 			 * and help message, on its own line.
1775*7c478bd9Sstevel@tonic-gate 			 */
1776*7c478bd9Sstevel@tonic-gate 			for (; lp->str != NULL; lp++) {
1777*7c478bd9Sstevel@tonic-gate 				fmt_print("\t");
1778*7c478bd9Sstevel@tonic-gate 				ljust_print(lp->str, width);
1779*7c478bd9Sstevel@tonic-gate 				fmt_print("- %s\n", lp->help);
1780*7c478bd9Sstevel@tonic-gate 			}
1781*7c478bd9Sstevel@tonic-gate 		}
1782*7c478bd9Sstevel@tonic-gate 		break;
1783*7c478bd9Sstevel@tonic-gate 
1784*7c478bd9Sstevel@tonic-gate 	default:
1785*7c478bd9Sstevel@tonic-gate 		err_print("Error: unknown input type.\n");
1786*7c478bd9Sstevel@tonic-gate 		fullabort();
1787*7c478bd9Sstevel@tonic-gate 	}
1788*7c478bd9Sstevel@tonic-gate 
1789*7c478bd9Sstevel@tonic-gate 	fmt_print("\n");
1790*7c478bd9Sstevel@tonic-gate }
1791*7c478bd9Sstevel@tonic-gate 
1792*7c478bd9Sstevel@tonic-gate 
1793*7c478bd9Sstevel@tonic-gate /*
1794*7c478bd9Sstevel@tonic-gate  * Search a string list for a particular string.
1795*7c478bd9Sstevel@tonic-gate  * Use minimum recognition, to accept unique abbreviations
1796*7c478bd9Sstevel@tonic-gate  * Return the number of possible matches found.
1797*7c478bd9Sstevel@tonic-gate  * If only one match was found, return the arbitrary value
1798*7c478bd9Sstevel@tonic-gate  * associated with the matched string in match_value.
1799*7c478bd9Sstevel@tonic-gate  */
1800*7c478bd9Sstevel@tonic-gate int
1801*7c478bd9Sstevel@tonic-gate find_value(slist, match_str, match_value)
1802*7c478bd9Sstevel@tonic-gate 	slist_t		*slist;
1803*7c478bd9Sstevel@tonic-gate 	char		*match_str;
1804*7c478bd9Sstevel@tonic-gate 	int		*match_value;
1805*7c478bd9Sstevel@tonic-gate {
1806*7c478bd9Sstevel@tonic-gate 	int		i;
1807*7c478bd9Sstevel@tonic-gate 	int		nmatches;
1808*7c478bd9Sstevel@tonic-gate 	int		length;
1809*7c478bd9Sstevel@tonic-gate 	int		match_length;
1810*7c478bd9Sstevel@tonic-gate 
1811*7c478bd9Sstevel@tonic-gate 	nmatches = 0;
1812*7c478bd9Sstevel@tonic-gate 	length = 0;
1813*7c478bd9Sstevel@tonic-gate 
1814*7c478bd9Sstevel@tonic-gate 	match_length = strlen(match_str);
1815*7c478bd9Sstevel@tonic-gate 
1816*7c478bd9Sstevel@tonic-gate 	for (; slist->str != NULL; slist++) {
1817*7c478bd9Sstevel@tonic-gate 		/*
1818*7c478bd9Sstevel@tonic-gate 		 * See how many characters of the token match
1819*7c478bd9Sstevel@tonic-gate 		 */
1820*7c478bd9Sstevel@tonic-gate 		i = strcnt(match_str, slist->str);
1821*7c478bd9Sstevel@tonic-gate 		/*
1822*7c478bd9Sstevel@tonic-gate 		 * If it's not the whole token, then it's not a match.
1823*7c478bd9Sstevel@tonic-gate 		 */
1824*7c478bd9Sstevel@tonic-gate 		if (i  < match_length)
1825*7c478bd9Sstevel@tonic-gate 			continue;
1826*7c478bd9Sstevel@tonic-gate 		/*
1827*7c478bd9Sstevel@tonic-gate 		 * If it ties with another input, remember that.
1828*7c478bd9Sstevel@tonic-gate 		 */
1829*7c478bd9Sstevel@tonic-gate 		if (i == length)
1830*7c478bd9Sstevel@tonic-gate 			nmatches++;
1831*7c478bd9Sstevel@tonic-gate 		/*
1832*7c478bd9Sstevel@tonic-gate 		 * If it matches the most so far, record that.
1833*7c478bd9Sstevel@tonic-gate 		 */
1834*7c478bd9Sstevel@tonic-gate 		if (i > length) {
1835*7c478bd9Sstevel@tonic-gate 			*match_value = slist->value;
1836*7c478bd9Sstevel@tonic-gate 			nmatches = 1;
1837*7c478bd9Sstevel@tonic-gate 			length = i;
1838*7c478bd9Sstevel@tonic-gate 		}
1839*7c478bd9Sstevel@tonic-gate 	}
1840*7c478bd9Sstevel@tonic-gate 
1841*7c478bd9Sstevel@tonic-gate 	return (nmatches);
1842*7c478bd9Sstevel@tonic-gate }
1843*7c478bd9Sstevel@tonic-gate 
1844*7c478bd9Sstevel@tonic-gate /*
1845*7c478bd9Sstevel@tonic-gate  * Search a string list for a particular value.
1846*7c478bd9Sstevel@tonic-gate  * Return the string associated with that value.
1847*7c478bd9Sstevel@tonic-gate  */
1848*7c478bd9Sstevel@tonic-gate char *
1849*7c478bd9Sstevel@tonic-gate find_string(slist, match_value)
1850*7c478bd9Sstevel@tonic-gate 	slist_t		*slist;
1851*7c478bd9Sstevel@tonic-gate 	int		match_value;
1852*7c478bd9Sstevel@tonic-gate {
1853*7c478bd9Sstevel@tonic-gate 	for (; slist->str != NULL; slist++) {
1854*7c478bd9Sstevel@tonic-gate 		if (slist->value == match_value) {
1855*7c478bd9Sstevel@tonic-gate 			return (slist->str);
1856*7c478bd9Sstevel@tonic-gate 		}
1857*7c478bd9Sstevel@tonic-gate 	}
1858*7c478bd9Sstevel@tonic-gate 
1859*7c478bd9Sstevel@tonic-gate 	return ((char *)NULL);
1860*7c478bd9Sstevel@tonic-gate }
1861*7c478bd9Sstevel@tonic-gate 
1862*7c478bd9Sstevel@tonic-gate /*
1863*7c478bd9Sstevel@tonic-gate  * Return the width of the widest string in an slist
1864*7c478bd9Sstevel@tonic-gate  */
1865*7c478bd9Sstevel@tonic-gate static int
1866*7c478bd9Sstevel@tonic-gate slist_widest_str(slist)
1867*7c478bd9Sstevel@tonic-gate 	slist_t	*slist;
1868*7c478bd9Sstevel@tonic-gate {
1869*7c478bd9Sstevel@tonic-gate 	int	i;
1870*7c478bd9Sstevel@tonic-gate 	int	width;
1871*7c478bd9Sstevel@tonic-gate 
1872*7c478bd9Sstevel@tonic-gate 	width = 0;
1873*7c478bd9Sstevel@tonic-gate 	for (; slist->str != NULL; slist++) {
1874*7c478bd9Sstevel@tonic-gate 		if ((i = strlen(slist->str)) > width)
1875*7c478bd9Sstevel@tonic-gate 			width = i;
1876*7c478bd9Sstevel@tonic-gate 	}
1877*7c478bd9Sstevel@tonic-gate 
1878*7c478bd9Sstevel@tonic-gate 	return (width);
1879*7c478bd9Sstevel@tonic-gate }
1880*7c478bd9Sstevel@tonic-gate 
1881*7c478bd9Sstevel@tonic-gate /*
1882*7c478bd9Sstevel@tonic-gate  * Print a string left-justified to a fixed width.
1883*7c478bd9Sstevel@tonic-gate  */
1884*7c478bd9Sstevel@tonic-gate static void
1885*7c478bd9Sstevel@tonic-gate ljust_print(str, width)
1886*7c478bd9Sstevel@tonic-gate 	char	*str;
1887*7c478bd9Sstevel@tonic-gate 	int	width;
1888*7c478bd9Sstevel@tonic-gate {
1889*7c478bd9Sstevel@tonic-gate 	int	i;
1890*7c478bd9Sstevel@tonic-gate 
1891*7c478bd9Sstevel@tonic-gate 	fmt_print("%s", str);
1892*7c478bd9Sstevel@tonic-gate 	for (i = width - strlen(str); i > 0; i--) {
1893*7c478bd9Sstevel@tonic-gate 		fmt_print(" ");
1894*7c478bd9Sstevel@tonic-gate 	}
1895*7c478bd9Sstevel@tonic-gate }
1896*7c478bd9Sstevel@tonic-gate 
1897*7c478bd9Sstevel@tonic-gate /*
1898*7c478bd9Sstevel@tonic-gate  * This routine is a modified version of printf.  It handles the cases
1899*7c478bd9Sstevel@tonic-gate  * of silent mode and logging; other than that it is identical to the
1900*7c478bd9Sstevel@tonic-gate  * library version.
1901*7c478bd9Sstevel@tonic-gate  */
1902*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
1903*7c478bd9Sstevel@tonic-gate void
1904*7c478bd9Sstevel@tonic-gate fmt_print(char *format, ...)
1905*7c478bd9Sstevel@tonic-gate {
1906*7c478bd9Sstevel@tonic-gate 	va_list ap;
1907*7c478bd9Sstevel@tonic-gate 
1908*7c478bd9Sstevel@tonic-gate 	va_start(ap, format);
1909*7c478bd9Sstevel@tonic-gate 
1910*7c478bd9Sstevel@tonic-gate 	/*
1911*7c478bd9Sstevel@tonic-gate 	 * If we are running silent, skip it.
1912*7c478bd9Sstevel@tonic-gate 	 */
1913*7c478bd9Sstevel@tonic-gate 	if (option_s == 0) {
1914*7c478bd9Sstevel@tonic-gate 		/*
1915*7c478bd9Sstevel@tonic-gate 		 * Do the print to standard out.
1916*7c478bd9Sstevel@tonic-gate 		 */
1917*7c478bd9Sstevel@tonic-gate 		if (need_newline) {
1918*7c478bd9Sstevel@tonic-gate 			(void) printf("\n");
1919*7c478bd9Sstevel@tonic-gate 		}
1920*7c478bd9Sstevel@tonic-gate 		(void) vprintf(format, ap);
1921*7c478bd9Sstevel@tonic-gate 		/*
1922*7c478bd9Sstevel@tonic-gate 		 * If we are logging, also print to the log file.
1923*7c478bd9Sstevel@tonic-gate 		 */
1924*7c478bd9Sstevel@tonic-gate 		if (log_file) {
1925*7c478bd9Sstevel@tonic-gate 			if (need_newline) {
1926*7c478bd9Sstevel@tonic-gate 				(void) fprintf(log_file, "\n");
1927*7c478bd9Sstevel@tonic-gate 			}
1928*7c478bd9Sstevel@tonic-gate 			(void) vfprintf(log_file, format, ap);
1929*7c478bd9Sstevel@tonic-gate 			(void) fflush(log_file);
1930*7c478bd9Sstevel@tonic-gate 		}
1931*7c478bd9Sstevel@tonic-gate 	}
1932*7c478bd9Sstevel@tonic-gate 
1933*7c478bd9Sstevel@tonic-gate 	need_newline = 0;
1934*7c478bd9Sstevel@tonic-gate 
1935*7c478bd9Sstevel@tonic-gate 	va_end(ap);
1936*7c478bd9Sstevel@tonic-gate }
1937*7c478bd9Sstevel@tonic-gate 
1938*7c478bd9Sstevel@tonic-gate /*
1939*7c478bd9Sstevel@tonic-gate  * This routine is a modified version of printf.  It handles the cases
1940*7c478bd9Sstevel@tonic-gate  * of silent mode; other than that it is identical to the
1941*7c478bd9Sstevel@tonic-gate  * library version.  It differs from the above printf in that it does
1942*7c478bd9Sstevel@tonic-gate  * not print the message to a log file.
1943*7c478bd9Sstevel@tonic-gate  */
1944*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
1945*7c478bd9Sstevel@tonic-gate void
1946*7c478bd9Sstevel@tonic-gate nolog_print(char *format, ...)
1947*7c478bd9Sstevel@tonic-gate {
1948*7c478bd9Sstevel@tonic-gate 	va_list ap;
1949*7c478bd9Sstevel@tonic-gate 
1950*7c478bd9Sstevel@tonic-gate 	va_start(ap, format);
1951*7c478bd9Sstevel@tonic-gate 
1952*7c478bd9Sstevel@tonic-gate 	/*
1953*7c478bd9Sstevel@tonic-gate 	 * If we are running silent, skip it.
1954*7c478bd9Sstevel@tonic-gate 	 */
1955*7c478bd9Sstevel@tonic-gate 	if (option_s == 0) {
1956*7c478bd9Sstevel@tonic-gate 		/*
1957*7c478bd9Sstevel@tonic-gate 		 * Do the print to standard out.
1958*7c478bd9Sstevel@tonic-gate 		 */
1959*7c478bd9Sstevel@tonic-gate 		if (need_newline) {
1960*7c478bd9Sstevel@tonic-gate 			(void) printf("\n");
1961*7c478bd9Sstevel@tonic-gate 		}
1962*7c478bd9Sstevel@tonic-gate 		(void) vprintf(format, ap);
1963*7c478bd9Sstevel@tonic-gate 	}
1964*7c478bd9Sstevel@tonic-gate 
1965*7c478bd9Sstevel@tonic-gate 	va_end(ap);
1966*7c478bd9Sstevel@tonic-gate 
1967*7c478bd9Sstevel@tonic-gate 	need_newline = 0;
1968*7c478bd9Sstevel@tonic-gate }
1969*7c478bd9Sstevel@tonic-gate 
1970*7c478bd9Sstevel@tonic-gate /*
1971*7c478bd9Sstevel@tonic-gate  * This routine is a modified version of printf.  It handles the cases
1972*7c478bd9Sstevel@tonic-gate  * of silent mode, and only prints the message to the log file, not
1973*7c478bd9Sstevel@tonic-gate  * stdout.  Other than that is identical to the library version.
1974*7c478bd9Sstevel@tonic-gate  */
1975*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
1976*7c478bd9Sstevel@tonic-gate void
1977*7c478bd9Sstevel@tonic-gate log_print(char *format, ...)
1978*7c478bd9Sstevel@tonic-gate {
1979*7c478bd9Sstevel@tonic-gate 	va_list ap;
1980*7c478bd9Sstevel@tonic-gate 
1981*7c478bd9Sstevel@tonic-gate 	va_start(ap, format);
1982*7c478bd9Sstevel@tonic-gate 
1983*7c478bd9Sstevel@tonic-gate 	/*
1984*7c478bd9Sstevel@tonic-gate 	 * If we are running silent, skip it.
1985*7c478bd9Sstevel@tonic-gate 	 */
1986*7c478bd9Sstevel@tonic-gate 	if (option_s == 0) {
1987*7c478bd9Sstevel@tonic-gate 		/*
1988*7c478bd9Sstevel@tonic-gate 		 * Do the print to the log file.
1989*7c478bd9Sstevel@tonic-gate 		 */
1990*7c478bd9Sstevel@tonic-gate 		if (need_newline) {
1991*7c478bd9Sstevel@tonic-gate 			(void) fprintf(log_file, "\n");
1992*7c478bd9Sstevel@tonic-gate 		}
1993*7c478bd9Sstevel@tonic-gate 		(void) vfprintf(log_file, format, ap);
1994*7c478bd9Sstevel@tonic-gate 		(void) fflush(log_file);
1995*7c478bd9Sstevel@tonic-gate 	}
1996*7c478bd9Sstevel@tonic-gate 
1997*7c478bd9Sstevel@tonic-gate 	va_end(ap);
1998*7c478bd9Sstevel@tonic-gate 
1999*7c478bd9Sstevel@tonic-gate 	need_newline = 0;
2000*7c478bd9Sstevel@tonic-gate }
2001*7c478bd9Sstevel@tonic-gate 
2002*7c478bd9Sstevel@tonic-gate /*
2003*7c478bd9Sstevel@tonic-gate  * This routine is a modified version of printf.  It prints the message
2004*7c478bd9Sstevel@tonic-gate  * to stderr, and to the log file is appropriate.
2005*7c478bd9Sstevel@tonic-gate  * Other than that is identical to the library version.
2006*7c478bd9Sstevel@tonic-gate  */
2007*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
2008*7c478bd9Sstevel@tonic-gate void
2009*7c478bd9Sstevel@tonic-gate err_print(char *format, ...)
2010*7c478bd9Sstevel@tonic-gate {
2011*7c478bd9Sstevel@tonic-gate 	va_list ap;
2012*7c478bd9Sstevel@tonic-gate 
2013*7c478bd9Sstevel@tonic-gate 	va_start(ap, format);
2014*7c478bd9Sstevel@tonic-gate 
2015*7c478bd9Sstevel@tonic-gate 	/*
2016*7c478bd9Sstevel@tonic-gate 	 * Flush anything pending to stdout
2017*7c478bd9Sstevel@tonic-gate 	 */
2018*7c478bd9Sstevel@tonic-gate 	if (need_newline) {
2019*7c478bd9Sstevel@tonic-gate 		(void) printf("\n");
2020*7c478bd9Sstevel@tonic-gate 	}
2021*7c478bd9Sstevel@tonic-gate 	(void) fflush(stdout);
2022*7c478bd9Sstevel@tonic-gate 	/*
2023*7c478bd9Sstevel@tonic-gate 	 * Do the print to stderr.
2024*7c478bd9Sstevel@tonic-gate 	 */
2025*7c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, format, ap);
2026*7c478bd9Sstevel@tonic-gate 	/*
2027*7c478bd9Sstevel@tonic-gate 	 * If we are logging, also print to the log file.
2028*7c478bd9Sstevel@tonic-gate 	 */
2029*7c478bd9Sstevel@tonic-gate 	if (log_file) {
2030*7c478bd9Sstevel@tonic-gate 		if (need_newline) {
2031*7c478bd9Sstevel@tonic-gate 			(void) fprintf(log_file, "\n");
2032*7c478bd9Sstevel@tonic-gate 		}
2033*7c478bd9Sstevel@tonic-gate 		(void) vfprintf(log_file, format, ap);
2034*7c478bd9Sstevel@tonic-gate 		(void) fflush(log_file);
2035*7c478bd9Sstevel@tonic-gate 	}
2036*7c478bd9Sstevel@tonic-gate 	va_end(ap);
2037*7c478bd9Sstevel@tonic-gate 
2038*7c478bd9Sstevel@tonic-gate 	need_newline = 0;
2039*7c478bd9Sstevel@tonic-gate }
2040*7c478bd9Sstevel@tonic-gate 
2041*7c478bd9Sstevel@tonic-gate /*
2042*7c478bd9Sstevel@tonic-gate  * Print a number of characters from a buffer.  The buffer
2043*7c478bd9Sstevel@tonic-gate  * does not need to be null-terminated.  Since the data
2044*7c478bd9Sstevel@tonic-gate  * may be coming from a device, we cannot be sure the
2045*7c478bd9Sstevel@tonic-gate  * data is not crud, so be rather defensive.
2046*7c478bd9Sstevel@tonic-gate  */
2047*7c478bd9Sstevel@tonic-gate void
2048*7c478bd9Sstevel@tonic-gate print_buf(buf, nbytes)
2049*7c478bd9Sstevel@tonic-gate 	char	*buf;
2050*7c478bd9Sstevel@tonic-gate 	int	nbytes;
2051*7c478bd9Sstevel@tonic-gate {
2052*7c478bd9Sstevel@tonic-gate 	int	c;
2053*7c478bd9Sstevel@tonic-gate 
2054*7c478bd9Sstevel@tonic-gate 	while (nbytes-- > 0) {
2055*7c478bd9Sstevel@tonic-gate 		c = *buf++;
2056*7c478bd9Sstevel@tonic-gate 		if (isascii(c) && isprint(c)) {
2057*7c478bd9Sstevel@tonic-gate 			fmt_print("%c", c);
2058*7c478bd9Sstevel@tonic-gate 		} else
2059*7c478bd9Sstevel@tonic-gate 			break;
2060*7c478bd9Sstevel@tonic-gate 	}
2061*7c478bd9Sstevel@tonic-gate }
2062*7c478bd9Sstevel@tonic-gate 
2063*7c478bd9Sstevel@tonic-gate #ifdef	not
2064*7c478bd9Sstevel@tonic-gate /*
2065*7c478bd9Sstevel@tonic-gate  * This routine prints out a message describing the given ctlr.
2066*7c478bd9Sstevel@tonic-gate  * The message is identical to the one printed by the kernel during
2067*7c478bd9Sstevel@tonic-gate  * booting.
2068*7c478bd9Sstevel@tonic-gate  */
2069*7c478bd9Sstevel@tonic-gate void
2070*7c478bd9Sstevel@tonic-gate pr_ctlrline(ctlr)
2071*7c478bd9Sstevel@tonic-gate 	register struct ctlr_info *ctlr;
2072*7c478bd9Sstevel@tonic-gate {
2073*7c478bd9Sstevel@tonic-gate 
2074*7c478bd9Sstevel@tonic-gate 	fmt_print("           %s%d at %s 0x%x ",
2075*7c478bd9Sstevel@tonic-gate 		ctlr->ctlr_cname, ctlr->ctlr_num,
2076*7c478bd9Sstevel@tonic-gate 		space2str(ctlr->ctlr_space), ctlr->ctlr_addr);
2077*7c478bd9Sstevel@tonic-gate 	if (ctlr->ctlr_vec != 0)
2078*7c478bd9Sstevel@tonic-gate 		fmt_print("vec 0x%x ", ctlr->ctlr_vec);
2079*7c478bd9Sstevel@tonic-gate 	else
2080*7c478bd9Sstevel@tonic-gate 		fmt_print("pri %d ", ctlr->ctlr_prio);
2081*7c478bd9Sstevel@tonic-gate 	fmt_print("\n");
2082*7c478bd9Sstevel@tonic-gate }
2083*7c478bd9Sstevel@tonic-gate #endif /* not */
2084*7c478bd9Sstevel@tonic-gate 
2085*7c478bd9Sstevel@tonic-gate /*
2086*7c478bd9Sstevel@tonic-gate  * This routine prints out a message describing the given disk.
2087*7c478bd9Sstevel@tonic-gate  * The message is identical to the one printed by the kernel during
2088*7c478bd9Sstevel@tonic-gate  * booting.
2089*7c478bd9Sstevel@tonic-gate  */
2090*7c478bd9Sstevel@tonic-gate void
2091*7c478bd9Sstevel@tonic-gate pr_diskline(disk, num)
2092*7c478bd9Sstevel@tonic-gate 	register struct disk_info *disk;
2093*7c478bd9Sstevel@tonic-gate 	int	num;
2094*7c478bd9Sstevel@tonic-gate {
2095*7c478bd9Sstevel@tonic-gate 	struct	ctlr_info *ctlr = disk->disk_ctlr;
2096*7c478bd9Sstevel@tonic-gate 	struct	disk_type *type = disk->disk_type;
2097*7c478bd9Sstevel@tonic-gate 
2098*7c478bd9Sstevel@tonic-gate 	fmt_print("    %4d. %s ", num, disk->disk_name);
2099*7c478bd9Sstevel@tonic-gate 	if ((type != NULL) && (disk->label_type == L_TYPE_SOLARIS)) {
2100*7c478bd9Sstevel@tonic-gate 		fmt_print("<%s cyl %d alt %d hd %d sec %d>",
2101*7c478bd9Sstevel@tonic-gate 			type->dtype_asciilabel, type->dtype_ncyl,
2102*7c478bd9Sstevel@tonic-gate 			type->dtype_acyl, type->dtype_nhead,
2103*7c478bd9Sstevel@tonic-gate 			type->dtype_nsect);
2104*7c478bd9Sstevel@tonic-gate 	} else if ((type != NULL) && (disk->label_type == L_TYPE_EFI)) {
2105*7c478bd9Sstevel@tonic-gate 		print_efi_string(type->vendor, type->product,
2106*7c478bd9Sstevel@tonic-gate 			type->revision, type->capacity);
2107*7c478bd9Sstevel@tonic-gate 	} else if (disk->disk_flags & DSK_RESERVED) {
2108*7c478bd9Sstevel@tonic-gate 		fmt_print("<drive not available: reserved>");
2109*7c478bd9Sstevel@tonic-gate 	} else if (disk->disk_flags & DSK_UNAVAILABLE) {
2110*7c478bd9Sstevel@tonic-gate 		fmt_print("<drive not available>");
2111*7c478bd9Sstevel@tonic-gate 	} else {
2112*7c478bd9Sstevel@tonic-gate 		fmt_print("<drive type unknown>");
2113*7c478bd9Sstevel@tonic-gate 	}
2114*7c478bd9Sstevel@tonic-gate 	if (chk_volname(disk)) {
2115*7c478bd9Sstevel@tonic-gate 		fmt_print("  ");
2116*7c478bd9Sstevel@tonic-gate 		print_volname(disk);
2117*7c478bd9Sstevel@tonic-gate 	}
2118*7c478bd9Sstevel@tonic-gate 	fmt_print("\n");
2119*7c478bd9Sstevel@tonic-gate 
2120*7c478bd9Sstevel@tonic-gate 	if (disk->devfs_name != NULL) {
2121*7c478bd9Sstevel@tonic-gate 		fmt_print("          %s\n", disk->devfs_name);
2122*7c478bd9Sstevel@tonic-gate 	} else {
2123*7c478bd9Sstevel@tonic-gate 		fmt_print("          %s%d at %s%d slave %d\n",
2124*7c478bd9Sstevel@tonic-gate 			ctlr->ctlr_dname, disk->disk_dkinfo.dki_unit,
2125*7c478bd9Sstevel@tonic-gate 			ctlr->ctlr_cname, ctlr->ctlr_num,
2126*7c478bd9Sstevel@tonic-gate 			disk->disk_dkinfo.dki_slave);
2127*7c478bd9Sstevel@tonic-gate 	}
2128*7c478bd9Sstevel@tonic-gate 
2129*7c478bd9Sstevel@tonic-gate #ifdef	OLD
2130*7c478bd9Sstevel@tonic-gate 	fmt_print("    %4d. %s at %s%d slave %d", num, disk->disk_name,
2131*7c478bd9Sstevel@tonic-gate 	    ctlr->ctlr_cname, ctlr->ctlr_num, disk->disk_dkinfo.dki_slave);
2132*7c478bd9Sstevel@tonic-gate 	if (chk_volname(disk)) {
2133*7c478bd9Sstevel@tonic-gate 		fmt_print(": ");
2134*7c478bd9Sstevel@tonic-gate 		print_volname(disk);
2135*7c478bd9Sstevel@tonic-gate 	}
2136*7c478bd9Sstevel@tonic-gate 	fmt_print("\n");
2137*7c478bd9Sstevel@tonic-gate 	if (type != NULL) {
2138*7c478bd9Sstevel@tonic-gate 		fmt_print(
2139*7c478bd9Sstevel@tonic-gate "           %s%d: <%s cyl %d alt %d hd %d sec %d>\n",
2140*7c478bd9Sstevel@tonic-gate 		    ctlr->ctlr_dname, disk->disk_dkinfo.dki_unit,
2141*7c478bd9Sstevel@tonic-gate 		    type->dtype_asciilabel, type->dtype_ncyl,
2142*7c478bd9Sstevel@tonic-gate 		    type->dtype_acyl, type->dtype_nhead,
2143*7c478bd9Sstevel@tonic-gate 		    type->dtype_nsect);
2144*7c478bd9Sstevel@tonic-gate 	} else {
2145*7c478bd9Sstevel@tonic-gate 		fmt_print("           %s%d: <drive type unknown>\n",
2146*7c478bd9Sstevel@tonic-gate 		    ctlr->ctlr_dname, disk->disk_dkinfo.dki_unit);
2147*7c478bd9Sstevel@tonic-gate 	}
2148*7c478bd9Sstevel@tonic-gate #endif /* OLD */
2149*7c478bd9Sstevel@tonic-gate }
2150*7c478bd9Sstevel@tonic-gate 
2151*7c478bd9Sstevel@tonic-gate /*
2152*7c478bd9Sstevel@tonic-gate  * This routine prints out a given disk block number in cylinder/head/sector
2153*7c478bd9Sstevel@tonic-gate  * format.  It uses the printing routine passed in to do the actual output.
2154*7c478bd9Sstevel@tonic-gate  * Downcasting bn is okay for L_TYPE_SOLARIS because the number of blocks
2155*7c478bd9Sstevel@tonic-gate  * on a Solaris (VTOC) label will never exceed 4 bytes (daddr_t).
2156*7c478bd9Sstevel@tonic-gate  */
2157*7c478bd9Sstevel@tonic-gate void
2158*7c478bd9Sstevel@tonic-gate pr_dblock(void (*func)(char *, ...), diskaddr_t bn)
2159*7c478bd9Sstevel@tonic-gate {
2160*7c478bd9Sstevel@tonic-gate 	if (cur_label == L_TYPE_SOLARIS) {
2161*7c478bd9Sstevel@tonic-gate 	    (*func)("%d/%d/%d", bn2c((daddr_t)bn),
2162*7c478bd9Sstevel@tonic-gate 		bn2h((daddr_t)bn), bn2s((daddr_t)bn));
2163*7c478bd9Sstevel@tonic-gate 	} else {
2164*7c478bd9Sstevel@tonic-gate 	    (*func)("%llu", bn);
2165*7c478bd9Sstevel@tonic-gate 	}
2166*7c478bd9Sstevel@tonic-gate }
2167*7c478bd9Sstevel@tonic-gate 
2168*7c478bd9Sstevel@tonic-gate /*
2169*7c478bd9Sstevel@tonic-gate  * This routine inputs a character from the data file.  It understands
2170*7c478bd9Sstevel@tonic-gate  * the use of '\' to prevent interpretation of a newline.  It also keeps
2171*7c478bd9Sstevel@tonic-gate  * track of the current line in the data file via a global variable.
2172*7c478bd9Sstevel@tonic-gate  */
2173*7c478bd9Sstevel@tonic-gate static int
2174*7c478bd9Sstevel@tonic-gate sup_inputchar()
2175*7c478bd9Sstevel@tonic-gate {
2176*7c478bd9Sstevel@tonic-gate 	int	c;
2177*7c478bd9Sstevel@tonic-gate 
2178*7c478bd9Sstevel@tonic-gate 	/*
2179*7c478bd9Sstevel@tonic-gate 	 * Input the character.
2180*7c478bd9Sstevel@tonic-gate 	 */
2181*7c478bd9Sstevel@tonic-gate 	c = getc(data_file);
2182*7c478bd9Sstevel@tonic-gate 	/*
2183*7c478bd9Sstevel@tonic-gate 	 * If it's not a backslash, return it.
2184*7c478bd9Sstevel@tonic-gate 	 */
2185*7c478bd9Sstevel@tonic-gate 	if (c != '\\')
2186*7c478bd9Sstevel@tonic-gate 		return (c);
2187*7c478bd9Sstevel@tonic-gate 	/*
2188*7c478bd9Sstevel@tonic-gate 	 * It was a backslash.  Get the next character.
2189*7c478bd9Sstevel@tonic-gate 	 */
2190*7c478bd9Sstevel@tonic-gate 	c = getc(data_file);
2191*7c478bd9Sstevel@tonic-gate 	/*
2192*7c478bd9Sstevel@tonic-gate 	 * If it was a newline, update the line counter and get the next
2193*7c478bd9Sstevel@tonic-gate 	 * character.
2194*7c478bd9Sstevel@tonic-gate 	 */
2195*7c478bd9Sstevel@tonic-gate 	if (c == '\n') {
2196*7c478bd9Sstevel@tonic-gate 		data_lineno++;
2197*7c478bd9Sstevel@tonic-gate 		c = getc(data_file);
2198*7c478bd9Sstevel@tonic-gate 	}
2199*7c478bd9Sstevel@tonic-gate 	/*
2200*7c478bd9Sstevel@tonic-gate 	 * Return the character.
2201*7c478bd9Sstevel@tonic-gate 	 */
2202*7c478bd9Sstevel@tonic-gate 	return (c);
2203*7c478bd9Sstevel@tonic-gate }
2204*7c478bd9Sstevel@tonic-gate 
2205*7c478bd9Sstevel@tonic-gate /*
2206*7c478bd9Sstevel@tonic-gate  * This routine pushes a character back onto the input pipe for the data file.
2207*7c478bd9Sstevel@tonic-gate  */
2208*7c478bd9Sstevel@tonic-gate static void
2209*7c478bd9Sstevel@tonic-gate sup_pushchar(c)
2210*7c478bd9Sstevel@tonic-gate 	int	c;
2211*7c478bd9Sstevel@tonic-gate {
2212*7c478bd9Sstevel@tonic-gate 	(void) ungetc(c, data_file);
2213*7c478bd9Sstevel@tonic-gate }
2214*7c478bd9Sstevel@tonic-gate 
2215*7c478bd9Sstevel@tonic-gate /*
2216*7c478bd9Sstevel@tonic-gate  * Variables to support pushing back tokens
2217*7c478bd9Sstevel@tonic-gate  */
2218*7c478bd9Sstevel@tonic-gate static  int	have_pushed_token = 0;
2219*7c478bd9Sstevel@tonic-gate static  TOKEN	pushed_buf;
2220*7c478bd9Sstevel@tonic-gate static  int	pushed_token;
2221*7c478bd9Sstevel@tonic-gate 
2222*7c478bd9Sstevel@tonic-gate /*
2223*7c478bd9Sstevel@tonic-gate  * This routine inputs a token from the data file.  A token is a series
2224*7c478bd9Sstevel@tonic-gate  * of contiguous non-white characters or a recognized special delimiter
2225*7c478bd9Sstevel@tonic-gate  * character.  Use of the wrapper lets us always have the value of the
2226*7c478bd9Sstevel@tonic-gate  * last token around, which is useful for error recovery.
2227*7c478bd9Sstevel@tonic-gate  */
2228*7c478bd9Sstevel@tonic-gate int
2229*7c478bd9Sstevel@tonic-gate sup_gettoken(buf)
2230*7c478bd9Sstevel@tonic-gate 	char	*buf;
2231*7c478bd9Sstevel@tonic-gate {
2232*7c478bd9Sstevel@tonic-gate 	last_token_type = sup_get_token(buf);
2233*7c478bd9Sstevel@tonic-gate 	return (last_token_type);
2234*7c478bd9Sstevel@tonic-gate }
2235*7c478bd9Sstevel@tonic-gate 
2236*7c478bd9Sstevel@tonic-gate static int
2237*7c478bd9Sstevel@tonic-gate sup_get_token(buf)
2238*7c478bd9Sstevel@tonic-gate 	char	*buf;
2239*7c478bd9Sstevel@tonic-gate {
2240*7c478bd9Sstevel@tonic-gate 	char	*ptr = buf;
2241*7c478bd9Sstevel@tonic-gate 	int	c, quoted = 0;
2242*7c478bd9Sstevel@tonic-gate 
2243*7c478bd9Sstevel@tonic-gate 	/*
2244*7c478bd9Sstevel@tonic-gate 	 * First check for presence of push-backed token.
2245*7c478bd9Sstevel@tonic-gate 	 * If so, return it.
2246*7c478bd9Sstevel@tonic-gate 	 */
2247*7c478bd9Sstevel@tonic-gate 	if (have_pushed_token) {
2248*7c478bd9Sstevel@tonic-gate 		have_pushed_token = 0;
2249*7c478bd9Sstevel@tonic-gate 		bcopy(pushed_buf, buf, TOKEN_SIZE+1);
2250*7c478bd9Sstevel@tonic-gate 		return (pushed_token);
2251*7c478bd9Sstevel@tonic-gate 	}
2252*7c478bd9Sstevel@tonic-gate 	/*
2253*7c478bd9Sstevel@tonic-gate 	 * Zero out the returned token buffer
2254*7c478bd9Sstevel@tonic-gate 	 */
2255*7c478bd9Sstevel@tonic-gate 	bzero(buf, TOKEN_SIZE + 1);
2256*7c478bd9Sstevel@tonic-gate 	/*
2257*7c478bd9Sstevel@tonic-gate 	 * Strip off leading white-space.
2258*7c478bd9Sstevel@tonic-gate 	 */
2259*7c478bd9Sstevel@tonic-gate 	while ((isspace(c = sup_inputchar())) && (c != '\n'))
2260*7c478bd9Sstevel@tonic-gate 		;
2261*7c478bd9Sstevel@tonic-gate 	/*
2262*7c478bd9Sstevel@tonic-gate 	 * Read in characters until we hit unquoted white-space.
2263*7c478bd9Sstevel@tonic-gate 	 */
2264*7c478bd9Sstevel@tonic-gate 	for (; !isspace(c) || quoted; c = sup_inputchar()) {
2265*7c478bd9Sstevel@tonic-gate 		/*
2266*7c478bd9Sstevel@tonic-gate 		 * If we hit eof, that's a token.
2267*7c478bd9Sstevel@tonic-gate 		 */
2268*7c478bd9Sstevel@tonic-gate 		if (feof(data_file))
2269*7c478bd9Sstevel@tonic-gate 			return (SUP_EOF);
2270*7c478bd9Sstevel@tonic-gate 		/*
2271*7c478bd9Sstevel@tonic-gate 		 * If we hit a double quote, change the state of quoting.
2272*7c478bd9Sstevel@tonic-gate 		 */
2273*7c478bd9Sstevel@tonic-gate 		if (c == '"') {
2274*7c478bd9Sstevel@tonic-gate 			quoted = !quoted;
2275*7c478bd9Sstevel@tonic-gate 			continue;
2276*7c478bd9Sstevel@tonic-gate 		}
2277*7c478bd9Sstevel@tonic-gate 		/*
2278*7c478bd9Sstevel@tonic-gate 		 * If we hit a newline, that delimits a token.
2279*7c478bd9Sstevel@tonic-gate 		 */
2280*7c478bd9Sstevel@tonic-gate 		if (c == '\n')
2281*7c478bd9Sstevel@tonic-gate 			break;
2282*7c478bd9Sstevel@tonic-gate 		/*
2283*7c478bd9Sstevel@tonic-gate 		 * If we hit any nonquoted special delimiters, that delimits
2284*7c478bd9Sstevel@tonic-gate 		 * a token.
2285*7c478bd9Sstevel@tonic-gate 		 */
2286*7c478bd9Sstevel@tonic-gate 		if (!quoted && (c == '=' || c == ',' || c == ':' ||
2287*7c478bd9Sstevel@tonic-gate 			c == '#' || c == '|' || c == '&' || c == '~'))
2288*7c478bd9Sstevel@tonic-gate 			break;
2289*7c478bd9Sstevel@tonic-gate 		/*
2290*7c478bd9Sstevel@tonic-gate 		 * Store the character if there's room left.
2291*7c478bd9Sstevel@tonic-gate 		 */
2292*7c478bd9Sstevel@tonic-gate 		if (ptr - buf < TOKEN_SIZE)
2293*7c478bd9Sstevel@tonic-gate 			*ptr++ = (char)c;
2294*7c478bd9Sstevel@tonic-gate 	}
2295*7c478bd9Sstevel@tonic-gate 	/*
2296*7c478bd9Sstevel@tonic-gate 	 * If we stored characters in the buffer, then we inputted a string.
2297*7c478bd9Sstevel@tonic-gate 	 * Push the delimiter back into the pipe and return the string.
2298*7c478bd9Sstevel@tonic-gate 	 */
2299*7c478bd9Sstevel@tonic-gate 	if (ptr - buf > 0) {
2300*7c478bd9Sstevel@tonic-gate 		sup_pushchar(c);
2301*7c478bd9Sstevel@tonic-gate 		return (SUP_STRING);
2302*7c478bd9Sstevel@tonic-gate 	}
2303*7c478bd9Sstevel@tonic-gate 	/*
2304*7c478bd9Sstevel@tonic-gate 	 * We didn't input a string, so we must have inputted a known delimiter.
2305*7c478bd9Sstevel@tonic-gate 	 * store the delimiter in the buffer, so it will get returned.
2306*7c478bd9Sstevel@tonic-gate 	 */
2307*7c478bd9Sstevel@tonic-gate 	buf[0] = c;
2308*7c478bd9Sstevel@tonic-gate 	/*
2309*7c478bd9Sstevel@tonic-gate 	 * Switch on the delimiter.  Return the appropriate value for each one.
2310*7c478bd9Sstevel@tonic-gate 	 */
2311*7c478bd9Sstevel@tonic-gate 	switch (c) {
2312*7c478bd9Sstevel@tonic-gate 	case '=':
2313*7c478bd9Sstevel@tonic-gate 		return (SUP_EQL);
2314*7c478bd9Sstevel@tonic-gate 	case ':':
2315*7c478bd9Sstevel@tonic-gate 		return (SUP_COLON);
2316*7c478bd9Sstevel@tonic-gate 	case ',':
2317*7c478bd9Sstevel@tonic-gate 		return (SUP_COMMA);
2318*7c478bd9Sstevel@tonic-gate 	case '\n':
2319*7c478bd9Sstevel@tonic-gate 		return (SUP_EOL);
2320*7c478bd9Sstevel@tonic-gate 	case '|':
2321*7c478bd9Sstevel@tonic-gate 		return (SUP_OR);
2322*7c478bd9Sstevel@tonic-gate 	case '&':
2323*7c478bd9Sstevel@tonic-gate 		return (SUP_AND);
2324*7c478bd9Sstevel@tonic-gate 	case '~':
2325*7c478bd9Sstevel@tonic-gate 		return (SUP_TILDE);
2326*7c478bd9Sstevel@tonic-gate 	case '#':
2327*7c478bd9Sstevel@tonic-gate 		/*
2328*7c478bd9Sstevel@tonic-gate 		 * For comments, we flush out the rest of the line and return
2329*7c478bd9Sstevel@tonic-gate 		 * an EOL.
2330*7c478bd9Sstevel@tonic-gate 		 */
2331*7c478bd9Sstevel@tonic-gate 		while ((c = sup_inputchar()) != '\n' && !feof(data_file))
2332*7c478bd9Sstevel@tonic-gate 			;
2333*7c478bd9Sstevel@tonic-gate 		if (feof(data_file))
2334*7c478bd9Sstevel@tonic-gate 			return (SUP_EOF);
2335*7c478bd9Sstevel@tonic-gate 		else
2336*7c478bd9Sstevel@tonic-gate 			return (SUP_EOL);
2337*7c478bd9Sstevel@tonic-gate 	/*
2338*7c478bd9Sstevel@tonic-gate 	 * Shouldn't ever get here.
2339*7c478bd9Sstevel@tonic-gate 	 */
2340*7c478bd9Sstevel@tonic-gate 	default:
2341*7c478bd9Sstevel@tonic-gate 		return (SUP_STRING);
2342*7c478bd9Sstevel@tonic-gate 	}
2343*7c478bd9Sstevel@tonic-gate }
2344*7c478bd9Sstevel@tonic-gate 
2345*7c478bd9Sstevel@tonic-gate /*
2346*7c478bd9Sstevel@tonic-gate  * Push back a token
2347*7c478bd9Sstevel@tonic-gate  */
2348*7c478bd9Sstevel@tonic-gate void
2349*7c478bd9Sstevel@tonic-gate sup_pushtoken(token_buf, token_type)
2350*7c478bd9Sstevel@tonic-gate 	char	*token_buf;
2351*7c478bd9Sstevel@tonic-gate 	int	token_type;
2352*7c478bd9Sstevel@tonic-gate {
2353*7c478bd9Sstevel@tonic-gate 	/*
2354*7c478bd9Sstevel@tonic-gate 	 * We can only push one token back at a time
2355*7c478bd9Sstevel@tonic-gate 	 */
2356*7c478bd9Sstevel@tonic-gate 	assert(have_pushed_token == 0);
2357*7c478bd9Sstevel@tonic-gate 
2358*7c478bd9Sstevel@tonic-gate 	have_pushed_token = 1;
2359*7c478bd9Sstevel@tonic-gate 	bcopy(token_buf, pushed_buf, TOKEN_SIZE+1);
2360*7c478bd9Sstevel@tonic-gate 	pushed_token = token_type;
2361*7c478bd9Sstevel@tonic-gate }
2362*7c478bd9Sstevel@tonic-gate 
2363*7c478bd9Sstevel@tonic-gate /*
2364*7c478bd9Sstevel@tonic-gate  * Get an entire line of input.  Handles logging, comments,
2365*7c478bd9Sstevel@tonic-gate  * and EOF.
2366*7c478bd9Sstevel@tonic-gate  */
2367*7c478bd9Sstevel@tonic-gate void
2368*7c478bd9Sstevel@tonic-gate get_inputline(line, nbytes)
2369*7c478bd9Sstevel@tonic-gate 	char	*line;
2370*7c478bd9Sstevel@tonic-gate 	int	nbytes;
2371*7c478bd9Sstevel@tonic-gate {
2372*7c478bd9Sstevel@tonic-gate 	char	*p = line;
2373*7c478bd9Sstevel@tonic-gate 	int	c;
2374*7c478bd9Sstevel@tonic-gate 
2375*7c478bd9Sstevel@tonic-gate 	/*
2376*7c478bd9Sstevel@tonic-gate 	 * Remove any leading white-space and comments
2377*7c478bd9Sstevel@tonic-gate 	 */
2378*7c478bd9Sstevel@tonic-gate 	do {
2379*7c478bd9Sstevel@tonic-gate 		while ((isspace(c = getchar())) && (c != '\n'))
2380*7c478bd9Sstevel@tonic-gate 			;
2381*7c478bd9Sstevel@tonic-gate 	} while (c == COMMENT_CHAR);
2382*7c478bd9Sstevel@tonic-gate 	/*
2383*7c478bd9Sstevel@tonic-gate 	 * Loop on each character until end of line
2384*7c478bd9Sstevel@tonic-gate 	 */
2385*7c478bd9Sstevel@tonic-gate 	while (c != '\n') {
2386*7c478bd9Sstevel@tonic-gate 		/*
2387*7c478bd9Sstevel@tonic-gate 		 * If we hit eof, get out.
2388*7c478bd9Sstevel@tonic-gate 		 */
2389*7c478bd9Sstevel@tonic-gate 		if (checkeof()) {
2390*7c478bd9Sstevel@tonic-gate 			fullabort();
2391*7c478bd9Sstevel@tonic-gate 		}
2392*7c478bd9Sstevel@tonic-gate 		/*
2393*7c478bd9Sstevel@tonic-gate 		 * Add the character to the buffer.
2394*7c478bd9Sstevel@tonic-gate 		 */
2395*7c478bd9Sstevel@tonic-gate 		if (nbytes > 1) {
2396*7c478bd9Sstevel@tonic-gate 			*p++ = (char)c;
2397*7c478bd9Sstevel@tonic-gate 			nbytes --;
2398*7c478bd9Sstevel@tonic-gate 		}
2399*7c478bd9Sstevel@tonic-gate 		/*
2400*7c478bd9Sstevel@tonic-gate 		 * Get the next character.
2401*7c478bd9Sstevel@tonic-gate 		 */
2402*7c478bd9Sstevel@tonic-gate 		c = getchar();
2403*7c478bd9Sstevel@tonic-gate 	}
2404*7c478bd9Sstevel@tonic-gate 	/*
2405*7c478bd9Sstevel@tonic-gate 	 * Null terminate the token.
2406*7c478bd9Sstevel@tonic-gate 	 */
2407*7c478bd9Sstevel@tonic-gate 	*p = 0;
2408*7c478bd9Sstevel@tonic-gate 	/*
2409*7c478bd9Sstevel@tonic-gate 	 * Indicate that we've emptied the pipe
2410*7c478bd9Sstevel@tonic-gate 	 */
2411*7c478bd9Sstevel@tonic-gate 	token_present = 0;
2412*7c478bd9Sstevel@tonic-gate 	/*
2413*7c478bd9Sstevel@tonic-gate 	 * If we're running out of a file, echo the line to
2414*7c478bd9Sstevel@tonic-gate 	 * the user, otherwise if we're logging, copy the
2415*7c478bd9Sstevel@tonic-gate 	 * input to the log file.
2416*7c478bd9Sstevel@tonic-gate 	 */
2417*7c478bd9Sstevel@tonic-gate 	if (option_f) {
2418*7c478bd9Sstevel@tonic-gate 		fmt_print("%s\n", line);
2419*7c478bd9Sstevel@tonic-gate 	} else if (log_file) {
2420*7c478bd9Sstevel@tonic-gate 		log_print("%s\n", line);
2421*7c478bd9Sstevel@tonic-gate 	}
2422*7c478bd9Sstevel@tonic-gate }
2423*7c478bd9Sstevel@tonic-gate 
2424*7c478bd9Sstevel@tonic-gate /*
2425*7c478bd9Sstevel@tonic-gate  * execute the shell escape command
2426*7c478bd9Sstevel@tonic-gate  */
2427*7c478bd9Sstevel@tonic-gate int
2428*7c478bd9Sstevel@tonic-gate execute_shell(s)
2429*7c478bd9Sstevel@tonic-gate 	char	*s;
2430*7c478bd9Sstevel@tonic-gate {
2431*7c478bd9Sstevel@tonic-gate 	struct	termio	termio;
2432*7c478bd9Sstevel@tonic-gate 	struct	termios	tty;
2433*7c478bd9Sstevel@tonic-gate 	int	tty_flag, i, j;
2434*7c478bd9Sstevel@tonic-gate 	char	*shell_name;
2435*7c478bd9Sstevel@tonic-gate 	static char	*default_shell = "/bin/sh";
2436*7c478bd9Sstevel@tonic-gate 
2437*7c478bd9Sstevel@tonic-gate 	tty_flag = -1;
2438*7c478bd9Sstevel@tonic-gate 
2439*7c478bd9Sstevel@tonic-gate 	if (*s == NULL) {
2440*7c478bd9Sstevel@tonic-gate 		shell_name = getenv("SHELL");
2441*7c478bd9Sstevel@tonic-gate 
2442*7c478bd9Sstevel@tonic-gate 		if (shell_name == NULL) {
2443*7c478bd9Sstevel@tonic-gate 			shell_name = default_shell;
2444*7c478bd9Sstevel@tonic-gate 		}
2445*7c478bd9Sstevel@tonic-gate 
2446*7c478bd9Sstevel@tonic-gate 		if (strlcpy(s, shell_name, MAXPATHLEN) >=
2447*7c478bd9Sstevel@tonic-gate 		    MAXPATHLEN) {
2448*7c478bd9Sstevel@tonic-gate 			err_print("Error: length of shell command"
2449*7c478bd9Sstevel@tonic-gate 				" ($SHELL) exceeds MAXPATHLEN\n");
2450*7c478bd9Sstevel@tonic-gate 			fullabort();
2451*7c478bd9Sstevel@tonic-gate 		}
2452*7c478bd9Sstevel@tonic-gate 	}
2453*7c478bd9Sstevel@tonic-gate 
2454*7c478bd9Sstevel@tonic-gate 	/* save tty information */
2455*7c478bd9Sstevel@tonic-gate 
2456*7c478bd9Sstevel@tonic-gate 	if (isatty(0)) {
2457*7c478bd9Sstevel@tonic-gate 		if (ioctl(0, TCGETS, &tty) == 0)
2458*7c478bd9Sstevel@tonic-gate 			tty_flag = 1;
2459*7c478bd9Sstevel@tonic-gate 		else {
2460*7c478bd9Sstevel@tonic-gate 			if (ioctl(0, TCGETA, &termio) == 0) {
2461*7c478bd9Sstevel@tonic-gate 				tty_flag = 0;
2462*7c478bd9Sstevel@tonic-gate 				tty.c_iflag = termio.c_iflag;
2463*7c478bd9Sstevel@tonic-gate 				tty.c_oflag = termio.c_oflag;
2464*7c478bd9Sstevel@tonic-gate 				tty.c_cflag = termio.c_cflag;
2465*7c478bd9Sstevel@tonic-gate 				tty.c_lflag = termio.c_lflag;
2466*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < NCC; i++)
2467*7c478bd9Sstevel@tonic-gate 					tty.c_cc[i] = termio.c_cc[i];
2468*7c478bd9Sstevel@tonic-gate 			}
2469*7c478bd9Sstevel@tonic-gate 		}
2470*7c478bd9Sstevel@tonic-gate 	}
2471*7c478bd9Sstevel@tonic-gate 
2472*7c478bd9Sstevel@tonic-gate 	/* close the current file descriptor */
2473*7c478bd9Sstevel@tonic-gate 	if (cur_disk != NULL) {
2474*7c478bd9Sstevel@tonic-gate 		(void) close(cur_file);
2475*7c478bd9Sstevel@tonic-gate 	}
2476*7c478bd9Sstevel@tonic-gate 
2477*7c478bd9Sstevel@tonic-gate 	/* execute the shell escape */
2478*7c478bd9Sstevel@tonic-gate 	(void) system(s);
2479*7c478bd9Sstevel@tonic-gate 
2480*7c478bd9Sstevel@tonic-gate 	/* reopen file descriptor if one was open before */
2481*7c478bd9Sstevel@tonic-gate 	if (cur_disk != NULL) {
2482*7c478bd9Sstevel@tonic-gate 		if ((cur_file = open_disk(cur_disk->disk_path,
2483*7c478bd9Sstevel@tonic-gate 			O_RDWR | O_NDELAY)) < 0) {
2484*7c478bd9Sstevel@tonic-gate 			err_print("Error: can't reopen selected disk '%s'. \n",
2485*7c478bd9Sstevel@tonic-gate 				cur_disk->disk_name);
2486*7c478bd9Sstevel@tonic-gate 			fullabort();
2487*7c478bd9Sstevel@tonic-gate 		}
2488*7c478bd9Sstevel@tonic-gate 	}
2489*7c478bd9Sstevel@tonic-gate 
2490*7c478bd9Sstevel@tonic-gate 	/* Restore tty information */
2491*7c478bd9Sstevel@tonic-gate 
2492*7c478bd9Sstevel@tonic-gate 	if (isatty(0)) {
2493*7c478bd9Sstevel@tonic-gate 		if (tty_flag > 0)
2494*7c478bd9Sstevel@tonic-gate 			(void) ioctl(0, TCSETSW, &tty);
2495*7c478bd9Sstevel@tonic-gate 		else if (tty_flag == 0) {
2496*7c478bd9Sstevel@tonic-gate 			termio.c_iflag = tty.c_iflag;
2497*7c478bd9Sstevel@tonic-gate 			termio.c_oflag = tty.c_oflag;
2498*7c478bd9Sstevel@tonic-gate 			termio.c_cflag = tty.c_cflag;
2499*7c478bd9Sstevel@tonic-gate 			termio.c_lflag = tty.c_lflag;
2500*7c478bd9Sstevel@tonic-gate 			for (j = 0; j < NCC; j++)
2501*7c478bd9Sstevel@tonic-gate 				termio.c_cc[j] = tty.c_cc[j];
2502*7c478bd9Sstevel@tonic-gate 			(void) ioctl(0, TCSETAW, &termio);
2503*7c478bd9Sstevel@tonic-gate 		}
2504*7c478bd9Sstevel@tonic-gate 
2505*7c478bd9Sstevel@tonic-gate 		if (isatty(1)) {
2506*7c478bd9Sstevel@tonic-gate 			fmt_print("\n[Hit Return to continue] \n");
2507*7c478bd9Sstevel@tonic-gate 			(void) fflush(stdin);
2508*7c478bd9Sstevel@tonic-gate 			if (getchar() == EOF)
2509*7c478bd9Sstevel@tonic-gate 				fullabort();
2510*7c478bd9Sstevel@tonic-gate 		}
2511*7c478bd9Sstevel@tonic-gate 	}
2512*7c478bd9Sstevel@tonic-gate 	return (0);
2513*7c478bd9Sstevel@tonic-gate }
2514*7c478bd9Sstevel@tonic-gate 
2515*7c478bd9Sstevel@tonic-gate void
2516*7c478bd9Sstevel@tonic-gate print_efi_string(char *vendor, char *product, char *revision,
2517*7c478bd9Sstevel@tonic-gate     uint64_t capacity)
2518*7c478bd9Sstevel@tonic-gate {
2519*7c478bd9Sstevel@tonic-gate 	char new_vendor[9];
2520*7c478bd9Sstevel@tonic-gate 	char new_product[17];
2521*7c478bd9Sstevel@tonic-gate 	char new_revision[5];
2522*7c478bd9Sstevel@tonic-gate 	char capacity_string[10];
2523*7c478bd9Sstevel@tonic-gate 	float scaled;
2524*7c478bd9Sstevel@tonic-gate 	int i;
2525*7c478bd9Sstevel@tonic-gate 
2526*7c478bd9Sstevel@tonic-gate 	/* Strip whitespace from the end of inquiry strings */
2527*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(new_vendor, vendor, sizeof (new_vendor));
2528*7c478bd9Sstevel@tonic-gate 	for (i = (strlen(new_vendor) - 1); i >= 0; i--) {
2529*7c478bd9Sstevel@tonic-gate 		if (new_vendor[i] != 0x20) {
2530*7c478bd9Sstevel@tonic-gate 			new_vendor[i+1] = '\0';
2531*7c478bd9Sstevel@tonic-gate 			break;
2532*7c478bd9Sstevel@tonic-gate 		}
2533*7c478bd9Sstevel@tonic-gate 	}
2534*7c478bd9Sstevel@tonic-gate 
2535*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(new_product, product, sizeof (new_product));
2536*7c478bd9Sstevel@tonic-gate 	for (i = (strlen(new_product) - 1); i >= 0; i--) {
2537*7c478bd9Sstevel@tonic-gate 		if (new_product[i] != 0x20) {
2538*7c478bd9Sstevel@tonic-gate 			new_product[i+1] = '\0';
2539*7c478bd9Sstevel@tonic-gate 			break;
2540*7c478bd9Sstevel@tonic-gate 		}
2541*7c478bd9Sstevel@tonic-gate 	}
2542*7c478bd9Sstevel@tonic-gate 
2543*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(new_revision, revision, sizeof (new_revision));
2544*7c478bd9Sstevel@tonic-gate 	for (i = (strlen(new_revision) - 1); i >= 0; i--) {
2545*7c478bd9Sstevel@tonic-gate 		if (new_revision[i] != 0x20) {
2546*7c478bd9Sstevel@tonic-gate 			new_revision[i+1] = '\0';
2547*7c478bd9Sstevel@tonic-gate 			break;
2548*7c478bd9Sstevel@tonic-gate 		}
2549*7c478bd9Sstevel@tonic-gate 	}
2550*7c478bd9Sstevel@tonic-gate 
2551*7c478bd9Sstevel@tonic-gate 	/* Now build size string */
2552*7c478bd9Sstevel@tonic-gate 	scaled = bn2mb(capacity);
2553*7c478bd9Sstevel@tonic-gate 	if (scaled >= (float)1024.0 * 1024) {
2554*7c478bd9Sstevel@tonic-gate 		(void) snprintf(capacity_string, sizeof (capacity_string),
2555*7c478bd9Sstevel@tonic-gate 		    "%.2fTB", scaled/((float)1024.0 * 1024));
2556*7c478bd9Sstevel@tonic-gate 	} else if (scaled >= (float)1024.0) {
2557*7c478bd9Sstevel@tonic-gate 		(void) snprintf(capacity_string, sizeof (capacity_string),
2558*7c478bd9Sstevel@tonic-gate 		    "%.2fGB", scaled/(float)1024.0);
2559*7c478bd9Sstevel@tonic-gate 	} else {
2560*7c478bd9Sstevel@tonic-gate 		(void) snprintf(capacity_string, sizeof (capacity_string),
2561*7c478bd9Sstevel@tonic-gate 		    "%.2fMB", scaled);
2562*7c478bd9Sstevel@tonic-gate 	}
2563*7c478bd9Sstevel@tonic-gate 
2564*7c478bd9Sstevel@tonic-gate 	fmt_print("<%s-%s-%s-%s>",
2565*7c478bd9Sstevel@tonic-gate 	    new_vendor, new_product, new_revision, capacity_string);
2566*7c478bd9Sstevel@tonic-gate }
2567