xref: /onnv-gate/usr/src/cmd/format/io.c (revision 9889:68d0fe4c716e)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54429Sbz211116  * Common Development and Distribution License (the "License").
64429Sbz211116  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*9889SLarry.Liu@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * This file contains I/O related functions.
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate #include "global.h"
300Sstevel@tonic-gate 
310Sstevel@tonic-gate #include <unistd.h>
320Sstevel@tonic-gate #include <stdlib.h>
330Sstevel@tonic-gate #include <string.h>
340Sstevel@tonic-gate #include <signal.h>
350Sstevel@tonic-gate #include <ctype.h>
360Sstevel@tonic-gate #include <stdarg.h>
370Sstevel@tonic-gate #include <sys/tty.h>
380Sstevel@tonic-gate #include <sys/termio.h>
390Sstevel@tonic-gate #include <sys/termios.h>
400Sstevel@tonic-gate 
410Sstevel@tonic-gate #include "startup.h"
420Sstevel@tonic-gate #include "misc.h"
430Sstevel@tonic-gate #include "menu_partition.h"
440Sstevel@tonic-gate #include "param.h"
450Sstevel@tonic-gate #include "menu.h"
460Sstevel@tonic-gate 
470Sstevel@tonic-gate 
480Sstevel@tonic-gate extern int	data_lineno;
490Sstevel@tonic-gate extern char	*space2str();
500Sstevel@tonic-gate extern long	strtol();
510Sstevel@tonic-gate 
520Sstevel@tonic-gate /*
530Sstevel@tonic-gate  * This variable is used to determine whether a token is present in the pipe
540Sstevel@tonic-gate  * already.
550Sstevel@tonic-gate  */
560Sstevel@tonic-gate static	char	token_present = 0;
570Sstevel@tonic-gate 
580Sstevel@tonic-gate /*
590Sstevel@tonic-gate  * This variable always gives us access to the most recent token type
600Sstevel@tonic-gate  */
610Sstevel@tonic-gate int	last_token_type = 0;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate #ifdef	__STDC__
640Sstevel@tonic-gate /*
650Sstevel@tonic-gate  * Prototypes for ANSI C compilers
660Sstevel@tonic-gate  */
670Sstevel@tonic-gate static int	sup_get_token(char *);
680Sstevel@tonic-gate static void	pushchar(int c);
690Sstevel@tonic-gate static int	checkeof(void);
700Sstevel@tonic-gate static void	flushline(void);
710Sstevel@tonic-gate static int	strcnt(char *s1, char *s2);
727563SPrasad.Singamsetty@Sun.COM static int	getbn(char *str, diskaddr_t *iptr);
730Sstevel@tonic-gate static void	print_input_choices(int type, u_ioparam_t *param);
740Sstevel@tonic-gate static int	slist_widest_str(slist_t *slist);
750Sstevel@tonic-gate static void	ljust_print(char *str, int width);
760Sstevel@tonic-gate static int	sup_inputchar(void);
770Sstevel@tonic-gate static void	sup_pushchar(int c);
780Sstevel@tonic-gate static int	geti64(char *str, uint64_t *iptr, uint64_t *wild);
790Sstevel@tonic-gate 
800Sstevel@tonic-gate #else	/* __STDC__ */
810Sstevel@tonic-gate /*
820Sstevel@tonic-gate  * Prototypes for non-ANSI C compilers
830Sstevel@tonic-gate  */
840Sstevel@tonic-gate 
850Sstevel@tonic-gate static int	sup_get_token();
860Sstevel@tonic-gate static void	pushchar(int c);
870Sstevel@tonic-gate static int	checkeof(void);
880Sstevel@tonic-gate static void	flushline(void);
890Sstevel@tonic-gate static int	strcnt(char *s1, char *s2);
907563SPrasad.Singamsetty@Sun.COM static int	getbn(char *str, diskaddr_t *iptr);
910Sstevel@tonic-gate static void	print_input_choices(int type, u_ioparam_t *param);
920Sstevel@tonic-gate static int	slist_widest_str(slist_t *slist);
930Sstevel@tonic-gate static void	ljust_print(char *str, int width);
940Sstevel@tonic-gate static int	sup_inputchar(void);
950Sstevel@tonic-gate static void	sup_pushchar(int c);
960Sstevel@tonic-gate static int	geti64(char *str, uint64_t *iptr, uint64_t *wild);
970Sstevel@tonic-gate 
980Sstevel@tonic-gate #endif	/* __STDC__ */
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate /*
1020Sstevel@tonic-gate  * This routine pushes the given character back onto the input stream.
1030Sstevel@tonic-gate  */
1040Sstevel@tonic-gate static void
pushchar(c)1050Sstevel@tonic-gate pushchar(c)
1060Sstevel@tonic-gate 	int	c;
1070Sstevel@tonic-gate {
1080Sstevel@tonic-gate 	(void) ungetc(c, stdin);
1090Sstevel@tonic-gate }
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate /*
1120Sstevel@tonic-gate  * This routine checks the input stream for an eof condition.
1130Sstevel@tonic-gate  */
1140Sstevel@tonic-gate static int
checkeof()1150Sstevel@tonic-gate checkeof()
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate 	return (feof(stdin));
1180Sstevel@tonic-gate }
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate /*
1210Sstevel@tonic-gate  * This routine gets the next token off the input stream.  A token is
1220Sstevel@tonic-gate  * basically any consecutive non-white characters.
1230Sstevel@tonic-gate  */
1240Sstevel@tonic-gate char *
gettoken(inbuf)1250Sstevel@tonic-gate gettoken(inbuf)
1260Sstevel@tonic-gate 	char	*inbuf;
1270Sstevel@tonic-gate {
1280Sstevel@tonic-gate 	char	*ptr = inbuf;
1290Sstevel@tonic-gate 	int	c, quoted = 0;
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate retoke:
1320Sstevel@tonic-gate 	/*
1330Sstevel@tonic-gate 	 * Remove any leading white-space.
1340Sstevel@tonic-gate 	 */
1350Sstevel@tonic-gate 	while ((isspace(c = getchar())) && (c != '\n'))
1360Sstevel@tonic-gate 		;
1370Sstevel@tonic-gate 	/*
1380Sstevel@tonic-gate 	 * If we are at the beginning of a line and hit the comment character,
1390Sstevel@tonic-gate 	 * flush the line and start again.
1400Sstevel@tonic-gate 	 */
1410Sstevel@tonic-gate 	if (!token_present && c == COMMENT_CHAR) {
1420Sstevel@tonic-gate 		token_present = 1;
1430Sstevel@tonic-gate 		flushline();
1440Sstevel@tonic-gate 		goto retoke;
1450Sstevel@tonic-gate 	}
1460Sstevel@tonic-gate 	/*
1470Sstevel@tonic-gate 	 * Loop on each character until we hit unquoted white-space.
1480Sstevel@tonic-gate 	 */
1490Sstevel@tonic-gate 	while (!isspace(c) || quoted && (c != '\n')) {
1500Sstevel@tonic-gate 		/*
1510Sstevel@tonic-gate 		 * If we hit eof, get out.
1520Sstevel@tonic-gate 		 */
1530Sstevel@tonic-gate 		if (checkeof())
1540Sstevel@tonic-gate 			return (NULL);
1550Sstevel@tonic-gate 		/*
1560Sstevel@tonic-gate 		 * If we hit a double quote, change the state of quotedness.
1570Sstevel@tonic-gate 		 */
1580Sstevel@tonic-gate 		if (c == '"')
1590Sstevel@tonic-gate 			quoted = !quoted;
1600Sstevel@tonic-gate 		/*
1610Sstevel@tonic-gate 		 * If there's room in the buffer, add the character to the end.
1620Sstevel@tonic-gate 		 */
1630Sstevel@tonic-gate 		else if (ptr - inbuf < TOKEN_SIZE)
1640Sstevel@tonic-gate 			*ptr++ = (char)c;
1650Sstevel@tonic-gate 		/*
1660Sstevel@tonic-gate 		 * Get the next character.
1670Sstevel@tonic-gate 		 */
1680Sstevel@tonic-gate 		c = getchar();
1690Sstevel@tonic-gate 	}
1700Sstevel@tonic-gate 	/*
1710Sstevel@tonic-gate 	 * Null terminate the token.
1720Sstevel@tonic-gate 	 */
1730Sstevel@tonic-gate 	*ptr = '\0';
1740Sstevel@tonic-gate 	/*
1750Sstevel@tonic-gate 	 * Peel off white-space still in the pipe.
1760Sstevel@tonic-gate 	 */
1770Sstevel@tonic-gate 	while (isspace(c) && (c != '\n'))
1780Sstevel@tonic-gate 		c = getchar();
1790Sstevel@tonic-gate 	/*
1800Sstevel@tonic-gate 	 * If we hit another token, push it back and set state.
1810Sstevel@tonic-gate 	 */
1820Sstevel@tonic-gate 	if (c != '\n') {
1830Sstevel@tonic-gate 		pushchar(c);
1840Sstevel@tonic-gate 		token_present = 1;
1850Sstevel@tonic-gate 	} else
1860Sstevel@tonic-gate 		token_present = 0;
1870Sstevel@tonic-gate 	/*
1880Sstevel@tonic-gate 	 * Return the token.
1890Sstevel@tonic-gate 	 */
1900Sstevel@tonic-gate 	return (inbuf);
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate /*
1940Sstevel@tonic-gate  * This routine removes the leading and trailing spaces from a token.
1950Sstevel@tonic-gate  */
1960Sstevel@tonic-gate void
clean_token(cleantoken,token)1970Sstevel@tonic-gate clean_token(cleantoken, token)
1980Sstevel@tonic-gate 	char	*cleantoken, *token;
1990Sstevel@tonic-gate {
2000Sstevel@tonic-gate 	char	*ptr;
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	/*
2030Sstevel@tonic-gate 	 * Strip off leading white-space.
2040Sstevel@tonic-gate 	 */
2050Sstevel@tonic-gate 	for (ptr = token; isspace(*ptr); ptr++)
2060Sstevel@tonic-gate 		;
2070Sstevel@tonic-gate 	/*
2080Sstevel@tonic-gate 	 * Copy it into the clean buffer.
2090Sstevel@tonic-gate 	 */
2100Sstevel@tonic-gate 	(void) strcpy(cleantoken, ptr);
2110Sstevel@tonic-gate 	/*
2120Sstevel@tonic-gate 	 * Strip off trailing white-space.
2130Sstevel@tonic-gate 	 */
2140Sstevel@tonic-gate 	for (ptr = cleantoken + strlen(cleantoken) - 1;
2150Sstevel@tonic-gate 		isspace(*ptr) && (ptr >= cleantoken); ptr--) {
2160Sstevel@tonic-gate 		*ptr = '\0';
2170Sstevel@tonic-gate 	}
2180Sstevel@tonic-gate }
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate /*
2210Sstevel@tonic-gate  * This routine checks if a token is already present on the input line
2220Sstevel@tonic-gate  */
2230Sstevel@tonic-gate int
istokenpresent()2240Sstevel@tonic-gate istokenpresent()
2250Sstevel@tonic-gate {
2260Sstevel@tonic-gate 	return (token_present);
2270Sstevel@tonic-gate }
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate /*
2300Sstevel@tonic-gate  * This routine flushes the rest of an input line if there is known
2310Sstevel@tonic-gate  * to be data in it.  The flush has to be qualified because the newline
2320Sstevel@tonic-gate  * may have already been swallowed by the last gettoken.
2330Sstevel@tonic-gate  */
2340Sstevel@tonic-gate static void
flushline()2350Sstevel@tonic-gate flushline()
2360Sstevel@tonic-gate {
2370Sstevel@tonic-gate 	if (token_present) {
2380Sstevel@tonic-gate 		/*
2390Sstevel@tonic-gate 		 * Flush the pipe to eol or eof.
2400Sstevel@tonic-gate 		 */
2410Sstevel@tonic-gate 		while ((getchar() != '\n') && !checkeof())
2420Sstevel@tonic-gate 			;
2430Sstevel@tonic-gate 		/*
2440Sstevel@tonic-gate 		 * Mark the pipe empty.
2450Sstevel@tonic-gate 		 */
2460Sstevel@tonic-gate 		token_present = 0;
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate /*
2510Sstevel@tonic-gate  * This routine returns the number of characters that are identical
2520Sstevel@tonic-gate  * between s1 and s2, stopping as soon as a mismatch is found.
2530Sstevel@tonic-gate  */
2540Sstevel@tonic-gate static int
strcnt(s1,s2)2550Sstevel@tonic-gate strcnt(s1, s2)
2560Sstevel@tonic-gate 	char	*s1, *s2;
2570Sstevel@tonic-gate {
2580Sstevel@tonic-gate 	int	i = 0;
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	while ((*s1 != '\0') && (*s1++ == *s2++))
2610Sstevel@tonic-gate 		i++;
2620Sstevel@tonic-gate 	return (i);
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate /*
2660Sstevel@tonic-gate  * This routine converts the given token into an integer.  The token
2670Sstevel@tonic-gate  * must convert cleanly into an integer with no unknown characters.
2680Sstevel@tonic-gate  * If the token is the wildcard string, and the wildcard parameter
2690Sstevel@tonic-gate  * is present, the wildcard value will be returned.
2700Sstevel@tonic-gate  */
2710Sstevel@tonic-gate int
geti(str,iptr,wild)2720Sstevel@tonic-gate geti(str, iptr, wild)
2730Sstevel@tonic-gate 	char	*str;
2740Sstevel@tonic-gate 	int	*iptr, *wild;
2750Sstevel@tonic-gate {
2760Sstevel@tonic-gate 	char	*str2;
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	/*
2790Sstevel@tonic-gate 	 * If there's a wildcard value and the string is wild, return the
2800Sstevel@tonic-gate 	 * wildcard value.
2810Sstevel@tonic-gate 	 */
2820Sstevel@tonic-gate 	if (wild != NULL && strcmp(str, WILD_STRING) == 0)
2830Sstevel@tonic-gate 		*iptr = *wild;
2840Sstevel@tonic-gate 	else {
2850Sstevel@tonic-gate 		/*
2860Sstevel@tonic-gate 		 * Conver the string to an integer.
2870Sstevel@tonic-gate 		 */
2880Sstevel@tonic-gate 		*iptr = (int)strtol(str, &str2, 0);
2890Sstevel@tonic-gate 		/*
2900Sstevel@tonic-gate 		 * If any characters didn't convert, it's an error.
2910Sstevel@tonic-gate 		 */
2920Sstevel@tonic-gate 		if (*str2 != '\0') {
2930Sstevel@tonic-gate 			err_print("`%s' is not an integer.\n", str);
2940Sstevel@tonic-gate 			return (-1);
2950Sstevel@tonic-gate 		}
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 	return (0);
2980Sstevel@tonic-gate }
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate /*
3010Sstevel@tonic-gate  * This routine converts the given token into a long long.  The token
3020Sstevel@tonic-gate  * must convert cleanly into a 64-bit integer with no unknown characters.
3030Sstevel@tonic-gate  * If the token is the wildcard string, and the wildcard parameter
3040Sstevel@tonic-gate  * is present, the wildcard value will be returned.
3050Sstevel@tonic-gate  */
3060Sstevel@tonic-gate static int
geti64(str,iptr,wild)3070Sstevel@tonic-gate geti64(str, iptr, wild)
3080Sstevel@tonic-gate 	char		*str;
3090Sstevel@tonic-gate 	uint64_t	*iptr, *wild;
3100Sstevel@tonic-gate {
3110Sstevel@tonic-gate 	char	*str2;
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	/*
3140Sstevel@tonic-gate 	 * If there's a wildcard value and the string is wild, return the
3150Sstevel@tonic-gate 	 * wildcard value.
3160Sstevel@tonic-gate 	 */
3170Sstevel@tonic-gate 	if ((wild != NULL) && (strcmp(str, WILD_STRING)) == 0) {
3180Sstevel@tonic-gate 		*iptr = *wild;
3190Sstevel@tonic-gate 	} else {
3200Sstevel@tonic-gate 		/*
3210Sstevel@tonic-gate 		 * Conver the string to an integer.
3220Sstevel@tonic-gate 		 */
3230Sstevel@tonic-gate 		*iptr = (uint64_t)strtoll(str, &str2, 0);
3240Sstevel@tonic-gate 		/*
3250Sstevel@tonic-gate 		 * If any characters didn't convert, it's an error.
3260Sstevel@tonic-gate 		 */
3270Sstevel@tonic-gate 		if (*str2 != '\0') {
3280Sstevel@tonic-gate 			err_print("`%s' is not an integer.\n", str);
3290Sstevel@tonic-gate 			return (-1);
3300Sstevel@tonic-gate 		}
3310Sstevel@tonic-gate 	}
3320Sstevel@tonic-gate 	return (0);
3330Sstevel@tonic-gate }
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate /*
3360Sstevel@tonic-gate  * This routine converts the given string into a block number on the
3370Sstevel@tonic-gate  * current disk.  The format of a block number is either a self-based
3380Sstevel@tonic-gate  * number, or a series of self-based numbers separated by slashes.
3390Sstevel@tonic-gate  * Any number preceeding the first slash is considered a cylinder value.
3400Sstevel@tonic-gate  * Any number succeeding the first slash but preceeding the second is
3410Sstevel@tonic-gate  * considered a head value.  Any number succeeding the second slash is
3420Sstevel@tonic-gate  * considered a sector value.  Any of these numbers can be wildcarded
3430Sstevel@tonic-gate  * to the highest possible legal value.
3440Sstevel@tonic-gate  */
3450Sstevel@tonic-gate static int
getbn(str,iptr)3460Sstevel@tonic-gate getbn(str, iptr)
3470Sstevel@tonic-gate 	char	*str;
3487563SPrasad.Singamsetty@Sun.COM 	diskaddr_t	*iptr;
3490Sstevel@tonic-gate {
3500Sstevel@tonic-gate 	char	*cptr, *hptr, *sptr;
3517563SPrasad.Singamsetty@Sun.COM 	int	cyl, head, sect;
3527563SPrasad.Singamsetty@Sun.COM 	int	wild;
3537563SPrasad.Singamsetty@Sun.COM 	diskaddr_t	wild64;
3540Sstevel@tonic-gate 	TOKEN	buf;
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 	/*
3570Sstevel@tonic-gate 	 * Set cylinder pointer to beginning of string.
3580Sstevel@tonic-gate 	 */
3590Sstevel@tonic-gate 	cptr = str;
3600Sstevel@tonic-gate 	/*
3610Sstevel@tonic-gate 	 * Look for the first slash.
3620Sstevel@tonic-gate 	 */
3630Sstevel@tonic-gate 	while ((*str != '\0') && (*str != '/'))
3640Sstevel@tonic-gate 		str++;
3650Sstevel@tonic-gate 	/*
3660Sstevel@tonic-gate 	 * If there wasn't one, convert string to an integer and return it.
3670Sstevel@tonic-gate 	 */
3680Sstevel@tonic-gate 	if (*str == '\0') {
3697563SPrasad.Singamsetty@Sun.COM 		wild64 = physsects() - 1;
3707563SPrasad.Singamsetty@Sun.COM 		if (geti64(cptr, iptr, &wild64))
3710Sstevel@tonic-gate 			return (-1);
3720Sstevel@tonic-gate 		return (0);
3730Sstevel@tonic-gate 	}
3740Sstevel@tonic-gate 	/*
3750Sstevel@tonic-gate 	 * Null out the slash and set head pointer just beyond it.
3760Sstevel@tonic-gate 	 */
3770Sstevel@tonic-gate 	*str++ = '\0';
3780Sstevel@tonic-gate 	hptr = str;
3790Sstevel@tonic-gate 	/*
3800Sstevel@tonic-gate 	 * Look for the second slash.
3810Sstevel@tonic-gate 	 */
3820Sstevel@tonic-gate 	while ((*str != '\0') && (*str != '/'))
3830Sstevel@tonic-gate 		str++;
3840Sstevel@tonic-gate 	/*
3850Sstevel@tonic-gate 	 * If there wasn't one, sector pointer points to a .
3860Sstevel@tonic-gate 	 */
3870Sstevel@tonic-gate 	if (*str == '\0')
3880Sstevel@tonic-gate 		sptr = str;
3890Sstevel@tonic-gate 	/*
3900Sstevel@tonic-gate 	 * If there was, null it out and set sector point just beyond it.
3910Sstevel@tonic-gate 	 */
3920Sstevel@tonic-gate 	else {
3930Sstevel@tonic-gate 		*str++ = '\0';
3940Sstevel@tonic-gate 		sptr = str;
3950Sstevel@tonic-gate 	}
3960Sstevel@tonic-gate 	/*
3970Sstevel@tonic-gate 	 * Convert the cylinder part to an integer and store it.
3980Sstevel@tonic-gate 	 */
3990Sstevel@tonic-gate 	clean_token(buf, cptr);
4000Sstevel@tonic-gate 	wild = ncyl + acyl - 1;
4010Sstevel@tonic-gate 	if (geti(buf, &cyl, &wild))
4020Sstevel@tonic-gate 		return (-1);
4030Sstevel@tonic-gate 	if ((cyl < 0) || (cyl >= (ncyl + acyl))) {
4040Sstevel@tonic-gate 		err_print("`%d' is out of range.\n", cyl);
4050Sstevel@tonic-gate 		return (-1);
4060Sstevel@tonic-gate 	}
4070Sstevel@tonic-gate 	/*
4080Sstevel@tonic-gate 	 * Convert the head part to an integer and store it.
4090Sstevel@tonic-gate 	 */
4100Sstevel@tonic-gate 	clean_token(buf, hptr);
4110Sstevel@tonic-gate 	wild = nhead - 1;
4120Sstevel@tonic-gate 	if (geti(buf, &head, &wild))
4130Sstevel@tonic-gate 		return (-1);
4140Sstevel@tonic-gate 	if ((head < 0) || (head >= nhead)) {
4150Sstevel@tonic-gate 		err_print("`%d' is out of range.\n", head);
4160Sstevel@tonic-gate 		return (-1);
4170Sstevel@tonic-gate 	}
4180Sstevel@tonic-gate 	/*
4190Sstevel@tonic-gate 	 * Convert the sector part to an integer and store it.
4200Sstevel@tonic-gate 	 */
4210Sstevel@tonic-gate 	clean_token(buf, sptr);
4220Sstevel@tonic-gate 	wild = sectors(head) - 1;
4230Sstevel@tonic-gate 	if (geti(buf, &sect, &wild))
4240Sstevel@tonic-gate 		return (-1);
4250Sstevel@tonic-gate 	if ((sect < 0) || (sect >= sectors(head))) {
4260Sstevel@tonic-gate 		err_print("`%d' is out of range.\n", sect);
4270Sstevel@tonic-gate 		return (-1);
4280Sstevel@tonic-gate 	}
4290Sstevel@tonic-gate 	/*
4300Sstevel@tonic-gate 	 * Combine the pieces into a block number and return it.
4310Sstevel@tonic-gate 	 */
4320Sstevel@tonic-gate 	*iptr = chs2bn(cyl, head, sect);
4330Sstevel@tonic-gate 	return (0);
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate /*
4370Sstevel@tonic-gate  * This routine is the basis for all input into the program.  It
4380Sstevel@tonic-gate  * understands the semantics of a set of input types, and provides
4390Sstevel@tonic-gate  * consistent error messages for all input.  It allows for default
4400Sstevel@tonic-gate  * values and prompt strings.
4410Sstevel@tonic-gate  */
4420Sstevel@tonic-gate uint64_t
input(type,promptstr,delim,param,deflt,cmdflag)4430Sstevel@tonic-gate input(type, promptstr, delim, param, deflt, cmdflag)
4440Sstevel@tonic-gate 	int		type;
4450Sstevel@tonic-gate 	char		*promptstr;
4460Sstevel@tonic-gate 	int		delim;
4470Sstevel@tonic-gate 	u_ioparam_t	*param;
4480Sstevel@tonic-gate 	int		*deflt;
4490Sstevel@tonic-gate 	int		cmdflag;
4500Sstevel@tonic-gate {
4510Sstevel@tonic-gate 	int		interactive, help, i, length, index, tied;
4527563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	bn;
4530Sstevel@tonic-gate 	diskaddr_t	bn64;
4540Sstevel@tonic-gate 	char		**str, **strings;
4550Sstevel@tonic-gate 	TOKEN		token, cleantoken;
4560Sstevel@tonic-gate 	TOKEN		token2, cleantoken2;
4571383Spr131582 	char		*arg;
4580Sstevel@tonic-gate 	struct		bounds *bounds;
4590Sstevel@tonic-gate 	char		*s;
4600Sstevel@tonic-gate 	int		value;
4610Sstevel@tonic-gate 	int		cyls, cylno;
4620Sstevel@tonic-gate 	uint64_t	blokno;
4630Sstevel@tonic-gate 	float		nmegs;
4640Sstevel@tonic-gate 	float		ngigs;
4650Sstevel@tonic-gate 	char		shell_argv[MAXPATHLEN];
4660Sstevel@tonic-gate 	part_deflt_t	*part_deflt;
4670Sstevel@tonic-gate 	efi_deflt_t	*efi_deflt;
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 	/*
4700Sstevel@tonic-gate 	 * Optional integer input has been added as a hack.
4710Sstevel@tonic-gate 	 * Function result is 1 if user typed anything.
4720Sstevel@tonic-gate 	 * Whatever they typed is returned in *deflt.
4730Sstevel@tonic-gate 	 * This permits us to distinguish between "no value",
4740Sstevel@tonic-gate 	 * and actually entering in some value, for instance.
4750Sstevel@tonic-gate 	 */
4760Sstevel@tonic-gate 	if (type == FIO_OPINT) {
4770Sstevel@tonic-gate 		assert(deflt != NULL);
4780Sstevel@tonic-gate 	}
4790Sstevel@tonic-gate reprompt:
4800Sstevel@tonic-gate 	help = interactive = 0;
4810Sstevel@tonic-gate 	/*
4820Sstevel@tonic-gate 	 * If we are inputting a command, flush any current input in the pipe.
4830Sstevel@tonic-gate 	 */
4840Sstevel@tonic-gate 	if (cmdflag == CMD_INPUT)
4850Sstevel@tonic-gate 		flushline();
4860Sstevel@tonic-gate 	/*
4870Sstevel@tonic-gate 	 * Note whether the token is already present.
4880Sstevel@tonic-gate 	 */
4890Sstevel@tonic-gate 	if (!token_present)
4900Sstevel@tonic-gate 		interactive = 1;
4910Sstevel@tonic-gate 	/*
4920Sstevel@tonic-gate 	 * Print the prompt.
4930Sstevel@tonic-gate 	 */
4940Sstevel@tonic-gate 	fmt_print(promptstr);
4950Sstevel@tonic-gate 	/*
4960Sstevel@tonic-gate 	 * If there is a default value, print it in a format appropriate
4970Sstevel@tonic-gate 	 * for the input type.
4980Sstevel@tonic-gate 	 */
4990Sstevel@tonic-gate 	if (deflt != NULL) {
5000Sstevel@tonic-gate 		switch (type) {
5010Sstevel@tonic-gate 		case FIO_BN:
5027563SPrasad.Singamsetty@Sun.COM #if !defined(lint)	/* caller has aligned the pointer specifying FIO_BN */
5037563SPrasad.Singamsetty@Sun.COM 			fmt_print("[%llu, ", *(diskaddr_t *)deflt);
5047563SPrasad.Singamsetty@Sun.COM 			pr_dblock(fmt_print, *(diskaddr_t *)deflt);
5050Sstevel@tonic-gate 			fmt_print("]");
5067563SPrasad.Singamsetty@Sun.COM #endif
5070Sstevel@tonic-gate 			break;
5080Sstevel@tonic-gate 		case FIO_INT:
5090Sstevel@tonic-gate 			fmt_print("[%d]", *deflt);
5100Sstevel@tonic-gate 			break;
5110Sstevel@tonic-gate 		case FIO_INT64:
5120Sstevel@tonic-gate #if defined(lint)
5130Sstevel@tonic-gate 			/* caller is longlong aligned specifying FIO_INT64 */
5140Sstevel@tonic-gate 			efi_deflt = NULL;
5150Sstevel@tonic-gate #else
5160Sstevel@tonic-gate 			efi_deflt = (efi_deflt_t *)deflt;
5170Sstevel@tonic-gate #endif
5180Sstevel@tonic-gate 			fmt_print("[%llu]", efi_deflt->start_sector);
5190Sstevel@tonic-gate 			break;
5200Sstevel@tonic-gate 		case FIO_CSTR:
5210Sstevel@tonic-gate 		case FIO_MSTR:
5220Sstevel@tonic-gate 			strings = (char **)param->io_charlist;
5230Sstevel@tonic-gate 			for (i = 0, str = strings; i < *deflt; i++, str++)
5240Sstevel@tonic-gate 				;
5250Sstevel@tonic-gate 			fmt_print("[%s]", *str);
5260Sstevel@tonic-gate 			break;
5270Sstevel@tonic-gate 		case FIO_OSTR:
5280Sstevel@tonic-gate 			fmt_print("[\"%s\"]", (char *)deflt);
5290Sstevel@tonic-gate 			break;
5300Sstevel@tonic-gate 		case FIO_SLIST:
5310Sstevel@tonic-gate 			/*
5320Sstevel@tonic-gate 			 * Search for a string matching the default
5330Sstevel@tonic-gate 			 * value.  If found, use it.  Otherwise
5340Sstevel@tonic-gate 			 * assume the default value is actually
5350Sstevel@tonic-gate 			 * an illegal choice, and default to
5360Sstevel@tonic-gate 			 * the first item in the list.
5370Sstevel@tonic-gate 			 */
5380Sstevel@tonic-gate 			s = find_string(param->io_slist, *deflt);
5390Sstevel@tonic-gate 			if (s == (char *)NULL) {
5400Sstevel@tonic-gate 				s = (param->io_slist)->str;
5410Sstevel@tonic-gate 			}
5420Sstevel@tonic-gate 			fmt_print("[%s]", s);
5430Sstevel@tonic-gate 			break;
5440Sstevel@tonic-gate 		case FIO_CYL:
5450Sstevel@tonic-gate 			/*
5460Sstevel@tonic-gate 			 * Old-style partition size input, used to
5470Sstevel@tonic-gate 			 * modify complete partition tables
5480Sstevel@tonic-gate 			 */
5497563SPrasad.Singamsetty@Sun.COM 			blokno = *(blkaddr32_t *)deflt;
5507563SPrasad.Singamsetty@Sun.COM 			fmt_print("[%llub, %uc, %1.2fmb, %1.2fgb]", blokno,
5517563SPrasad.Singamsetty@Sun.COM 			    bn2c(blokno), bn2mb(blokno), bn2gb(blokno));
5520Sstevel@tonic-gate 			break;
5530Sstevel@tonic-gate 		case FIO_ECYL:
5540Sstevel@tonic-gate 			/*
5550Sstevel@tonic-gate 			 * set up pointer to partition defaults
5560Sstevel@tonic-gate 			 * structure
5570Sstevel@tonic-gate 			 */
5580Sstevel@tonic-gate 			part_deflt = (part_deflt_t *)deflt;
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 			/*
5610Sstevel@tonic-gate 			 * Build print format specifier.  We use the
5620Sstevel@tonic-gate 			 * starting cylinder number which was entered
5630Sstevel@tonic-gate 			 * before this call to input(), in case the
5640Sstevel@tonic-gate 			 * user has changed it from the value in the
5650Sstevel@tonic-gate 			 * cur_parts->pinfo_map[].dkl_cylno
5660Sstevel@tonic-gate 			 * field for the current parition
5670Sstevel@tonic-gate 			 */
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate 			/*
5700Sstevel@tonic-gate 			 * Determine the proper default end cylinder:
5710Sstevel@tonic-gate 			 * Start Cyl	Default Size	End Cylinder
5720Sstevel@tonic-gate 			 *	0		0	0
5730Sstevel@tonic-gate 			 *	>0		0	Start Cyl
5740Sstevel@tonic-gate 			 *	0		>0	Default Size
5750Sstevel@tonic-gate 			 *				(Cyls) - 1
5760Sstevel@tonic-gate 			 *	>0		>0	(Start +
5770Sstevel@tonic-gate 			 *				Default Size
5780Sstevel@tonic-gate 			 *				(Cyls)) -1
5790Sstevel@tonic-gate 			 */
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 			if (part_deflt->deflt_size == 0) {
5820Sstevel@tonic-gate 				cylno = part_deflt->start_cyl;
5830Sstevel@tonic-gate 			} else if (part_deflt->start_cyl == 0) {
5847563SPrasad.Singamsetty@Sun.COM 				cylno = bn2c(part_deflt->deflt_size) - 1;
5850Sstevel@tonic-gate 			} else {
5860Sstevel@tonic-gate 				cylno = (bn2c(part_deflt->deflt_size) +
5870Sstevel@tonic-gate 					    part_deflt->start_cyl) - 1;
5880Sstevel@tonic-gate 			}
5890Sstevel@tonic-gate 
5907563SPrasad.Singamsetty@Sun.COM 			fmt_print("[%ub, %uc, %de, %1.2fmb, %1.2fgb]",
5910Sstevel@tonic-gate 			    part_deflt->deflt_size,
5920Sstevel@tonic-gate 			    bn2c(part_deflt->deflt_size),
5930Sstevel@tonic-gate 			    cylno,
5940Sstevel@tonic-gate 			    bn2mb(part_deflt->deflt_size),
5950Sstevel@tonic-gate 			    bn2gb(part_deflt->deflt_size));
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 			break;
5980Sstevel@tonic-gate 		case FIO_EFI:
5990Sstevel@tonic-gate #if defined(lint)
6000Sstevel@tonic-gate 			/* caller is longlong aligned when specifying FIO_EFI */
6010Sstevel@tonic-gate 			efi_deflt = NULL;
6020Sstevel@tonic-gate #else
6030Sstevel@tonic-gate 			efi_deflt = (efi_deflt_t *)deflt;
6040Sstevel@tonic-gate #endif
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate 			fmt_print("[%llub, %llue, %llumb, %llugb, %llutb]",
6070Sstevel@tonic-gate 			    efi_deflt->end_sector,
6080Sstevel@tonic-gate 			    efi_deflt->start_sector + efi_deflt->end_sector - 1,
609*9889SLarry.Liu@Sun.COM 			    (efi_deflt->end_sector * cur_blksz) /
6100Sstevel@tonic-gate 				(1024 * 1024),
611*9889SLarry.Liu@Sun.COM 			    (efi_deflt->end_sector * cur_blksz) /
6120Sstevel@tonic-gate 				(1024 * 1024 * 1024),
613*9889SLarry.Liu@Sun.COM 			    (efi_deflt->end_sector * cur_blksz) /
6140Sstevel@tonic-gate 				((uint64_t)1024 * 1024 * 1024 * 1024));
6150Sstevel@tonic-gate 			break;
6160Sstevel@tonic-gate 		case FIO_OPINT:
6170Sstevel@tonic-gate 			/* no default value for optional input type */
6180Sstevel@tonic-gate 			fmt_print("[default]");
6190Sstevel@tonic-gate 			break;
6200Sstevel@tonic-gate 		default:
6210Sstevel@tonic-gate 			err_print("Error: unknown input type.\n");
6220Sstevel@tonic-gate 			fullabort();
6230Sstevel@tonic-gate 		}
6240Sstevel@tonic-gate 	}
6250Sstevel@tonic-gate 	/*
6260Sstevel@tonic-gate 	 * Print the delimiter character.
6270Sstevel@tonic-gate 	 */
6280Sstevel@tonic-gate 	fmt_print("%c ", delim);
6290Sstevel@tonic-gate 	/*
6300Sstevel@tonic-gate 	 * Get the token.  If we hit eof, exit the program gracefully.
6310Sstevel@tonic-gate 	 */
6320Sstevel@tonic-gate 	if (gettoken(token) == NULL)
6330Sstevel@tonic-gate 		fullabort();
6340Sstevel@tonic-gate 
6350Sstevel@tonic-gate 	/*
6360Sstevel@tonic-gate 	 * check if the user has issued (!) , escape to shell
6370Sstevel@tonic-gate 	 */
6380Sstevel@tonic-gate 	if ((cmdflag == CMD_INPUT) && (token[0] == '!')) {
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	    /* get the list of arguments to shell command */
6411383Spr131582 		(void) memset(shell_argv, 0, sizeof (shell_argv));
6421383Spr131582 
6431383Spr131582 		/* initialize to the first token... */
6441383Spr131582 		arg = &token[1];
6451383Spr131582 
6461383Spr131582 		/*
6471383Spr131582 		 * ... and then collect all tokens until the end of
6481383Spr131582 		 * the line as arguments
6491383Spr131582 		 */
6501383Spr131582 		do {
6511383Spr131582 			/* skip empty tokens. */
6521383Spr131582 			if (*arg == '\0')
6531383Spr131582 				continue;
6541383Spr131582 			/*
6551383Spr131582 			 * If either of the following two strlcat()
6561383Spr131582 			 * operations overflows, report an error and
6571383Spr131582 			 * exit gracefully.
6581383Spr131582 			 */
6591383Spr131582 			if ((strlcat(shell_argv, arg, sizeof (shell_argv)) >=
6601383Spr131582 				sizeof (shell_argv)) ||
6611383Spr131582 			    (strlcat(shell_argv, " ", sizeof (shell_argv)) >=
6621383Spr131582 				sizeof (shell_argv))) {
6631383Spr131582 				err_print("Error: Command line too long.\n");
6640Sstevel@tonic-gate 				fullabort();
6650Sstevel@tonic-gate 			}
6661383Spr131582 		} while (token_present && (arg = gettoken(token)) != NULL);
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 		/* execute the shell command */
6691383Spr131582 		(void) execute_shell(shell_argv, sizeof (shell_argv));
6700Sstevel@tonic-gate 		redisplay_menu_list((char **)param->io_charlist);
6710Sstevel@tonic-gate 		if (interactive) {
6720Sstevel@tonic-gate 			goto reprompt;
6730Sstevel@tonic-gate 		}
6740Sstevel@tonic-gate 	}
6750Sstevel@tonic-gate 
6760Sstevel@tonic-gate 	/*
6770Sstevel@tonic-gate 	 * Certain commands accept up to two tokens
6780Sstevel@tonic-gate 	 * Unfortunately, this is kind of a hack.
6790Sstevel@tonic-gate 	 */
6800Sstevel@tonic-gate 	token2[0] = 0;
6810Sstevel@tonic-gate 	cleantoken2[0] = 0;
6820Sstevel@tonic-gate 	if (type == FIO_CYL || type == FIO_ECYL) {
6830Sstevel@tonic-gate 		if (token_present) {
6840Sstevel@tonic-gate 			if (gettoken(token2) == NULL)
6850Sstevel@tonic-gate 				fullabort();
6860Sstevel@tonic-gate 			clean_token(cleantoken2, token2);
6870Sstevel@tonic-gate 		}
6880Sstevel@tonic-gate 	}
6890Sstevel@tonic-gate 	/*
6900Sstevel@tonic-gate 	 * Echo the token back to the user if it was in the pipe or we
6910Sstevel@tonic-gate 	 * are running out of a command file.
6920Sstevel@tonic-gate 	 */
6930Sstevel@tonic-gate 	if (!interactive || option_f) {
6940Sstevel@tonic-gate 		if (token2[0] == 0) {
6950Sstevel@tonic-gate 			fmt_print("%s\n", token);
6960Sstevel@tonic-gate 		} else {
6970Sstevel@tonic-gate 			fmt_print("%s %s\n", token, token2);
6980Sstevel@tonic-gate 		}
6990Sstevel@tonic-gate 	}
7000Sstevel@tonic-gate 	/*
7010Sstevel@tonic-gate 	 * If we are logging, echo the token to the log file.  The else
7020Sstevel@tonic-gate 	 * is necessary here because the above printf will also put the
7030Sstevel@tonic-gate 	 * token in the log file.
7040Sstevel@tonic-gate 	 */
7050Sstevel@tonic-gate 	else if (log_file) {
7060Sstevel@tonic-gate 		log_print("%s %s\n", token, token2);
7070Sstevel@tonic-gate 	}
7080Sstevel@tonic-gate 	/*
7090Sstevel@tonic-gate 	 * If the token was not in the pipe and it wasn't a command, flush
7100Sstevel@tonic-gate 	 * the rest of the line to keep things in sync.
7110Sstevel@tonic-gate 	 */
7120Sstevel@tonic-gate 	if (interactive && cmdflag != CMD_INPUT)
7130Sstevel@tonic-gate 		flushline();
7140Sstevel@tonic-gate 	/*
7150Sstevel@tonic-gate 	 * Scrub off the white-space.
7160Sstevel@tonic-gate 	 */
7170Sstevel@tonic-gate 	clean_token(cleantoken, token);
7180Sstevel@tonic-gate 	/*
7190Sstevel@tonic-gate 	 * If the input was a blank line and we weren't prompting
7200Sstevel@tonic-gate 	 * specifically for a blank line...
7210Sstevel@tonic-gate 	 */
7220Sstevel@tonic-gate 	if ((strcmp(cleantoken, "") == 0) && (type != FIO_BLNK)) {
7230Sstevel@tonic-gate 		/*
7240Sstevel@tonic-gate 		 * If there's a default, return it.
7250Sstevel@tonic-gate 		 */
7260Sstevel@tonic-gate 		if (deflt != NULL) {
7270Sstevel@tonic-gate 			if (type == FIO_OSTR) {
7280Sstevel@tonic-gate 				/*
7290Sstevel@tonic-gate 				 * Duplicate and return the default string
7300Sstevel@tonic-gate 				 */
7310Sstevel@tonic-gate 				return ((int)alloc_string((char *)deflt));
7320Sstevel@tonic-gate 			} else if (type == FIO_SLIST) {
7330Sstevel@tonic-gate 				/*
7340Sstevel@tonic-gate 				 * If we can find a match for the default
7350Sstevel@tonic-gate 				 * value in the list, return the default
7360Sstevel@tonic-gate 				 * value.  If there's no match for the
7370Sstevel@tonic-gate 				 * default value, it's an illegal
7380Sstevel@tonic-gate 				 * choice.  Return the first value in
7390Sstevel@tonic-gate 				 * the list.
7400Sstevel@tonic-gate 				 */
7410Sstevel@tonic-gate 				s = find_string(param->io_slist, *deflt);
7420Sstevel@tonic-gate 				if ((cur_label == L_TYPE_EFI) &&
7430Sstevel@tonic-gate 				    (s == (char *)NULL)) {
7440Sstevel@tonic-gate 					return (*deflt);
7450Sstevel@tonic-gate 				}
7460Sstevel@tonic-gate 				if (s == (char *)NULL) {
7470Sstevel@tonic-gate 					return ((param->io_slist)->value);
7480Sstevel@tonic-gate 				} else {
7490Sstevel@tonic-gate 					return (*deflt);
7500Sstevel@tonic-gate 				}
7510Sstevel@tonic-gate 			} else if (type == FIO_OPINT) {
7520Sstevel@tonic-gate 				/*
7530Sstevel@tonic-gate 				 * The user didn't enter anything
7540Sstevel@tonic-gate 				 */
7550Sstevel@tonic-gate 				return (0);
7560Sstevel@tonic-gate 			} else if (type == FIO_ECYL) {
7570Sstevel@tonic-gate 				return (part_deflt->deflt_size);
7580Sstevel@tonic-gate 			} else if (type == FIO_INT64) {
7590Sstevel@tonic-gate 				return (efi_deflt->start_sector);
7600Sstevel@tonic-gate 			} else if (type == FIO_EFI) {
7610Sstevel@tonic-gate 				return (efi_deflt->end_sector);
7620Sstevel@tonic-gate 			} else {
7630Sstevel@tonic-gate 				return (*deflt);
7640Sstevel@tonic-gate 			}
7650Sstevel@tonic-gate 		}
7660Sstevel@tonic-gate 		/*
7670Sstevel@tonic-gate 		 * If the blank was not in the pipe, just reprompt.
7680Sstevel@tonic-gate 		 */
7690Sstevel@tonic-gate 		if (interactive) {
7700Sstevel@tonic-gate 			goto reprompt;
7710Sstevel@tonic-gate 		}
7720Sstevel@tonic-gate 		/*
7730Sstevel@tonic-gate 		 * If the blank was in the pipe, it's an error.
7740Sstevel@tonic-gate 		 */
7750Sstevel@tonic-gate 		err_print("No default for this entry.\n");
7760Sstevel@tonic-gate 		cmdabort(SIGINT);
7770Sstevel@tonic-gate 	}
7780Sstevel@tonic-gate 	/*
7790Sstevel@tonic-gate 	 * If token is a '?' or a 'h', it is a request for help.
7800Sstevel@tonic-gate 	 */
7810Sstevel@tonic-gate 	if ((strcmp(cleantoken, "?") == 0) ||
7820Sstevel@tonic-gate 		(strcmp(cleantoken, "h") == 0) ||
7830Sstevel@tonic-gate 			(strcmp(cleantoken, "help") == 0)) {
7840Sstevel@tonic-gate 		help = 1;
7850Sstevel@tonic-gate 	}
7860Sstevel@tonic-gate 	/*
7870Sstevel@tonic-gate 	 * Switch on the type of input expected.
7880Sstevel@tonic-gate 	 */
7890Sstevel@tonic-gate 	switch (type) {
7900Sstevel@tonic-gate 	/*
7910Sstevel@tonic-gate 	 * Expecting a disk block number.
7920Sstevel@tonic-gate 	 */
7930Sstevel@tonic-gate 	case FIO_BN:
7940Sstevel@tonic-gate 		/*
7950Sstevel@tonic-gate 		 * Parameter is the bounds of legal block numbers.
7960Sstevel@tonic-gate 		 */
7970Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
7980Sstevel@tonic-gate 		/*
7990Sstevel@tonic-gate 		 * Print help message if required.
8000Sstevel@tonic-gate 		 */
8010Sstevel@tonic-gate 		if (help) {
8020Sstevel@tonic-gate 			fmt_print("Expecting a block number from %llu (",
8030Sstevel@tonic-gate 			    bounds->lower);
8040Sstevel@tonic-gate 			pr_dblock(fmt_print, bounds->lower);
8050Sstevel@tonic-gate 			fmt_print(") to %llu (", bounds->upper);
8060Sstevel@tonic-gate 			pr_dblock(fmt_print, bounds->upper);
8070Sstevel@tonic-gate 			fmt_print(")\n");
8080Sstevel@tonic-gate 			break;
8090Sstevel@tonic-gate 		}
8100Sstevel@tonic-gate 		/*
8110Sstevel@tonic-gate 		 * Convert token to a disk block number.
8120Sstevel@tonic-gate 		 */
8130Sstevel@tonic-gate 		if (cur_label == L_TYPE_EFI) {
8140Sstevel@tonic-gate 		    if (geti64(cleantoken, (uint64_t *)&bn64,
8150Sstevel@tonic-gate 			(uint64_t *)NULL))
8160Sstevel@tonic-gate 			    break;
8170Sstevel@tonic-gate 		} else {
8187563SPrasad.Singamsetty@Sun.COM 		    if (getbn(cleantoken, &bn64))
8190Sstevel@tonic-gate 			break;
8200Sstevel@tonic-gate 		}
8217563SPrasad.Singamsetty@Sun.COM 		/*
8227563SPrasad.Singamsetty@Sun.COM 		 * Check to be sure it is within the legal bounds.
8237563SPrasad.Singamsetty@Sun.COM 		 */
8247563SPrasad.Singamsetty@Sun.COM 		if ((bn64 < bounds->lower) || (bn64 > bounds->upper)) {
8250Sstevel@tonic-gate 			err_print("`");
8260Sstevel@tonic-gate 			pr_dblock(err_print, bn64);
8270Sstevel@tonic-gate 			err_print("' is out of range.\n");
8280Sstevel@tonic-gate 			break;
8290Sstevel@tonic-gate 		}
8300Sstevel@tonic-gate 		/*
8317563SPrasad.Singamsetty@Sun.COM 		 * It's ok, return it.
8320Sstevel@tonic-gate 		 */
8337563SPrasad.Singamsetty@Sun.COM 		return (bn64);
8340Sstevel@tonic-gate 	/*
8350Sstevel@tonic-gate 	 * Expecting an integer.
8360Sstevel@tonic-gate 	 */
8370Sstevel@tonic-gate 	case FIO_INT:
8380Sstevel@tonic-gate 		/*
8390Sstevel@tonic-gate 		 * Parameter is the bounds of legal integers.
8400Sstevel@tonic-gate 		 */
8410Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
8420Sstevel@tonic-gate 		/*
8430Sstevel@tonic-gate 		 * Print help message if required.
8440Sstevel@tonic-gate 		 */
8450Sstevel@tonic-gate 		if (help) {
8460Sstevel@tonic-gate 			fmt_print("Expecting an integer from %llu",
8470Sstevel@tonic-gate 			    bounds->lower);
8480Sstevel@tonic-gate 			fmt_print(" to %llu\n", bounds->upper);
8490Sstevel@tonic-gate 			break;
8500Sstevel@tonic-gate 		}
8510Sstevel@tonic-gate 		/*
8520Sstevel@tonic-gate 		 * Convert the token into an integer.
8530Sstevel@tonic-gate 		 */
8540Sstevel@tonic-gate 		if (geti(cleantoken, (int *)&bn, (int *)NULL))
8550Sstevel@tonic-gate 			break;
8560Sstevel@tonic-gate 		/*
8570Sstevel@tonic-gate 		 * Check to be sure it is within the legal bounds.
8580Sstevel@tonic-gate 		 */
8590Sstevel@tonic-gate 		if ((bn < bounds->lower) || (bn > bounds->upper)) {
8607563SPrasad.Singamsetty@Sun.COM 			err_print("`%lu' is out of range.\n", bn);
8610Sstevel@tonic-gate 			break;
8620Sstevel@tonic-gate 		}
8630Sstevel@tonic-gate 		/*
8640Sstevel@tonic-gate 		 * If it's ok, return it.
8650Sstevel@tonic-gate 		 */
8660Sstevel@tonic-gate 		return (bn);
8670Sstevel@tonic-gate 	case FIO_INT64:
8680Sstevel@tonic-gate 		/*
8690Sstevel@tonic-gate 		 * Parameter is the bounds of legal integers.
8700Sstevel@tonic-gate 		 */
8710Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
8720Sstevel@tonic-gate 		/*
8730Sstevel@tonic-gate 		 * Print help message if required.
8740Sstevel@tonic-gate 		 */
8750Sstevel@tonic-gate 		if (help) {
8760Sstevel@tonic-gate 			fmt_print("Expecting an integer from %llu",
8770Sstevel@tonic-gate 			    bounds->lower);
8780Sstevel@tonic-gate 			fmt_print(" to %llu\n", bounds->upper);
8790Sstevel@tonic-gate 			break;
8800Sstevel@tonic-gate 		}
8810Sstevel@tonic-gate 		/*
8820Sstevel@tonic-gate 		 * Convert the token into an integer.
8830Sstevel@tonic-gate 		 */
8840Sstevel@tonic-gate 		if (geti64(cleantoken, (uint64_t *)&bn64, (uint64_t *)NULL)) {
8850Sstevel@tonic-gate 			break;
8860Sstevel@tonic-gate 		}
8870Sstevel@tonic-gate 		/*
8880Sstevel@tonic-gate 		 * Check to be sure it is within the legal bounds.
8890Sstevel@tonic-gate 		 */
8900Sstevel@tonic-gate 		if ((bn64 < bounds->lower) || (bn64 > bounds->upper)) {
8910Sstevel@tonic-gate 			err_print("`%llu' is out of range.\n", bn64);
8920Sstevel@tonic-gate 			break;
8930Sstevel@tonic-gate 		}
8940Sstevel@tonic-gate 		/*
8950Sstevel@tonic-gate 		 * If it's ok, return it.
8960Sstevel@tonic-gate 		 */
8970Sstevel@tonic-gate 		return (bn64);
8980Sstevel@tonic-gate 	/*
8990Sstevel@tonic-gate 	 * Expecting an integer, or no input.
9000Sstevel@tonic-gate 	 */
9010Sstevel@tonic-gate 	case FIO_OPINT:
9020Sstevel@tonic-gate 		/*
9030Sstevel@tonic-gate 		 * Parameter is the bounds of legal integers.
9040Sstevel@tonic-gate 		 */
9050Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
9060Sstevel@tonic-gate 		/*
9070Sstevel@tonic-gate 		 * Print help message if required.
9080Sstevel@tonic-gate 		 */
9090Sstevel@tonic-gate 		if (help) {
9100Sstevel@tonic-gate 			fmt_print("Expecting an integer from %llu",
9110Sstevel@tonic-gate 			    bounds->lower);
9120Sstevel@tonic-gate 			fmt_print(" to %llu, or no input\n", bounds->upper);
9130Sstevel@tonic-gate 			break;
9140Sstevel@tonic-gate 		}
9150Sstevel@tonic-gate 		/*
9160Sstevel@tonic-gate 		 * Convert the token into an integer.
9170Sstevel@tonic-gate 		 */
9180Sstevel@tonic-gate 		if (geti(cleantoken, (int *)&bn, (int *)NULL))
9190Sstevel@tonic-gate 			break;
9200Sstevel@tonic-gate 		/*
9210Sstevel@tonic-gate 		 * Check to be sure it is within the legal bounds.
9220Sstevel@tonic-gate 		 */
9230Sstevel@tonic-gate 		if ((bn < bounds->lower) || (bn > bounds->upper)) {
9247563SPrasad.Singamsetty@Sun.COM 			err_print("`%lu' is out of range.\n", bn);
9250Sstevel@tonic-gate 			break;
9260Sstevel@tonic-gate 		}
9270Sstevel@tonic-gate 		/*
9280Sstevel@tonic-gate 		 * For optional case, return 1 indicating that
9290Sstevel@tonic-gate 		 * the user actually did enter something.
9300Sstevel@tonic-gate 		 */
9317563SPrasad.Singamsetty@Sun.COM 		if (!deflt)
9327563SPrasad.Singamsetty@Sun.COM 			*deflt = bn;
9330Sstevel@tonic-gate 		return (1);
9340Sstevel@tonic-gate 	/*
9350Sstevel@tonic-gate 	 * Expecting a closed string.  This means that the input
9360Sstevel@tonic-gate 	 * string must exactly match one of the strings passed in
9370Sstevel@tonic-gate 	 * as the parameter.
9380Sstevel@tonic-gate 	 */
9390Sstevel@tonic-gate 	case FIO_CSTR:
9400Sstevel@tonic-gate 		/*
9410Sstevel@tonic-gate 		 * The parameter is a null terminated array of character
9420Sstevel@tonic-gate 		 * pointers, each one pointing to a legal input string.
9430Sstevel@tonic-gate 		 */
9440Sstevel@tonic-gate 		strings = (char **)param->io_charlist;
9450Sstevel@tonic-gate 		/*
9460Sstevel@tonic-gate 		 * Walk through the legal strings, seeing if any of them
9470Sstevel@tonic-gate 		 * match the token.  If a match is made, return the index
9480Sstevel@tonic-gate 		 * of the string that was matched.
9490Sstevel@tonic-gate 		 */
9500Sstevel@tonic-gate 		for (str = strings; *str != NULL; str++)
9510Sstevel@tonic-gate 			if (strcmp(cleantoken, *str) == 0)
9520Sstevel@tonic-gate 				return (str - strings);
9530Sstevel@tonic-gate 		/*
9540Sstevel@tonic-gate 		 * Print help message if required.
9550Sstevel@tonic-gate 		 */
9560Sstevel@tonic-gate 		if (help) {
9570Sstevel@tonic-gate 			print_input_choices(type, param);
9580Sstevel@tonic-gate 		} else {
9590Sstevel@tonic-gate 			err_print("`%s' is not expected.\n", cleantoken);
9600Sstevel@tonic-gate 		}
9610Sstevel@tonic-gate 		break;
9620Sstevel@tonic-gate 	/*
9630Sstevel@tonic-gate 	 * Expecting a matched string.  This means that the input
9640Sstevel@tonic-gate 	 * string must either match one of the strings passed in,
9650Sstevel@tonic-gate 	 * or be a unique abbreviation of one of them.
9660Sstevel@tonic-gate 	 */
9670Sstevel@tonic-gate 	case FIO_MSTR:
9680Sstevel@tonic-gate 		/*
9690Sstevel@tonic-gate 		 * The parameter is a null terminated array of character
9700Sstevel@tonic-gate 		 * pointers, each one pointing to a legal input string.
9710Sstevel@tonic-gate 		 */
9720Sstevel@tonic-gate 		strings = (char **)param->io_charlist;
9730Sstevel@tonic-gate 		length = index = tied = 0;
9740Sstevel@tonic-gate 		/*
9750Sstevel@tonic-gate 		 * Loop through the legal input strings.
9760Sstevel@tonic-gate 		 */
9770Sstevel@tonic-gate 		for (str = strings; *str != NULL; str++) {
9780Sstevel@tonic-gate 			/*
9790Sstevel@tonic-gate 			 * See how many characters of the token match
9800Sstevel@tonic-gate 			 * this legal string.
9810Sstevel@tonic-gate 			 */
9820Sstevel@tonic-gate 			i = strcnt(cleantoken, *str);
9830Sstevel@tonic-gate 			/*
9840Sstevel@tonic-gate 			 * If it's not the whole token, then it's not a match.
9850Sstevel@tonic-gate 			 */
9860Sstevel@tonic-gate 			if ((uint_t)i < strlen(cleantoken))
9870Sstevel@tonic-gate 				continue;
9880Sstevel@tonic-gate 			/*
9890Sstevel@tonic-gate 			 * If it ties with another input, remember that.
9900Sstevel@tonic-gate 			 */
9910Sstevel@tonic-gate 			if (i == length)
9920Sstevel@tonic-gate 				tied = 1;
9930Sstevel@tonic-gate 			/*
9940Sstevel@tonic-gate 			 * If it matches the most so far, record that.
9950Sstevel@tonic-gate 			 */
9960Sstevel@tonic-gate 			if (i > length) {
9970Sstevel@tonic-gate 				index = str - strings;
9980Sstevel@tonic-gate 				tied = 0;
9990Sstevel@tonic-gate 				length = i;
10000Sstevel@tonic-gate 			}
10010Sstevel@tonic-gate 		}
10020Sstevel@tonic-gate 		/*
10030Sstevel@tonic-gate 		 * Print help message if required.
10040Sstevel@tonic-gate 		 */
10050Sstevel@tonic-gate 		if (length == 0) {
10060Sstevel@tonic-gate 			if (help) {
10070Sstevel@tonic-gate 				print_input_choices(type, param);
10080Sstevel@tonic-gate 			} else {
10090Sstevel@tonic-gate 				err_print("`%s' is not expected.\n",
10100Sstevel@tonic-gate 				    cleantoken);
10110Sstevel@tonic-gate 			}
10120Sstevel@tonic-gate 			break;
10130Sstevel@tonic-gate 		}
10140Sstevel@tonic-gate 		/*
10150Sstevel@tonic-gate 		 * If the abbreviation was non-unique, it's an error.
10160Sstevel@tonic-gate 		 */
10170Sstevel@tonic-gate 		if (tied) {
10180Sstevel@tonic-gate 			err_print("`%s' is ambiguous.\n", cleantoken);
10190Sstevel@tonic-gate 			break;
10200Sstevel@tonic-gate 		}
10210Sstevel@tonic-gate 		/*
10220Sstevel@tonic-gate 		 * We matched one.  Return the index of the string we matched.
10230Sstevel@tonic-gate 		 */
10240Sstevel@tonic-gate 		return (index);
10250Sstevel@tonic-gate 	/*
10260Sstevel@tonic-gate 	 * Expecting an open string.  This means that any string is legal.
10270Sstevel@tonic-gate 	 */
10280Sstevel@tonic-gate 	case FIO_OSTR:
10290Sstevel@tonic-gate 		/*
10300Sstevel@tonic-gate 		 * Print a help message if required.
10310Sstevel@tonic-gate 		 */
10320Sstevel@tonic-gate 		if (help) {
10330Sstevel@tonic-gate 			fmt_print("Expecting a string\n");
10340Sstevel@tonic-gate 			break;
10350Sstevel@tonic-gate 		}
10360Sstevel@tonic-gate 		/*
10370Sstevel@tonic-gate 		 * alloc a copy of the string and return it
10380Sstevel@tonic-gate 		 */
10390Sstevel@tonic-gate 		return ((int)alloc_string(token));
10400Sstevel@tonic-gate 
10410Sstevel@tonic-gate 	/*
10420Sstevel@tonic-gate 	 * Expecting a blank line.
10430Sstevel@tonic-gate 	 */
10440Sstevel@tonic-gate 	case FIO_BLNK:
10450Sstevel@tonic-gate 		/*
10460Sstevel@tonic-gate 		 * We are always in non-echo mode when we are inputting
10470Sstevel@tonic-gate 		 * this type.  We echo the newline as a carriage return
10480Sstevel@tonic-gate 		 * only so the prompt string will be covered over.
10490Sstevel@tonic-gate 		 */
10500Sstevel@tonic-gate 		nolog_print("\015");
10510Sstevel@tonic-gate 		/*
10520Sstevel@tonic-gate 		 * If we are logging, send a newline to the log file.
10530Sstevel@tonic-gate 		 */
10540Sstevel@tonic-gate 		if (log_file)
10550Sstevel@tonic-gate 			log_print("\n");
10560Sstevel@tonic-gate 		/*
10570Sstevel@tonic-gate 		 * There is no value returned for this type.
10580Sstevel@tonic-gate 		 */
10590Sstevel@tonic-gate 		return (0);
10600Sstevel@tonic-gate 
10610Sstevel@tonic-gate 	/*
10620Sstevel@tonic-gate 	 * Expecting one of the entries in a string list.
10630Sstevel@tonic-gate 	 * Accept unique abbreviations.
10640Sstevel@tonic-gate 	 * Return the value associated with the matched string.
10650Sstevel@tonic-gate 	 */
10660Sstevel@tonic-gate 	case FIO_SLIST:
10670Sstevel@tonic-gate 		i = find_value((slist_t *)param->io_slist,
10680Sstevel@tonic-gate 			cleantoken, &value);
10690Sstevel@tonic-gate 		if (i == 1) {
10700Sstevel@tonic-gate 			return (value);
10710Sstevel@tonic-gate 		} else {
10720Sstevel@tonic-gate 			/*
10730Sstevel@tonic-gate 			 * Print help message if required.
10740Sstevel@tonic-gate 			 */
10750Sstevel@tonic-gate 
10760Sstevel@tonic-gate 			if (help) {
10770Sstevel@tonic-gate 				print_input_choices(type, param);
10780Sstevel@tonic-gate 			} else {
10790Sstevel@tonic-gate 				if (i == 0)
10800Sstevel@tonic-gate 					err_print("`%s' not expected.\n",
10810Sstevel@tonic-gate 					    cleantoken);
10820Sstevel@tonic-gate 				else
10830Sstevel@tonic-gate 					err_print("`%s' is ambiguous.\n",
10840Sstevel@tonic-gate 					    cleantoken);
10850Sstevel@tonic-gate 			}
10860Sstevel@tonic-gate 		}
10870Sstevel@tonic-gate 		break;
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate 	/*
10900Sstevel@tonic-gate 	 * Cylinder size input when modifying a complete partition map
10910Sstevel@tonic-gate 	 */
10920Sstevel@tonic-gate 	case FIO_CYL:
10930Sstevel@tonic-gate 		/*
10940Sstevel@tonic-gate 		 * Parameter is the bounds of legal block numbers.
10950Sstevel@tonic-gate 		 */
10960Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
10970Sstevel@tonic-gate 		assert(bounds->lower == 0);
10980Sstevel@tonic-gate 		/*
10990Sstevel@tonic-gate 		 * Print help message if required.
11000Sstevel@tonic-gate 		 */
11010Sstevel@tonic-gate 		if (help) {
11020Sstevel@tonic-gate 			fmt_print("Expecting up to %llu blocks,",
11030Sstevel@tonic-gate 			    bounds->upper);
11047563SPrasad.Singamsetty@Sun.COM 			fmt_print(" %u cylinders, ", bn2c(bounds->upper));
11050Sstevel@tonic-gate 			fmt_print(" %1.2f megabytes, ", bn2mb(bounds->upper));
11060Sstevel@tonic-gate 			fmt_print("or %1.2f gigabytes\n", bn2gb(bounds->upper));
11070Sstevel@tonic-gate 			break;
11080Sstevel@tonic-gate 		}
11090Sstevel@tonic-gate 		/*
11100Sstevel@tonic-gate 		 * Parse the first token: try to find 'b', 'c' or 'm'
11110Sstevel@tonic-gate 		 */
11120Sstevel@tonic-gate 		s = cleantoken;
11130Sstevel@tonic-gate 		while (*s && (isdigit(*s) || (*s == '.') || (*s == '$'))) {
11140Sstevel@tonic-gate 			s++;
11150Sstevel@tonic-gate 		}
11160Sstevel@tonic-gate 		/*
11170Sstevel@tonic-gate 		 * If we found a conversion specifier, second token is unused
11180Sstevel@tonic-gate 		 * Otherwise, the second token should supply it.
11190Sstevel@tonic-gate 		 */
11200Sstevel@tonic-gate 		if (*s != 0) {
11210Sstevel@tonic-gate 			value = *s;
11220Sstevel@tonic-gate 			*s = 0;
11230Sstevel@tonic-gate 		} else {
11240Sstevel@tonic-gate 			value = cleantoken2[0];
11250Sstevel@tonic-gate 		}
11260Sstevel@tonic-gate 		/*
11270Sstevel@tonic-gate 		 * If the token is the wild card, simply supply the max
11280Sstevel@tonic-gate 		 * This order allows the user to specify the maximum in
11290Sstevel@tonic-gate 		 * either blocks/cyls/megabytes - a convenient fiction.
11300Sstevel@tonic-gate 		 */
11310Sstevel@tonic-gate 		if (strcmp(cleantoken, WILD_STRING) == 0) {
11320Sstevel@tonic-gate 			return (bounds->upper);
11330Sstevel@tonic-gate 		}
11340Sstevel@tonic-gate 		/*
11350Sstevel@tonic-gate 		 * Allow the user to specify zero with no units,
11360Sstevel@tonic-gate 		 * by just defaulting to cylinders.
11370Sstevel@tonic-gate 		 */
11380Sstevel@tonic-gate 		if (strcmp(cleantoken, "0") == 0) {
11390Sstevel@tonic-gate 			value = 'c';
11400Sstevel@tonic-gate 		}
11410Sstevel@tonic-gate 		/*
11420Sstevel@tonic-gate 		 * If there's a decimal point, but no unit specification,
11430Sstevel@tonic-gate 		 * let's assume megabytes.
11440Sstevel@tonic-gate 		 */
11450Sstevel@tonic-gate 		if ((value == 0) && (strchr(cleantoken, '.') != NULL)) {
11460Sstevel@tonic-gate 			value = 'm';
11470Sstevel@tonic-gate 		}
11480Sstevel@tonic-gate 		/*
11490Sstevel@tonic-gate 		 * Handle each unit type we support
11500Sstevel@tonic-gate 		 */
11510Sstevel@tonic-gate 		switch (value) {
11520Sstevel@tonic-gate 		case 'b':
11530Sstevel@tonic-gate 			/*
11540Sstevel@tonic-gate 			 * Convert token to a disk block number.
11550Sstevel@tonic-gate 			 */
11567563SPrasad.Singamsetty@Sun.COM 			if (geti64(cleantoken, &bn64, &bounds->upper))
11570Sstevel@tonic-gate 				break;
11580Sstevel@tonic-gate 			/*
11590Sstevel@tonic-gate 			 * Check to be sure it is within the legal bounds.
11600Sstevel@tonic-gate 			 */
11617563SPrasad.Singamsetty@Sun.COM 			if ((bn64 < bounds->lower) || (bn64 > bounds->upper)) {
11620Sstevel@tonic-gate 				err_print(
11637563SPrasad.Singamsetty@Sun.COM 				    "`%llub' is out of the range %llu "
11647563SPrasad.Singamsetty@Sun.COM 				    "to %llu\n",
11657563SPrasad.Singamsetty@Sun.COM 				    bn64, bounds->lower, bounds->upper);
11660Sstevel@tonic-gate 				break;
11670Sstevel@tonic-gate 			}
11680Sstevel@tonic-gate 			/*
11690Sstevel@tonic-gate 			 * Verify the block lies on a cylinder boundary
11700Sstevel@tonic-gate 			 */
11717563SPrasad.Singamsetty@Sun.COM 			if ((bn64 % spc()) != 0) {
11720Sstevel@tonic-gate 				err_print(
11737563SPrasad.Singamsetty@Sun.COM 				    "partition size must be a multiple of "
11747563SPrasad.Singamsetty@Sun.COM 				    "%u blocks to lie on a cylinder boundary\n",
11750Sstevel@tonic-gate 				    spc());
11760Sstevel@tonic-gate 				err_print(
11777563SPrasad.Singamsetty@Sun.COM 				    "%llu blocks is approximately %u cylinders,"
11787563SPrasad.Singamsetty@Sun.COM 				    " %1.2f megabytes or %1.2f gigabytes\n",
11797563SPrasad.Singamsetty@Sun.COM 				    bn64, bn2c(bn64), bn2mb(bn64), bn2gb(bn64));
11800Sstevel@tonic-gate 				break;
11810Sstevel@tonic-gate 			}
11827563SPrasad.Singamsetty@Sun.COM 			return (bn64);
11830Sstevel@tonic-gate 		case 'c':
11840Sstevel@tonic-gate 			/*
11850Sstevel@tonic-gate 			 * Convert token from a number of cylinders to
11860Sstevel@tonic-gate 			 * a number of blocks.
11870Sstevel@tonic-gate 			 */
11880Sstevel@tonic-gate 			i = bn2c(bounds->upper);
11890Sstevel@tonic-gate 			if (geti(cleantoken, &cyls, &i))
11900Sstevel@tonic-gate 				break;
11910Sstevel@tonic-gate 			/*
11920Sstevel@tonic-gate 			 * Check the bounds - cyls is number of cylinders
11930Sstevel@tonic-gate 			 */
11940Sstevel@tonic-gate 			if (cyls > (bounds->upper/spc())) {
11950Sstevel@tonic-gate 				err_print("`%dc' is out of range\n", cyls);
11960Sstevel@tonic-gate 				break;
11970Sstevel@tonic-gate 			}
11980Sstevel@tonic-gate 			/*
11990Sstevel@tonic-gate 			 * Convert cylinders to blocks and return
12000Sstevel@tonic-gate 			 */
12010Sstevel@tonic-gate 			return (cyls * spc());
12020Sstevel@tonic-gate 		case 'm':
12030Sstevel@tonic-gate 			/*
12040Sstevel@tonic-gate 			 * Convert token from megabytes to a block number.
12050Sstevel@tonic-gate 			 */
12064429Sbz211116 			if (sscanf(cleantoken, "%f2", &nmegs) != 1) {
12070Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
12080Sstevel@tonic-gate 				    cleantoken);
12090Sstevel@tonic-gate 				break;
12100Sstevel@tonic-gate 			}
12110Sstevel@tonic-gate 			/*
12120Sstevel@tonic-gate 			 * Check the bounds
12130Sstevel@tonic-gate 			 */
12140Sstevel@tonic-gate 			if (nmegs > bn2mb(bounds->upper)) {
12150Sstevel@tonic-gate 				err_print("`%1.2fmb' is out of range\n", nmegs);
12160Sstevel@tonic-gate 				break;
12170Sstevel@tonic-gate 			}
12180Sstevel@tonic-gate 			/*
12190Sstevel@tonic-gate 			 * Convert to blocks
12200Sstevel@tonic-gate 			 */
12217563SPrasad.Singamsetty@Sun.COM 			bn64 = mb2bn(nmegs);
12220Sstevel@tonic-gate 			/*
12230Sstevel@tonic-gate 			 * Round value up to nearest cylinder
12240Sstevel@tonic-gate 			 */
12250Sstevel@tonic-gate 			i = spc();
12267563SPrasad.Singamsetty@Sun.COM 			bn64 = ((bn64 + (i-1)) / i) * i;
12277563SPrasad.Singamsetty@Sun.COM 			return (bn64);
12280Sstevel@tonic-gate 		case 'g':
12290Sstevel@tonic-gate 			/*
12300Sstevel@tonic-gate 			 * Convert token from gigabytes to a block number.
12310Sstevel@tonic-gate 			 */
12324429Sbz211116 			if (sscanf(cleantoken, "%f2", &ngigs) != 1) {
12330Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
12340Sstevel@tonic-gate 				    cleantoken);
12350Sstevel@tonic-gate 				break;
12360Sstevel@tonic-gate 			}
12370Sstevel@tonic-gate 			/*
12380Sstevel@tonic-gate 			 * Check the bounds
12390Sstevel@tonic-gate 			 */
12400Sstevel@tonic-gate 			if (ngigs > bn2gb(bounds->upper)) {
12410Sstevel@tonic-gate 				err_print("`%1.2fgb' is out of range\n", ngigs);
12420Sstevel@tonic-gate 				break;
12430Sstevel@tonic-gate 			}
12440Sstevel@tonic-gate 			/*
12450Sstevel@tonic-gate 			 * Convert to blocks
12460Sstevel@tonic-gate 			 */
12477563SPrasad.Singamsetty@Sun.COM 			bn64 = gb2bn(ngigs);
12480Sstevel@tonic-gate 			/*
12490Sstevel@tonic-gate 			 * Round value up to nearest cylinder
12500Sstevel@tonic-gate 			 */
12510Sstevel@tonic-gate 			i = spc();
12527563SPrasad.Singamsetty@Sun.COM 			bn64 = ((bn64 + (i-1)) / i) * i;
12537563SPrasad.Singamsetty@Sun.COM 			return (bn64);
12540Sstevel@tonic-gate 		default:
12550Sstevel@tonic-gate 			err_print(
12560Sstevel@tonic-gate "Please specify units in either b(blocks), c(cylinders), m(megabytes) \
12570Sstevel@tonic-gate or g(gigabytes)\n");
12580Sstevel@tonic-gate 			break;
12590Sstevel@tonic-gate 		}
12600Sstevel@tonic-gate 		break;
12610Sstevel@tonic-gate 
12620Sstevel@tonic-gate 	case FIO_ECYL:
12630Sstevel@tonic-gate 		/*
12640Sstevel@tonic-gate 		 * Parameter is the bounds of legal block numbers.
12650Sstevel@tonic-gate 		 */
12660Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
12670Sstevel@tonic-gate 		assert(bounds->lower == 0);
12680Sstevel@tonic-gate 
12690Sstevel@tonic-gate 		/*
12700Sstevel@tonic-gate 		 * Print help message if required.
12710Sstevel@tonic-gate 		 */
12720Sstevel@tonic-gate 		if (help) {
12730Sstevel@tonic-gate 			fmt_print("Expecting up to %llu blocks,",
12740Sstevel@tonic-gate 			    bounds->upper);
12757563SPrasad.Singamsetty@Sun.COM 			fmt_print(" %u cylinders, ",
12760Sstevel@tonic-gate 			    bn2c(bounds->upper));
12777563SPrasad.Singamsetty@Sun.COM 			fmt_print(" %u end cylinder, ",
12787563SPrasad.Singamsetty@Sun.COM 			    (uint_t)(bounds->upper / spc()));
12790Sstevel@tonic-gate 			fmt_print(" %1.2f megabytes, ",
12800Sstevel@tonic-gate 			    bn2mb(bounds->upper));
12810Sstevel@tonic-gate 			fmt_print("or %1.2f gigabytes\n",
12820Sstevel@tonic-gate 			    bn2gb(bounds->upper));
12830Sstevel@tonic-gate 			break;
12840Sstevel@tonic-gate 		}
12850Sstevel@tonic-gate 
12860Sstevel@tonic-gate 		/*
12870Sstevel@tonic-gate 		 * Parse the first token: try to find 'b', 'c', 'e'
12880Sstevel@tonic-gate 		 * or 'm'
12890Sstevel@tonic-gate 		 */
12900Sstevel@tonic-gate 		s = cleantoken;
12910Sstevel@tonic-gate 		while (*s && (isdigit(*s) || (*s == '.') || (*s == '$'))) {
12920Sstevel@tonic-gate 			s++;
12930Sstevel@tonic-gate 		}
12940Sstevel@tonic-gate 
12950Sstevel@tonic-gate 		/*
12960Sstevel@tonic-gate 		 * If we found a conversion specifier, second token is
12970Sstevel@tonic-gate 		 * unused Otherwise, the second token should supply it.
12980Sstevel@tonic-gate 		 */
12990Sstevel@tonic-gate 		if (*s != 0) {
13000Sstevel@tonic-gate 			value = *s;
13010Sstevel@tonic-gate 			*s = 0;
13020Sstevel@tonic-gate 		} else {
13030Sstevel@tonic-gate 			value = cleantoken2[0];
13040Sstevel@tonic-gate 		}
13050Sstevel@tonic-gate 
13060Sstevel@tonic-gate 		/*
13070Sstevel@tonic-gate 		 * If the token is the wild card, simply supply the max
13080Sstevel@tonic-gate 		 * This order allows the user to specify the maximum in
13090Sstevel@tonic-gate 		 * either blocks/cyls/megabytes - a convenient fiction.
13100Sstevel@tonic-gate 		 */
13110Sstevel@tonic-gate 		if (strcmp(cleantoken, WILD_STRING) == 0) {
13120Sstevel@tonic-gate 			return (bounds->upper);
13130Sstevel@tonic-gate 		}
13140Sstevel@tonic-gate 
13150Sstevel@tonic-gate 		/*
13160Sstevel@tonic-gate 		 * Allow the user to specify zero with no units,
13170Sstevel@tonic-gate 		 * by just defaulting to cylinders.
13180Sstevel@tonic-gate 		 */
13190Sstevel@tonic-gate 
13200Sstevel@tonic-gate 		if (value != 'e' && strcmp(cleantoken, "0") == 0) {
13210Sstevel@tonic-gate 			value = 'c';
13220Sstevel@tonic-gate 		}
13230Sstevel@tonic-gate 
13240Sstevel@tonic-gate 
13250Sstevel@tonic-gate 		/*
13260Sstevel@tonic-gate 		 * If there's a decimal point, but no unit
13270Sstevel@tonic-gate 		 * specification, let's assume megabytes.
13280Sstevel@tonic-gate 		 */
13290Sstevel@tonic-gate 		if ((value == 0) && (strchr(cleantoken, '.') != NULL)) {
13300Sstevel@tonic-gate 			value = 'm';
13310Sstevel@tonic-gate 		}
13320Sstevel@tonic-gate 
13330Sstevel@tonic-gate 		/*
13340Sstevel@tonic-gate 		 * Handle each unit type we support
13350Sstevel@tonic-gate 		 */
13360Sstevel@tonic-gate 		switch (value) {
13370Sstevel@tonic-gate 		case 'b':
13380Sstevel@tonic-gate 			/*
13390Sstevel@tonic-gate 			 * Convert token to a disk block number.
13400Sstevel@tonic-gate 			 */
13417563SPrasad.Singamsetty@Sun.COM 			if (geti64(cleantoken, &bn64, &bounds->upper))
13420Sstevel@tonic-gate 				break;
13430Sstevel@tonic-gate 			/*
13440Sstevel@tonic-gate 			 * Check to be sure it is within the
13450Sstevel@tonic-gate 			 * legal bounds.
13460Sstevel@tonic-gate 			 */
13477563SPrasad.Singamsetty@Sun.COM 			if ((bn64 < bounds->lower) || (bn64 > bounds->upper)) {
13480Sstevel@tonic-gate 				err_print(
13497563SPrasad.Singamsetty@Sun.COM "`%llub' is out of the range %llu to %llu\n",
13507563SPrasad.Singamsetty@Sun.COM 				    bn64, bounds->lower, bounds->upper);
13510Sstevel@tonic-gate 				break;
13520Sstevel@tonic-gate 			}
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate 			/*
13550Sstevel@tonic-gate 			 * Verify the block lies on a cylinder
13560Sstevel@tonic-gate 			 * boundary
13570Sstevel@tonic-gate 			 */
13587563SPrasad.Singamsetty@Sun.COM 			if ((bn64 % spc()) != 0) {
13590Sstevel@tonic-gate 				err_print(
13607563SPrasad.Singamsetty@Sun.COM 				    "partition size must be a multiple of %u "
13617563SPrasad.Singamsetty@Sun.COM 				    "blocks to lie on a cylinder boundary\n",
13620Sstevel@tonic-gate 				    spc());
13630Sstevel@tonic-gate 				err_print(
13647563SPrasad.Singamsetty@Sun.COM 				    "%llu blocks is approximately %u cylinders,"
13657563SPrasad.Singamsetty@Sun.COM 				    " %1.2f megabytes or %1.2f gigabytes\n",
13667563SPrasad.Singamsetty@Sun.COM 				    bn64, bn2c(bn64), bn2mb(bn64), bn2gb(bn64));
13670Sstevel@tonic-gate 				break;
13680Sstevel@tonic-gate 			}
13690Sstevel@tonic-gate 
13707563SPrasad.Singamsetty@Sun.COM 			return (bn64);
13710Sstevel@tonic-gate 
13720Sstevel@tonic-gate 		case 'e':
13730Sstevel@tonic-gate 			/*
13740Sstevel@tonic-gate 			 * Token is ending cylinder
13750Sstevel@tonic-gate 			 */
13760Sstevel@tonic-gate 
13770Sstevel@tonic-gate 			/* convert token to integer */
13780Sstevel@tonic-gate 			if (geti(cleantoken, &cylno, (int *)NULL)) {
13790Sstevel@tonic-gate 				break;
13800Sstevel@tonic-gate 			}
13810Sstevel@tonic-gate 
13820Sstevel@tonic-gate 			/*
13830Sstevel@tonic-gate 			 * check that input cylno isn't before the current
13840Sstevel@tonic-gate 			 * starting cylinder number.  Note that we are NOT
13850Sstevel@tonic-gate 			 * using the starting cylinder from
13860Sstevel@tonic-gate 			 * cur_parts->pinfo_map[].dkl_cylno!
13870Sstevel@tonic-gate 			 */
13880Sstevel@tonic-gate 			if (cylno < part_deflt->start_cyl) {
13890Sstevel@tonic-gate 				err_print(
13907563SPrasad.Singamsetty@Sun.COM "End cylinder must fall on or after start cylinder %u\n",
13910Sstevel@tonic-gate 				    part_deflt->start_cyl);
13920Sstevel@tonic-gate 				break;
13930Sstevel@tonic-gate 			}
13940Sstevel@tonic-gate 
13950Sstevel@tonic-gate 			/*
13960Sstevel@tonic-gate 			 * calculate cylinder number of upper boundary, and
13970Sstevel@tonic-gate 			 * verify that our input is within range
13980Sstevel@tonic-gate 			 */
13990Sstevel@tonic-gate 			i = (bn2c(bounds->upper) + part_deflt->start_cyl - 1);
14000Sstevel@tonic-gate 
14010Sstevel@tonic-gate 			if (cylno > i) {
14020Sstevel@tonic-gate 				err_print(
14030Sstevel@tonic-gate "End cylinder %d is beyond max cylinder %d\n",
14040Sstevel@tonic-gate 				    cylno, i);
14050Sstevel@tonic-gate 				break;
14060Sstevel@tonic-gate 			}
14070Sstevel@tonic-gate 
14080Sstevel@tonic-gate 			/*
14090Sstevel@tonic-gate 			 * calculate number of cylinders based on input
14100Sstevel@tonic-gate 			 */
14110Sstevel@tonic-gate 			cyls = ((cylno - part_deflt->start_cyl) + 1);
14120Sstevel@tonic-gate 
14130Sstevel@tonic-gate 			return (cyls * spc());
14140Sstevel@tonic-gate 
14150Sstevel@tonic-gate 		case 'c':
14160Sstevel@tonic-gate 			/*
14170Sstevel@tonic-gate 			 * Convert token from a number of
14180Sstevel@tonic-gate 			 * cylinders to a number of blocks.
14190Sstevel@tonic-gate 			 */
14200Sstevel@tonic-gate 			i = bn2c(bounds->upper);
14210Sstevel@tonic-gate 			if (geti(cleantoken, &cyls, &i))
14220Sstevel@tonic-gate 				break;
14230Sstevel@tonic-gate 
14240Sstevel@tonic-gate 			/*
14250Sstevel@tonic-gate 			 * Check the bounds - cyls is number of
14260Sstevel@tonic-gate 			 * cylinders
14270Sstevel@tonic-gate 			 */
14280Sstevel@tonic-gate 			if (cyls > (bounds->upper/spc())) {
14290Sstevel@tonic-gate 				err_print("`%dc' is out of range\n", cyls);
14300Sstevel@tonic-gate 				break;
14310Sstevel@tonic-gate 			}
14320Sstevel@tonic-gate 
14330Sstevel@tonic-gate 			/*
14340Sstevel@tonic-gate 			 * Convert cylinders to blocks and
14350Sstevel@tonic-gate 			 * return
14360Sstevel@tonic-gate 			 */
14370Sstevel@tonic-gate 			return (cyls * spc());
14380Sstevel@tonic-gate 
14390Sstevel@tonic-gate 		case 'm':
14400Sstevel@tonic-gate 			/*
14410Sstevel@tonic-gate 			 * Convert token from megabytes to a
14420Sstevel@tonic-gate 			 * block number.
14430Sstevel@tonic-gate 			 */
14444429Sbz211116 			if (sscanf(cleantoken, "%f2", &nmegs) != 1) {
14450Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
14460Sstevel@tonic-gate 				    cleantoken);
14470Sstevel@tonic-gate 				break;
14480Sstevel@tonic-gate 			}
14490Sstevel@tonic-gate 
14500Sstevel@tonic-gate 			/*
14510Sstevel@tonic-gate 			 * Check the bounds
14520Sstevel@tonic-gate 			 */
14530Sstevel@tonic-gate 			if (nmegs > bn2mb(bounds->upper)) {
14540Sstevel@tonic-gate 				err_print("`%1.2fmb' is out of range\n", nmegs);
14550Sstevel@tonic-gate 				break;
14560Sstevel@tonic-gate 			}
14570Sstevel@tonic-gate 
14580Sstevel@tonic-gate 			/*
14590Sstevel@tonic-gate 			 * Convert to blocks
14600Sstevel@tonic-gate 			 */
14617563SPrasad.Singamsetty@Sun.COM 			bn64 = mb2bn(nmegs);
14620Sstevel@tonic-gate 
14630Sstevel@tonic-gate 			/*
14640Sstevel@tonic-gate 			 * Round value up to nearest cylinder
14650Sstevel@tonic-gate 			 */
14660Sstevel@tonic-gate 			i = spc();
14677563SPrasad.Singamsetty@Sun.COM 			bn64 = ((bn64 + (i-1)) / i) * i;
14687563SPrasad.Singamsetty@Sun.COM 			return (bn64);
14690Sstevel@tonic-gate 
14700Sstevel@tonic-gate 		case 'g':
14710Sstevel@tonic-gate 			/*
14720Sstevel@tonic-gate 			 * Convert token from gigabytes to a
14730Sstevel@tonic-gate 			 * block number.
14740Sstevel@tonic-gate 			 */
14754429Sbz211116 			if (sscanf(cleantoken, "%f2", &ngigs) != 1) {
14760Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
14770Sstevel@tonic-gate 				    cleantoken);
14780Sstevel@tonic-gate 				break;
14790Sstevel@tonic-gate 			}
14800Sstevel@tonic-gate 
14810Sstevel@tonic-gate 			/*
14820Sstevel@tonic-gate 			 * Check the bounds
14830Sstevel@tonic-gate 			 */
14840Sstevel@tonic-gate 			if (ngigs > bn2gb(bounds->upper)) {
14850Sstevel@tonic-gate 				err_print("`%1.2fgb' is out of range\n", ngigs);
14860Sstevel@tonic-gate 				break;
14870Sstevel@tonic-gate 			}
14880Sstevel@tonic-gate 
14890Sstevel@tonic-gate 			/*
14900Sstevel@tonic-gate 			 * Convert to blocks
14910Sstevel@tonic-gate 			 */
14927563SPrasad.Singamsetty@Sun.COM 			bn64 = gb2bn(ngigs);
14930Sstevel@tonic-gate 
14940Sstevel@tonic-gate 			/*
14950Sstevel@tonic-gate 			 * Round value up to nearest cylinder
14960Sstevel@tonic-gate 			 */
14970Sstevel@tonic-gate 			i = spc();
14987563SPrasad.Singamsetty@Sun.COM 			bn64 = ((bn64 + (i-1)) / i) * i;
14997563SPrasad.Singamsetty@Sun.COM 			return (bn64);
15000Sstevel@tonic-gate 
15010Sstevel@tonic-gate 		default:
15020Sstevel@tonic-gate 			err_print(
15030Sstevel@tonic-gate "Please specify units in either b(blocks), c(cylinders), e(end cylinder),\n");
15040Sstevel@tonic-gate 			err_print("m(megabytes) or g(gigabytes)\n");
15050Sstevel@tonic-gate 			break;
15060Sstevel@tonic-gate 		}
15070Sstevel@tonic-gate 		break;
15080Sstevel@tonic-gate 	case FIO_EFI:
15090Sstevel@tonic-gate 		/*
15100Sstevel@tonic-gate 		 * Parameter is the bounds of legal block numbers.
15110Sstevel@tonic-gate 		 */
15120Sstevel@tonic-gate 		bounds = (struct bounds *)&param->io_bounds;
15130Sstevel@tonic-gate 
15140Sstevel@tonic-gate 		/*
15150Sstevel@tonic-gate 		 * Print help message if required.
15160Sstevel@tonic-gate 		 */
15170Sstevel@tonic-gate 		if (help) {
15180Sstevel@tonic-gate 			fmt_print("Expecting up to %llu sectors,",
15190Sstevel@tonic-gate 			    cur_parts->etoc->efi_last_u_lba);
15200Sstevel@tonic-gate 			fmt_print("or %llu megabytes,",
1521*9889SLarry.Liu@Sun.COM 			    (cur_parts->etoc->efi_last_u_lba * cur_blksz)/
15220Sstevel@tonic-gate 				(1024 * 1024));
15230Sstevel@tonic-gate 			fmt_print("or %llu gigabytes\n",
1524*9889SLarry.Liu@Sun.COM 			    (cur_parts->etoc->efi_last_u_lba * cur_blksz)/
15250Sstevel@tonic-gate 				(1024 * 1024 * 1024));
15260Sstevel@tonic-gate 			fmt_print("or %llu terabytes\n",
1527*9889SLarry.Liu@Sun.COM 			    (cur_parts->etoc->efi_last_u_lba * cur_blksz)/
15280Sstevel@tonic-gate 				((uint64_t)1024 * 1024 * 1024 * 1024));
15290Sstevel@tonic-gate 			break;
15300Sstevel@tonic-gate 		}
15310Sstevel@tonic-gate 
15320Sstevel@tonic-gate 		/*
15330Sstevel@tonic-gate 		 * Parse the first token: try to find 'b', 'c', 'e'
15340Sstevel@tonic-gate 		 * or 'm'
15350Sstevel@tonic-gate 		 */
15360Sstevel@tonic-gate 		s = cleantoken;
15370Sstevel@tonic-gate 		while (*s && (isdigit(*s) || (*s == '.') || (*s == '$'))) {
15380Sstevel@tonic-gate 			s++;
15390Sstevel@tonic-gate 		}
15400Sstevel@tonic-gate 
15410Sstevel@tonic-gate 		/*
15420Sstevel@tonic-gate 		 * If we found a conversion specifier, second token is
15430Sstevel@tonic-gate 		 * unused Otherwise, the second token should supply it.
15440Sstevel@tonic-gate 		 */
15450Sstevel@tonic-gate 		if (*s != 0) {
15460Sstevel@tonic-gate 			value = *s;
15470Sstevel@tonic-gate 			*s = 0;
15480Sstevel@tonic-gate 		} else {
15490Sstevel@tonic-gate 			value = cleantoken2[0];
15500Sstevel@tonic-gate 		}
15510Sstevel@tonic-gate 
15520Sstevel@tonic-gate 		/*
15530Sstevel@tonic-gate 		 * If the token is the wild card, simply supply the max
15540Sstevel@tonic-gate 		 * This order allows the user to specify the maximum in
15550Sstevel@tonic-gate 		 * either blocks/cyls/megabytes - a convenient fiction.
15560Sstevel@tonic-gate 		 */
15570Sstevel@tonic-gate 		if (strcmp(cleantoken, WILD_STRING) == 0) {
15580Sstevel@tonic-gate 			return (bounds->upper - EFI_MIN_RESV_SIZE -
15590Sstevel@tonic-gate 			    efi_deflt->start_sector);
15600Sstevel@tonic-gate 		}
15610Sstevel@tonic-gate 
15620Sstevel@tonic-gate 		/*
15630Sstevel@tonic-gate 		 * Allow the user to specify zero with no units,
15640Sstevel@tonic-gate 		 * by just defaulting to sectors.
15650Sstevel@tonic-gate 		 */
15660Sstevel@tonic-gate 
15670Sstevel@tonic-gate 		if (value != 'e' && strcmp(cleantoken, "0") == 0) {
15680Sstevel@tonic-gate 			value = 'm';
15690Sstevel@tonic-gate 		}
15700Sstevel@tonic-gate 
15710Sstevel@tonic-gate 
15720Sstevel@tonic-gate 		/*
15730Sstevel@tonic-gate 		 * If there's a decimal point, but no unit
15740Sstevel@tonic-gate 		 * specification, let's assume megabytes.
15750Sstevel@tonic-gate 		 */
15760Sstevel@tonic-gate 		if ((value == 0) && (strchr(cleantoken, '.') != NULL)) {
15770Sstevel@tonic-gate 			value = 'm';
15780Sstevel@tonic-gate 		}
15790Sstevel@tonic-gate 
15800Sstevel@tonic-gate 		/*
15810Sstevel@tonic-gate 		 * Handle each unit type we support
15820Sstevel@tonic-gate 		 */
15830Sstevel@tonic-gate 		switch (value) {
15840Sstevel@tonic-gate 		case 'b':
15850Sstevel@tonic-gate 			/*
15860Sstevel@tonic-gate 			 * Token is number of blocks
15870Sstevel@tonic-gate 			 */
15880Sstevel@tonic-gate 			if (geti64(cleantoken, &blokno, (uint64_t *)NULL)) {
15890Sstevel@tonic-gate 			    break;
15900Sstevel@tonic-gate 			}
15910Sstevel@tonic-gate 			if (blokno > bounds->upper) {
15920Sstevel@tonic-gate 			    err_print(
15930Sstevel@tonic-gate "Number of blocks must be less that the total available blocks.\n");
15940Sstevel@tonic-gate 			    break;
15950Sstevel@tonic-gate 			}
15960Sstevel@tonic-gate 			return (blokno);
15970Sstevel@tonic-gate 
15980Sstevel@tonic-gate 		case 'e':
15990Sstevel@tonic-gate 			/*
16000Sstevel@tonic-gate 			 * Token is ending block number
16010Sstevel@tonic-gate 			 */
16020Sstevel@tonic-gate 
16030Sstevel@tonic-gate 			/* convert token to integer */
16040Sstevel@tonic-gate 			if (geti64(cleantoken, &blokno, (uint64_t *)NULL)) {
16050Sstevel@tonic-gate 				break;
16060Sstevel@tonic-gate 			}
16070Sstevel@tonic-gate 
16080Sstevel@tonic-gate 			/*
16090Sstevel@tonic-gate 			 * Some sanity check
16100Sstevel@tonic-gate 			 */
16110Sstevel@tonic-gate 			if (blokno < efi_deflt->start_sector) {
16120Sstevel@tonic-gate 				err_print(
16130Sstevel@tonic-gate "End Sector must fall on or after start sector %llu\n",
16140Sstevel@tonic-gate 				    efi_deflt->start_sector);
16150Sstevel@tonic-gate 				break;
16160Sstevel@tonic-gate 			}
16170Sstevel@tonic-gate 
16180Sstevel@tonic-gate 			/*
16190Sstevel@tonic-gate 			 * verify that our input is within range
16200Sstevel@tonic-gate 			 */
16210Sstevel@tonic-gate 			if (blokno > cur_parts->etoc->efi_last_u_lba) {
16220Sstevel@tonic-gate 				err_print(
16230Sstevel@tonic-gate "End Sector %llu is beyond max Sector %llu\n",
16240Sstevel@tonic-gate 				    blokno, cur_parts->etoc->efi_last_u_lba);
16250Sstevel@tonic-gate 				break;
16260Sstevel@tonic-gate 			}
16270Sstevel@tonic-gate 
16280Sstevel@tonic-gate 			/*
16290Sstevel@tonic-gate 			 * calculate number of blocks based on input
16300Sstevel@tonic-gate 			 */
16310Sstevel@tonic-gate 
16320Sstevel@tonic-gate 			return (blokno - efi_deflt->start_sector + 1);
16330Sstevel@tonic-gate 
16340Sstevel@tonic-gate 		case 'm':
16350Sstevel@tonic-gate 			/*
16360Sstevel@tonic-gate 			 * Convert token from megabytes to a
16370Sstevel@tonic-gate 			 * block number.
16380Sstevel@tonic-gate 			 */
16394429Sbz211116 			if (sscanf(cleantoken, "%f2", &nmegs) != 1) {
16400Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
16410Sstevel@tonic-gate 				    cleantoken);
16420Sstevel@tonic-gate 				break;
16430Sstevel@tonic-gate 			}
16440Sstevel@tonic-gate 
16450Sstevel@tonic-gate 			/*
16460Sstevel@tonic-gate 			 * Check the bounds
16470Sstevel@tonic-gate 			 */
16480Sstevel@tonic-gate 			if (nmegs > bn2mb(bounds->upper - bounds->lower)) {
16490Sstevel@tonic-gate 				err_print("`%1.2fmb' is out of range\n", nmegs);
16500Sstevel@tonic-gate 				break;
16510Sstevel@tonic-gate 			}
16520Sstevel@tonic-gate 
16530Sstevel@tonic-gate 			return (mb2bn(nmegs));
16540Sstevel@tonic-gate 
16550Sstevel@tonic-gate 		case 'g':
16564429Sbz211116 			if (sscanf(cleantoken, "%f2", &nmegs) != 1) {
16570Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
16580Sstevel@tonic-gate 				    cleantoken);
16590Sstevel@tonic-gate 				break;
16600Sstevel@tonic-gate 			}
16610Sstevel@tonic-gate 			if (nmegs > bn2gb(bounds->upper - bounds->lower)) {
16620Sstevel@tonic-gate 				err_print("`%1.2fgb' is out of range\n", nmegs);
16630Sstevel@tonic-gate 				break;
16640Sstevel@tonic-gate 			}
16650Sstevel@tonic-gate 
16660Sstevel@tonic-gate 			return (gb2bn(nmegs));
16670Sstevel@tonic-gate 
16680Sstevel@tonic-gate 		case 't':
16694429Sbz211116 			if (sscanf(cleantoken, "%f2", &nmegs) != 1) {
16700Sstevel@tonic-gate 				err_print("`%s' is not recognized\n",
16710Sstevel@tonic-gate 				    cleantoken);
16720Sstevel@tonic-gate 				break;
16730Sstevel@tonic-gate 			}
16740Sstevel@tonic-gate 			if (nmegs > bn2tb(bounds->upper - bounds->lower)) {
16750Sstevel@tonic-gate 				err_print("`%1.2ftb' is out of range\n", nmegs);
16760Sstevel@tonic-gate 				break;
16770Sstevel@tonic-gate 			}
16780Sstevel@tonic-gate 			return (uint64_t)((float)nmegs * 1024.0 *
1679*9889SLarry.Liu@Sun.COM 				1024.0 * 1024.0 * 1024.0 / cur_blksz);
16800Sstevel@tonic-gate 
16810Sstevel@tonic-gate 		default:
16820Sstevel@tonic-gate 			err_print(
16830Sstevel@tonic-gate "Please specify units in either b(number of blocks), e(end sector),\n");
16840Sstevel@tonic-gate 			err_print(" g(gigabytes), m(megabytes)");
16850Sstevel@tonic-gate 			err_print(" or t(terabytes)\n");
16860Sstevel@tonic-gate 			break;
16870Sstevel@tonic-gate 		}
16880Sstevel@tonic-gate 		break;
16890Sstevel@tonic-gate 
16900Sstevel@tonic-gate 	/*
16910Sstevel@tonic-gate 	 * If we don't recognize the input type, it's bad news.
16920Sstevel@tonic-gate 	 */
16930Sstevel@tonic-gate 	default:
16940Sstevel@tonic-gate 		err_print("Error: unknown input type.\n");
16950Sstevel@tonic-gate 		fullabort();
16960Sstevel@tonic-gate 	}
16970Sstevel@tonic-gate 	/*
16980Sstevel@tonic-gate 	 * If we get here, it's because some error kept us from accepting
16990Sstevel@tonic-gate 	 * the token.  If we are running out of a command file, gracefully
17000Sstevel@tonic-gate 	 * leave the program.  If we are interacting with the user, simply
17010Sstevel@tonic-gate 	 * reprompt.  If the token was in the pipe, abort the current command.
17020Sstevel@tonic-gate 	 */
17030Sstevel@tonic-gate 	if (option_f)
17040Sstevel@tonic-gate 		fullabort();
17050Sstevel@tonic-gate 	else if (interactive)
17060Sstevel@tonic-gate 		goto reprompt;
17070Sstevel@tonic-gate 	else
17080Sstevel@tonic-gate 		cmdabort(SIGINT);
17090Sstevel@tonic-gate 	/*
17100Sstevel@tonic-gate 	 * Never actually reached.
17110Sstevel@tonic-gate 	 */
17120Sstevel@tonic-gate 	return (-1);
17130Sstevel@tonic-gate }
17140Sstevel@tonic-gate 
17150Sstevel@tonic-gate /*
17160Sstevel@tonic-gate  * Print input choices
17170Sstevel@tonic-gate  */
17180Sstevel@tonic-gate static void
print_input_choices(type,param)17190Sstevel@tonic-gate print_input_choices(type, param)
17200Sstevel@tonic-gate 	int		type;
17210Sstevel@tonic-gate 	u_ioparam_t	*param;
17220Sstevel@tonic-gate {
17230Sstevel@tonic-gate 	char		**sp;
17240Sstevel@tonic-gate 	slist_t		*lp;
17250Sstevel@tonic-gate 	int		width;
17260Sstevel@tonic-gate 	int		col;
17270Sstevel@tonic-gate 	int		ncols;
17280Sstevel@tonic-gate 
17290Sstevel@tonic-gate 	switch (type) {
17300Sstevel@tonic-gate 	case FIO_CSTR:
17310Sstevel@tonic-gate 		fmt_print("Expecting one of the following:\n");
17320Sstevel@tonic-gate 		goto common;
17330Sstevel@tonic-gate 
17340Sstevel@tonic-gate 	case FIO_MSTR:
17350Sstevel@tonic-gate 		fmt_print("Expecting one of the following: ");
17360Sstevel@tonic-gate 		fmt_print("(abbreviations ok):\n");
17370Sstevel@tonic-gate common:
17380Sstevel@tonic-gate 		for (sp = (char **)param->io_charlist; *sp != NULL; sp++) {
17390Sstevel@tonic-gate 			fmt_print("\t%s\n", *sp);
17400Sstevel@tonic-gate 		}
17410Sstevel@tonic-gate 		break;
17420Sstevel@tonic-gate 
17430Sstevel@tonic-gate 	case FIO_SLIST:
17440Sstevel@tonic-gate 		fmt_print("Expecting one of the following: ");
17450Sstevel@tonic-gate 		fmt_print("(abbreviations ok):\n");
17460Sstevel@tonic-gate 		/*
17470Sstevel@tonic-gate 		 * Figure out the width of the widest string
17480Sstevel@tonic-gate 		 */
17490Sstevel@tonic-gate 		width = slist_widest_str((slist_t *)param->io_slist);
17500Sstevel@tonic-gate 		width += 4;
17510Sstevel@tonic-gate 		/*
17520Sstevel@tonic-gate 		 * If the help messages are empty, print the
17530Sstevel@tonic-gate 		 * possible choices in left-justified columns
17540Sstevel@tonic-gate 		 */
17550Sstevel@tonic-gate 		lp = (slist_t *)param->io_slist;
17560Sstevel@tonic-gate 		if (*lp->help == 0) {
17570Sstevel@tonic-gate 			col = 0;
17580Sstevel@tonic-gate 			ncols = 60 / width;
17590Sstevel@tonic-gate 			for (; lp->str != NULL; lp++) {
17600Sstevel@tonic-gate 				if (col == 0)
17610Sstevel@tonic-gate 					fmt_print("\t");
17620Sstevel@tonic-gate 				ljust_print(lp->str,
17630Sstevel@tonic-gate 				    (++col == ncols) ? 0 : width);
17640Sstevel@tonic-gate 				if (col == ncols) {
17650Sstevel@tonic-gate 					col = 0;
17660Sstevel@tonic-gate 					fmt_print("\n");
17670Sstevel@tonic-gate 				}
17680Sstevel@tonic-gate 			}
17690Sstevel@tonic-gate 			if (col != 0)
17700Sstevel@tonic-gate 				fmt_print("\n");
17710Sstevel@tonic-gate 		} else {
17720Sstevel@tonic-gate 			/*
17730Sstevel@tonic-gate 			 * With help messages, print each choice,
17740Sstevel@tonic-gate 			 * and help message, on its own line.
17750Sstevel@tonic-gate 			 */
17760Sstevel@tonic-gate 			for (; lp->str != NULL; lp++) {
17770Sstevel@tonic-gate 				fmt_print("\t");
17780Sstevel@tonic-gate 				ljust_print(lp->str, width);
17790Sstevel@tonic-gate 				fmt_print("- %s\n", lp->help);
17800Sstevel@tonic-gate 			}
17810Sstevel@tonic-gate 		}
17820Sstevel@tonic-gate 		break;
17830Sstevel@tonic-gate 
17840Sstevel@tonic-gate 	default:
17850Sstevel@tonic-gate 		err_print("Error: unknown input type.\n");
17860Sstevel@tonic-gate 		fullabort();
17870Sstevel@tonic-gate 	}
17880Sstevel@tonic-gate 
17890Sstevel@tonic-gate 	fmt_print("\n");
17900Sstevel@tonic-gate }
17910Sstevel@tonic-gate 
17920Sstevel@tonic-gate 
17930Sstevel@tonic-gate /*
17940Sstevel@tonic-gate  * Search a string list for a particular string.
17950Sstevel@tonic-gate  * Use minimum recognition, to accept unique abbreviations
17960Sstevel@tonic-gate  * Return the number of possible matches found.
17970Sstevel@tonic-gate  * If only one match was found, return the arbitrary value
17980Sstevel@tonic-gate  * associated with the matched string in match_value.
17990Sstevel@tonic-gate  */
18000Sstevel@tonic-gate int
find_value(slist,match_str,match_value)18010Sstevel@tonic-gate find_value(slist, match_str, match_value)
18020Sstevel@tonic-gate 	slist_t		*slist;
18030Sstevel@tonic-gate 	char		*match_str;
18040Sstevel@tonic-gate 	int		*match_value;
18050Sstevel@tonic-gate {
18060Sstevel@tonic-gate 	int		i;
18070Sstevel@tonic-gate 	int		nmatches;
18080Sstevel@tonic-gate 	int		length;
18090Sstevel@tonic-gate 	int		match_length;
18100Sstevel@tonic-gate 
18110Sstevel@tonic-gate 	nmatches = 0;
18120Sstevel@tonic-gate 	length = 0;
18130Sstevel@tonic-gate 
18140Sstevel@tonic-gate 	match_length = strlen(match_str);
18150Sstevel@tonic-gate 
18160Sstevel@tonic-gate 	for (; slist->str != NULL; slist++) {
18170Sstevel@tonic-gate 		/*
18180Sstevel@tonic-gate 		 * See how many characters of the token match
18190Sstevel@tonic-gate 		 */
18200Sstevel@tonic-gate 		i = strcnt(match_str, slist->str);
18210Sstevel@tonic-gate 		/*
18220Sstevel@tonic-gate 		 * If it's not the whole token, then it's not a match.
18230Sstevel@tonic-gate 		 */
18240Sstevel@tonic-gate 		if (i  < match_length)
18250Sstevel@tonic-gate 			continue;
18260Sstevel@tonic-gate 		/*
18270Sstevel@tonic-gate 		 * If it ties with another input, remember that.
18280Sstevel@tonic-gate 		 */
18290Sstevel@tonic-gate 		if (i == length)
18300Sstevel@tonic-gate 			nmatches++;
18310Sstevel@tonic-gate 		/*
18320Sstevel@tonic-gate 		 * If it matches the most so far, record that.
18330Sstevel@tonic-gate 		 */
18340Sstevel@tonic-gate 		if (i > length) {
18350Sstevel@tonic-gate 			*match_value = slist->value;
18360Sstevel@tonic-gate 			nmatches = 1;
18370Sstevel@tonic-gate 			length = i;
18380Sstevel@tonic-gate 		}
18390Sstevel@tonic-gate 	}
18400Sstevel@tonic-gate 
18410Sstevel@tonic-gate 	return (nmatches);
18420Sstevel@tonic-gate }
18430Sstevel@tonic-gate 
18440Sstevel@tonic-gate /*
18450Sstevel@tonic-gate  * Search a string list for a particular value.
18460Sstevel@tonic-gate  * Return the string associated with that value.
18470Sstevel@tonic-gate  */
18480Sstevel@tonic-gate char *
find_string(slist,match_value)18490Sstevel@tonic-gate find_string(slist, match_value)
18500Sstevel@tonic-gate 	slist_t		*slist;
18510Sstevel@tonic-gate 	int		match_value;
18520Sstevel@tonic-gate {
18530Sstevel@tonic-gate 	for (; slist->str != NULL; slist++) {
18540Sstevel@tonic-gate 		if (slist->value == match_value) {
18550Sstevel@tonic-gate 			return (slist->str);
18560Sstevel@tonic-gate 		}
18570Sstevel@tonic-gate 	}
18580Sstevel@tonic-gate 
18590Sstevel@tonic-gate 	return ((char *)NULL);
18600Sstevel@tonic-gate }
18610Sstevel@tonic-gate 
18620Sstevel@tonic-gate /*
18630Sstevel@tonic-gate  * Return the width of the widest string in an slist
18640Sstevel@tonic-gate  */
18650Sstevel@tonic-gate static int
slist_widest_str(slist)18660Sstevel@tonic-gate slist_widest_str(slist)
18670Sstevel@tonic-gate 	slist_t	*slist;
18680Sstevel@tonic-gate {
18690Sstevel@tonic-gate 	int	i;
18700Sstevel@tonic-gate 	int	width;
18710Sstevel@tonic-gate 
18720Sstevel@tonic-gate 	width = 0;
18730Sstevel@tonic-gate 	for (; slist->str != NULL; slist++) {
18740Sstevel@tonic-gate 		if ((i = strlen(slist->str)) > width)
18750Sstevel@tonic-gate 			width = i;
18760Sstevel@tonic-gate 	}
18770Sstevel@tonic-gate 
18780Sstevel@tonic-gate 	return (width);
18790Sstevel@tonic-gate }
18800Sstevel@tonic-gate 
18810Sstevel@tonic-gate /*
18820Sstevel@tonic-gate  * Print a string left-justified to a fixed width.
18830Sstevel@tonic-gate  */
18840Sstevel@tonic-gate static void
ljust_print(str,width)18850Sstevel@tonic-gate ljust_print(str, width)
18860Sstevel@tonic-gate 	char	*str;
18870Sstevel@tonic-gate 	int	width;
18880Sstevel@tonic-gate {
18890Sstevel@tonic-gate 	int	i;
18900Sstevel@tonic-gate 
18910Sstevel@tonic-gate 	fmt_print("%s", str);
18920Sstevel@tonic-gate 	for (i = width - strlen(str); i > 0; i--) {
18930Sstevel@tonic-gate 		fmt_print(" ");
18940Sstevel@tonic-gate 	}
18950Sstevel@tonic-gate }
18960Sstevel@tonic-gate 
18970Sstevel@tonic-gate /*
18980Sstevel@tonic-gate  * This routine is a modified version of printf.  It handles the cases
18990Sstevel@tonic-gate  * of silent mode and logging; other than that it is identical to the
19000Sstevel@tonic-gate  * library version.
19010Sstevel@tonic-gate  */
19020Sstevel@tonic-gate /*PRINTFLIKE1*/
19030Sstevel@tonic-gate void
fmt_print(char * format,...)19040Sstevel@tonic-gate fmt_print(char *format, ...)
19050Sstevel@tonic-gate {
19060Sstevel@tonic-gate 	va_list ap;
19070Sstevel@tonic-gate 
19080Sstevel@tonic-gate 	va_start(ap, format);
19090Sstevel@tonic-gate 
19100Sstevel@tonic-gate 	/*
19110Sstevel@tonic-gate 	 * If we are running silent, skip it.
19120Sstevel@tonic-gate 	 */
19130Sstevel@tonic-gate 	if (option_s == 0) {
19140Sstevel@tonic-gate 		/*
19150Sstevel@tonic-gate 		 * Do the print to standard out.
19160Sstevel@tonic-gate 		 */
19170Sstevel@tonic-gate 		if (need_newline) {
19180Sstevel@tonic-gate 			(void) printf("\n");
19190Sstevel@tonic-gate 		}
19200Sstevel@tonic-gate 		(void) vprintf(format, ap);
19210Sstevel@tonic-gate 		/*
19220Sstevel@tonic-gate 		 * If we are logging, also print to the log file.
19230Sstevel@tonic-gate 		 */
19240Sstevel@tonic-gate 		if (log_file) {
19250Sstevel@tonic-gate 			if (need_newline) {
19260Sstevel@tonic-gate 				(void) fprintf(log_file, "\n");
19270Sstevel@tonic-gate 			}
19280Sstevel@tonic-gate 			(void) vfprintf(log_file, format, ap);
19290Sstevel@tonic-gate 			(void) fflush(log_file);
19300Sstevel@tonic-gate 		}
19310Sstevel@tonic-gate 	}
19320Sstevel@tonic-gate 
19330Sstevel@tonic-gate 	need_newline = 0;
19340Sstevel@tonic-gate 
19350Sstevel@tonic-gate 	va_end(ap);
19360Sstevel@tonic-gate }
19370Sstevel@tonic-gate 
19380Sstevel@tonic-gate /*
19390Sstevel@tonic-gate  * This routine is a modified version of printf.  It handles the cases
19400Sstevel@tonic-gate  * of silent mode; other than that it is identical to the
19410Sstevel@tonic-gate  * library version.  It differs from the above printf in that it does
19420Sstevel@tonic-gate  * not print the message to a log file.
19430Sstevel@tonic-gate  */
19440Sstevel@tonic-gate /*PRINTFLIKE1*/
19450Sstevel@tonic-gate void
nolog_print(char * format,...)19460Sstevel@tonic-gate nolog_print(char *format, ...)
19470Sstevel@tonic-gate {
19480Sstevel@tonic-gate 	va_list ap;
19490Sstevel@tonic-gate 
19500Sstevel@tonic-gate 	va_start(ap, format);
19510Sstevel@tonic-gate 
19520Sstevel@tonic-gate 	/*
19530Sstevel@tonic-gate 	 * If we are running silent, skip it.
19540Sstevel@tonic-gate 	 */
19550Sstevel@tonic-gate 	if (option_s == 0) {
19560Sstevel@tonic-gate 		/*
19570Sstevel@tonic-gate 		 * Do the print to standard out.
19580Sstevel@tonic-gate 		 */
19590Sstevel@tonic-gate 		if (need_newline) {
19600Sstevel@tonic-gate 			(void) printf("\n");
19610Sstevel@tonic-gate 		}
19620Sstevel@tonic-gate 		(void) vprintf(format, ap);
19630Sstevel@tonic-gate 	}
19640Sstevel@tonic-gate 
19650Sstevel@tonic-gate 	va_end(ap);
19660Sstevel@tonic-gate 
19670Sstevel@tonic-gate 	need_newline = 0;
19680Sstevel@tonic-gate }
19690Sstevel@tonic-gate 
19700Sstevel@tonic-gate /*
19710Sstevel@tonic-gate  * This routine is a modified version of printf.  It handles the cases
19720Sstevel@tonic-gate  * of silent mode, and only prints the message to the log file, not
19730Sstevel@tonic-gate  * stdout.  Other than that is identical to the library version.
19740Sstevel@tonic-gate  */
19750Sstevel@tonic-gate /*PRINTFLIKE1*/
19760Sstevel@tonic-gate void
log_print(char * format,...)19770Sstevel@tonic-gate log_print(char *format, ...)
19780Sstevel@tonic-gate {
19790Sstevel@tonic-gate 	va_list ap;
19800Sstevel@tonic-gate 
19810Sstevel@tonic-gate 	va_start(ap, format);
19820Sstevel@tonic-gate 
19830Sstevel@tonic-gate 	/*
19840Sstevel@tonic-gate 	 * If we are running silent, skip it.
19850Sstevel@tonic-gate 	 */
19860Sstevel@tonic-gate 	if (option_s == 0) {
19870Sstevel@tonic-gate 		/*
19880Sstevel@tonic-gate 		 * Do the print to the log file.
19890Sstevel@tonic-gate 		 */
19900Sstevel@tonic-gate 		if (need_newline) {
19910Sstevel@tonic-gate 			(void) fprintf(log_file, "\n");
19920Sstevel@tonic-gate 		}
19930Sstevel@tonic-gate 		(void) vfprintf(log_file, format, ap);
19940Sstevel@tonic-gate 		(void) fflush(log_file);
19950Sstevel@tonic-gate 	}
19960Sstevel@tonic-gate 
19970Sstevel@tonic-gate 	va_end(ap);
19980Sstevel@tonic-gate 
19990Sstevel@tonic-gate 	need_newline = 0;
20000Sstevel@tonic-gate }
20010Sstevel@tonic-gate 
20020Sstevel@tonic-gate /*
20030Sstevel@tonic-gate  * This routine is a modified version of printf.  It prints the message
20040Sstevel@tonic-gate  * to stderr, and to the log file is appropriate.
20050Sstevel@tonic-gate  * Other than that is identical to the library version.
20060Sstevel@tonic-gate  */
20070Sstevel@tonic-gate /*PRINTFLIKE1*/
20080Sstevel@tonic-gate void
err_print(char * format,...)20090Sstevel@tonic-gate err_print(char *format, ...)
20100Sstevel@tonic-gate {
20110Sstevel@tonic-gate 	va_list ap;
20120Sstevel@tonic-gate 
20130Sstevel@tonic-gate 	va_start(ap, format);
20140Sstevel@tonic-gate 
20150Sstevel@tonic-gate 	/*
20160Sstevel@tonic-gate 	 * Flush anything pending to stdout
20170Sstevel@tonic-gate 	 */
20180Sstevel@tonic-gate 	if (need_newline) {
20190Sstevel@tonic-gate 		(void) printf("\n");
20200Sstevel@tonic-gate 	}
20210Sstevel@tonic-gate 	(void) fflush(stdout);
20220Sstevel@tonic-gate 	/*
20230Sstevel@tonic-gate 	 * Do the print to stderr.
20240Sstevel@tonic-gate 	 */
20250Sstevel@tonic-gate 	(void) vfprintf(stderr, format, ap);
20260Sstevel@tonic-gate 	/*
20270Sstevel@tonic-gate 	 * If we are logging, also print to the log file.
20280Sstevel@tonic-gate 	 */
20290Sstevel@tonic-gate 	if (log_file) {
20300Sstevel@tonic-gate 		if (need_newline) {
20310Sstevel@tonic-gate 			(void) fprintf(log_file, "\n");
20320Sstevel@tonic-gate 		}
20330Sstevel@tonic-gate 		(void) vfprintf(log_file, format, ap);
20340Sstevel@tonic-gate 		(void) fflush(log_file);
20350Sstevel@tonic-gate 	}
20360Sstevel@tonic-gate 	va_end(ap);
20370Sstevel@tonic-gate 
20380Sstevel@tonic-gate 	need_newline = 0;
20390Sstevel@tonic-gate }
20400Sstevel@tonic-gate 
20410Sstevel@tonic-gate /*
20420Sstevel@tonic-gate  * Print a number of characters from a buffer.  The buffer
20430Sstevel@tonic-gate  * does not need to be null-terminated.  Since the data
20440Sstevel@tonic-gate  * may be coming from a device, we cannot be sure the
20450Sstevel@tonic-gate  * data is not crud, so be rather defensive.
20460Sstevel@tonic-gate  */
20470Sstevel@tonic-gate void
print_buf(buf,nbytes)20480Sstevel@tonic-gate print_buf(buf, nbytes)
20490Sstevel@tonic-gate 	char	*buf;
20500Sstevel@tonic-gate 	int	nbytes;
20510Sstevel@tonic-gate {
20520Sstevel@tonic-gate 	int	c;
20530Sstevel@tonic-gate 
20540Sstevel@tonic-gate 	while (nbytes-- > 0) {
20550Sstevel@tonic-gate 		c = *buf++;
20560Sstevel@tonic-gate 		if (isascii(c) && isprint(c)) {
20570Sstevel@tonic-gate 			fmt_print("%c", c);
20580Sstevel@tonic-gate 		} else
20590Sstevel@tonic-gate 			break;
20600Sstevel@tonic-gate 	}
20610Sstevel@tonic-gate }
20620Sstevel@tonic-gate 
20630Sstevel@tonic-gate #ifdef	not
20640Sstevel@tonic-gate /*
20650Sstevel@tonic-gate  * This routine prints out a message describing the given ctlr.
20660Sstevel@tonic-gate  * The message is identical to the one printed by the kernel during
20670Sstevel@tonic-gate  * booting.
20680Sstevel@tonic-gate  */
20690Sstevel@tonic-gate void
pr_ctlrline(ctlr)20700Sstevel@tonic-gate pr_ctlrline(ctlr)
20710Sstevel@tonic-gate 	register struct ctlr_info *ctlr;
20720Sstevel@tonic-gate {
20730Sstevel@tonic-gate 
20740Sstevel@tonic-gate 	fmt_print("           %s%d at %s 0x%x ",
20750Sstevel@tonic-gate 		ctlr->ctlr_cname, ctlr->ctlr_num,
20760Sstevel@tonic-gate 		space2str(ctlr->ctlr_space), ctlr->ctlr_addr);
20770Sstevel@tonic-gate 	if (ctlr->ctlr_vec != 0)
20780Sstevel@tonic-gate 		fmt_print("vec 0x%x ", ctlr->ctlr_vec);
20790Sstevel@tonic-gate 	else
20800Sstevel@tonic-gate 		fmt_print("pri %d ", ctlr->ctlr_prio);
20810Sstevel@tonic-gate 	fmt_print("\n");
20820Sstevel@tonic-gate }
20830Sstevel@tonic-gate #endif /* not */
20840Sstevel@tonic-gate 
20850Sstevel@tonic-gate /*
20860Sstevel@tonic-gate  * This routine prints out a message describing the given disk.
20870Sstevel@tonic-gate  * The message is identical to the one printed by the kernel during
20880Sstevel@tonic-gate  * booting.
20890Sstevel@tonic-gate  */
20900Sstevel@tonic-gate void
pr_diskline(disk,num)20910Sstevel@tonic-gate pr_diskline(disk, num)
20920Sstevel@tonic-gate 	register struct disk_info *disk;
20930Sstevel@tonic-gate 	int	num;
20940Sstevel@tonic-gate {
20950Sstevel@tonic-gate 	struct	ctlr_info *ctlr = disk->disk_ctlr;
20960Sstevel@tonic-gate 	struct	disk_type *type = disk->disk_type;
20970Sstevel@tonic-gate 
20980Sstevel@tonic-gate 	fmt_print("    %4d. %s ", num, disk->disk_name);
20990Sstevel@tonic-gate 	if ((type != NULL) && (disk->label_type == L_TYPE_SOLARIS)) {
21007563SPrasad.Singamsetty@Sun.COM 		fmt_print("<%s cyl %u alt %u hd %u sec %u>",
21010Sstevel@tonic-gate 			type->dtype_asciilabel, type->dtype_ncyl,
21020Sstevel@tonic-gate 			type->dtype_acyl, type->dtype_nhead,
21030Sstevel@tonic-gate 			type->dtype_nsect);
21040Sstevel@tonic-gate 	} else if ((type != NULL) && (disk->label_type == L_TYPE_EFI)) {
2105*9889SLarry.Liu@Sun.COM 		cur_blksz = disk->disk_lbasize;
21060Sstevel@tonic-gate 		print_efi_string(type->vendor, type->product,
21070Sstevel@tonic-gate 			type->revision, type->capacity);
21080Sstevel@tonic-gate 	} else if (disk->disk_flags & DSK_RESERVED) {
21090Sstevel@tonic-gate 		fmt_print("<drive not available: reserved>");
21100Sstevel@tonic-gate 	} else if (disk->disk_flags & DSK_UNAVAILABLE) {
21110Sstevel@tonic-gate 		fmt_print("<drive not available>");
21120Sstevel@tonic-gate 	} else {
21130Sstevel@tonic-gate 		fmt_print("<drive type unknown>");
21140Sstevel@tonic-gate 	}
21150Sstevel@tonic-gate 	if (chk_volname(disk)) {
21160Sstevel@tonic-gate 		fmt_print("  ");
21170Sstevel@tonic-gate 		print_volname(disk);
21180Sstevel@tonic-gate 	}
21190Sstevel@tonic-gate 	fmt_print("\n");
21200Sstevel@tonic-gate 
21210Sstevel@tonic-gate 	if (disk->devfs_name != NULL) {
21220Sstevel@tonic-gate 		fmt_print("          %s\n", disk->devfs_name);
21230Sstevel@tonic-gate 	} else {
21240Sstevel@tonic-gate 		fmt_print("          %s%d at %s%d slave %d\n",
21250Sstevel@tonic-gate 			ctlr->ctlr_dname, disk->disk_dkinfo.dki_unit,
21260Sstevel@tonic-gate 			ctlr->ctlr_cname, ctlr->ctlr_num,
21270Sstevel@tonic-gate 			disk->disk_dkinfo.dki_slave);
21280Sstevel@tonic-gate 	}
21290Sstevel@tonic-gate 
21300Sstevel@tonic-gate #ifdef	OLD
21310Sstevel@tonic-gate 	fmt_print("    %4d. %s at %s%d slave %d", num, disk->disk_name,
21320Sstevel@tonic-gate 	    ctlr->ctlr_cname, ctlr->ctlr_num, disk->disk_dkinfo.dki_slave);
21330Sstevel@tonic-gate 	if (chk_volname(disk)) {
21340Sstevel@tonic-gate 		fmt_print(": ");
21350Sstevel@tonic-gate 		print_volname(disk);
21360Sstevel@tonic-gate 	}
21370Sstevel@tonic-gate 	fmt_print("\n");
21380Sstevel@tonic-gate 	if (type != NULL) {
21390Sstevel@tonic-gate 		fmt_print(
21407563SPrasad.Singamsetty@Sun.COM "           %s%d: <%s cyl %u alt %u hd %u sec %u>\n",
21410Sstevel@tonic-gate 		    ctlr->ctlr_dname, disk->disk_dkinfo.dki_unit,
21420Sstevel@tonic-gate 		    type->dtype_asciilabel, type->dtype_ncyl,
21430Sstevel@tonic-gate 		    type->dtype_acyl, type->dtype_nhead,
21440Sstevel@tonic-gate 		    type->dtype_nsect);
21450Sstevel@tonic-gate 	} else {
21460Sstevel@tonic-gate 		fmt_print("           %s%d: <drive type unknown>\n",
21470Sstevel@tonic-gate 		    ctlr->ctlr_dname, disk->disk_dkinfo.dki_unit);
21480Sstevel@tonic-gate 	}
21490Sstevel@tonic-gate #endif /* OLD */
21500Sstevel@tonic-gate }
21510Sstevel@tonic-gate 
21520Sstevel@tonic-gate /*
21530Sstevel@tonic-gate  * This routine prints out a given disk block number in cylinder/head/sector
21540Sstevel@tonic-gate  * format.  It uses the printing routine passed in to do the actual output.
21550Sstevel@tonic-gate  */
21560Sstevel@tonic-gate void
pr_dblock(void (* func)(char *,...),diskaddr_t bn)21570Sstevel@tonic-gate pr_dblock(void (*func)(char *, ...), diskaddr_t bn)
21580Sstevel@tonic-gate {
21590Sstevel@tonic-gate 	if (cur_label == L_TYPE_SOLARIS) {
21607563SPrasad.Singamsetty@Sun.COM 		(*func)("%u/%u/%u", bn2c(bn),
21617563SPrasad.Singamsetty@Sun.COM 		    bn2h(bn), bn2s(bn));
21620Sstevel@tonic-gate 	} else {
21634429Sbz211116 		(*func)("%llu", bn);
21640Sstevel@tonic-gate 	}
21650Sstevel@tonic-gate }
21660Sstevel@tonic-gate 
21670Sstevel@tonic-gate /*
21680Sstevel@tonic-gate  * This routine inputs a character from the data file.  It understands
21690Sstevel@tonic-gate  * the use of '\' to prevent interpretation of a newline.  It also keeps
21700Sstevel@tonic-gate  * track of the current line in the data file via a global variable.
21710Sstevel@tonic-gate  */
21720Sstevel@tonic-gate static int
sup_inputchar()21730Sstevel@tonic-gate sup_inputchar()
21740Sstevel@tonic-gate {
21750Sstevel@tonic-gate 	int	c;
21760Sstevel@tonic-gate 
21770Sstevel@tonic-gate 	/*
21780Sstevel@tonic-gate 	 * Input the character.
21790Sstevel@tonic-gate 	 */
21800Sstevel@tonic-gate 	c = getc(data_file);
21810Sstevel@tonic-gate 	/*
21820Sstevel@tonic-gate 	 * If it's not a backslash, return it.
21830Sstevel@tonic-gate 	 */
21840Sstevel@tonic-gate 	if (c != '\\')
21850Sstevel@tonic-gate 		return (c);
21860Sstevel@tonic-gate 	/*
21870Sstevel@tonic-gate 	 * It was a backslash.  Get the next character.
21880Sstevel@tonic-gate 	 */
21890Sstevel@tonic-gate 	c = getc(data_file);
21900Sstevel@tonic-gate 	/*
21910Sstevel@tonic-gate 	 * If it was a newline, update the line counter and get the next
21920Sstevel@tonic-gate 	 * character.
21930Sstevel@tonic-gate 	 */
21940Sstevel@tonic-gate 	if (c == '\n') {
21950Sstevel@tonic-gate 		data_lineno++;
21960Sstevel@tonic-gate 		c = getc(data_file);
21970Sstevel@tonic-gate 	}
21980Sstevel@tonic-gate 	/*
21990Sstevel@tonic-gate 	 * Return the character.
22000Sstevel@tonic-gate 	 */
22010Sstevel@tonic-gate 	return (c);
22020Sstevel@tonic-gate }
22030Sstevel@tonic-gate 
22040Sstevel@tonic-gate /*
22050Sstevel@tonic-gate  * This routine pushes a character back onto the input pipe for the data file.
22060Sstevel@tonic-gate  */
22070Sstevel@tonic-gate static void
sup_pushchar(c)22080Sstevel@tonic-gate sup_pushchar(c)
22090Sstevel@tonic-gate 	int	c;
22100Sstevel@tonic-gate {
22110Sstevel@tonic-gate 	(void) ungetc(c, data_file);
22120Sstevel@tonic-gate }
22130Sstevel@tonic-gate 
22140Sstevel@tonic-gate /*
22150Sstevel@tonic-gate  * Variables to support pushing back tokens
22160Sstevel@tonic-gate  */
22170Sstevel@tonic-gate static  int	have_pushed_token = 0;
22180Sstevel@tonic-gate static  TOKEN	pushed_buf;
22190Sstevel@tonic-gate static  int	pushed_token;
22200Sstevel@tonic-gate 
22210Sstevel@tonic-gate /*
22220Sstevel@tonic-gate  * This routine inputs a token from the data file.  A token is a series
22230Sstevel@tonic-gate  * of contiguous non-white characters or a recognized special delimiter
22240Sstevel@tonic-gate  * character.  Use of the wrapper lets us always have the value of the
22250Sstevel@tonic-gate  * last token around, which is useful for error recovery.
22260Sstevel@tonic-gate  */
22270Sstevel@tonic-gate int
sup_gettoken(buf)22280Sstevel@tonic-gate sup_gettoken(buf)
22290Sstevel@tonic-gate 	char	*buf;
22300Sstevel@tonic-gate {
22310Sstevel@tonic-gate 	last_token_type = sup_get_token(buf);
22320Sstevel@tonic-gate 	return (last_token_type);
22330Sstevel@tonic-gate }
22340Sstevel@tonic-gate 
22350Sstevel@tonic-gate static int
sup_get_token(buf)22360Sstevel@tonic-gate sup_get_token(buf)
22370Sstevel@tonic-gate 	char	*buf;
22380Sstevel@tonic-gate {
22390Sstevel@tonic-gate 	char	*ptr = buf;
22400Sstevel@tonic-gate 	int	c, quoted = 0;
22410Sstevel@tonic-gate 
22420Sstevel@tonic-gate 	/*
22430Sstevel@tonic-gate 	 * First check for presence of push-backed token.
22440Sstevel@tonic-gate 	 * If so, return it.
22450Sstevel@tonic-gate 	 */
22460Sstevel@tonic-gate 	if (have_pushed_token) {
22470Sstevel@tonic-gate 		have_pushed_token = 0;
22480Sstevel@tonic-gate 		bcopy(pushed_buf, buf, TOKEN_SIZE+1);
22490Sstevel@tonic-gate 		return (pushed_token);
22500Sstevel@tonic-gate 	}
22510Sstevel@tonic-gate 	/*
22520Sstevel@tonic-gate 	 * Zero out the returned token buffer
22530Sstevel@tonic-gate 	 */
22540Sstevel@tonic-gate 	bzero(buf, TOKEN_SIZE + 1);
22550Sstevel@tonic-gate 	/*
22560Sstevel@tonic-gate 	 * Strip off leading white-space.
22570Sstevel@tonic-gate 	 */
22580Sstevel@tonic-gate 	while ((isspace(c = sup_inputchar())) && (c != '\n'))
22590Sstevel@tonic-gate 		;
22600Sstevel@tonic-gate 	/*
22610Sstevel@tonic-gate 	 * Read in characters until we hit unquoted white-space.
22620Sstevel@tonic-gate 	 */
22630Sstevel@tonic-gate 	for (; !isspace(c) || quoted; c = sup_inputchar()) {
22640Sstevel@tonic-gate 		/*
22650Sstevel@tonic-gate 		 * If we hit eof, that's a token.
22660Sstevel@tonic-gate 		 */
22670Sstevel@tonic-gate 		if (feof(data_file))
22680Sstevel@tonic-gate 			return (SUP_EOF);
22690Sstevel@tonic-gate 		/*
22700Sstevel@tonic-gate 		 * If we hit a double quote, change the state of quoting.
22710Sstevel@tonic-gate 		 */
22720Sstevel@tonic-gate 		if (c == '"') {
22730Sstevel@tonic-gate 			quoted = !quoted;
22740Sstevel@tonic-gate 			continue;
22750Sstevel@tonic-gate 		}
22760Sstevel@tonic-gate 		/*
22770Sstevel@tonic-gate 		 * If we hit a newline, that delimits a token.
22780Sstevel@tonic-gate 		 */
22790Sstevel@tonic-gate 		if (c == '\n')
22800Sstevel@tonic-gate 			break;
22810Sstevel@tonic-gate 		/*
22820Sstevel@tonic-gate 		 * If we hit any nonquoted special delimiters, that delimits
22830Sstevel@tonic-gate 		 * a token.
22840Sstevel@tonic-gate 		 */
22850Sstevel@tonic-gate 		if (!quoted && (c == '=' || c == ',' || c == ':' ||
22860Sstevel@tonic-gate 			c == '#' || c == '|' || c == '&' || c == '~'))
22870Sstevel@tonic-gate 			break;
22880Sstevel@tonic-gate 		/*
22890Sstevel@tonic-gate 		 * Store the character if there's room left.
22900Sstevel@tonic-gate 		 */
22910Sstevel@tonic-gate 		if (ptr - buf < TOKEN_SIZE)
22920Sstevel@tonic-gate 			*ptr++ = (char)c;
22930Sstevel@tonic-gate 	}
22940Sstevel@tonic-gate 	/*
22950Sstevel@tonic-gate 	 * If we stored characters in the buffer, then we inputted a string.
22960Sstevel@tonic-gate 	 * Push the delimiter back into the pipe and return the string.
22970Sstevel@tonic-gate 	 */
22980Sstevel@tonic-gate 	if (ptr - buf > 0) {
22990Sstevel@tonic-gate 		sup_pushchar(c);
23000Sstevel@tonic-gate 		return (SUP_STRING);
23010Sstevel@tonic-gate 	}
23020Sstevel@tonic-gate 	/*
23030Sstevel@tonic-gate 	 * We didn't input a string, so we must have inputted a known delimiter.
23040Sstevel@tonic-gate 	 * store the delimiter in the buffer, so it will get returned.
23050Sstevel@tonic-gate 	 */
23060Sstevel@tonic-gate 	buf[0] = c;
23070Sstevel@tonic-gate 	/*
23080Sstevel@tonic-gate 	 * Switch on the delimiter.  Return the appropriate value for each one.
23090Sstevel@tonic-gate 	 */
23100Sstevel@tonic-gate 	switch (c) {
23110Sstevel@tonic-gate 	case '=':
23120Sstevel@tonic-gate 		return (SUP_EQL);
23130Sstevel@tonic-gate 	case ':':
23140Sstevel@tonic-gate 		return (SUP_COLON);
23150Sstevel@tonic-gate 	case ',':
23160Sstevel@tonic-gate 		return (SUP_COMMA);
23170Sstevel@tonic-gate 	case '\n':
23180Sstevel@tonic-gate 		return (SUP_EOL);
23190Sstevel@tonic-gate 	case '|':
23200Sstevel@tonic-gate 		return (SUP_OR);
23210Sstevel@tonic-gate 	case '&':
23220Sstevel@tonic-gate 		return (SUP_AND);
23230Sstevel@tonic-gate 	case '~':
23240Sstevel@tonic-gate 		return (SUP_TILDE);
23250Sstevel@tonic-gate 	case '#':
23260Sstevel@tonic-gate 		/*
23270Sstevel@tonic-gate 		 * For comments, we flush out the rest of the line and return
23280Sstevel@tonic-gate 		 * an EOL.
23290Sstevel@tonic-gate 		 */
23300Sstevel@tonic-gate 		while ((c = sup_inputchar()) != '\n' && !feof(data_file))
23310Sstevel@tonic-gate 			;
23320Sstevel@tonic-gate 		if (feof(data_file))
23330Sstevel@tonic-gate 			return (SUP_EOF);
23340Sstevel@tonic-gate 		else
23350Sstevel@tonic-gate 			return (SUP_EOL);
23360Sstevel@tonic-gate 	/*
23370Sstevel@tonic-gate 	 * Shouldn't ever get here.
23380Sstevel@tonic-gate 	 */
23390Sstevel@tonic-gate 	default:
23400Sstevel@tonic-gate 		return (SUP_STRING);
23410Sstevel@tonic-gate 	}
23420Sstevel@tonic-gate }
23430Sstevel@tonic-gate 
23440Sstevel@tonic-gate /*
23450Sstevel@tonic-gate  * Push back a token
23460Sstevel@tonic-gate  */
23470Sstevel@tonic-gate void
sup_pushtoken(token_buf,token_type)23480Sstevel@tonic-gate sup_pushtoken(token_buf, token_type)
23490Sstevel@tonic-gate 	char	*token_buf;
23500Sstevel@tonic-gate 	int	token_type;
23510Sstevel@tonic-gate {
23520Sstevel@tonic-gate 	/*
23530Sstevel@tonic-gate 	 * We can only push one token back at a time
23540Sstevel@tonic-gate 	 */
23550Sstevel@tonic-gate 	assert(have_pushed_token == 0);
23560Sstevel@tonic-gate 
23570Sstevel@tonic-gate 	have_pushed_token = 1;
23580Sstevel@tonic-gate 	bcopy(token_buf, pushed_buf, TOKEN_SIZE+1);
23590Sstevel@tonic-gate 	pushed_token = token_type;
23600Sstevel@tonic-gate }
23610Sstevel@tonic-gate 
23620Sstevel@tonic-gate /*
23630Sstevel@tonic-gate  * Get an entire line of input.  Handles logging, comments,
23640Sstevel@tonic-gate  * and EOF.
23650Sstevel@tonic-gate  */
23660Sstevel@tonic-gate void
get_inputline(line,nbytes)23670Sstevel@tonic-gate get_inputline(line, nbytes)
23680Sstevel@tonic-gate 	char	*line;
23690Sstevel@tonic-gate 	int	nbytes;
23700Sstevel@tonic-gate {
23710Sstevel@tonic-gate 	char	*p = line;
23720Sstevel@tonic-gate 	int	c;
23730Sstevel@tonic-gate 
23740Sstevel@tonic-gate 	/*
23750Sstevel@tonic-gate 	 * Remove any leading white-space and comments
23760Sstevel@tonic-gate 	 */
23770Sstevel@tonic-gate 	do {
23780Sstevel@tonic-gate 		while ((isspace(c = getchar())) && (c != '\n'))
23790Sstevel@tonic-gate 			;
23800Sstevel@tonic-gate 	} while (c == COMMENT_CHAR);
23810Sstevel@tonic-gate 	/*
23820Sstevel@tonic-gate 	 * Loop on each character until end of line
23830Sstevel@tonic-gate 	 */
23840Sstevel@tonic-gate 	while (c != '\n') {
23850Sstevel@tonic-gate 		/*
23860Sstevel@tonic-gate 		 * If we hit eof, get out.
23870Sstevel@tonic-gate 		 */
23880Sstevel@tonic-gate 		if (checkeof()) {
23890Sstevel@tonic-gate 			fullabort();
23900Sstevel@tonic-gate 		}
23910Sstevel@tonic-gate 		/*
23920Sstevel@tonic-gate 		 * Add the character to the buffer.
23930Sstevel@tonic-gate 		 */
23940Sstevel@tonic-gate 		if (nbytes > 1) {
23950Sstevel@tonic-gate 			*p++ = (char)c;
23960Sstevel@tonic-gate 			nbytes --;
23970Sstevel@tonic-gate 		}
23980Sstevel@tonic-gate 		/*
23990Sstevel@tonic-gate 		 * Get the next character.
24000Sstevel@tonic-gate 		 */
24010Sstevel@tonic-gate 		c = getchar();
24020Sstevel@tonic-gate 	}
24030Sstevel@tonic-gate 	/*
24040Sstevel@tonic-gate 	 * Null terminate the token.
24050Sstevel@tonic-gate 	 */
24060Sstevel@tonic-gate 	*p = 0;
24070Sstevel@tonic-gate 	/*
24080Sstevel@tonic-gate 	 * Indicate that we've emptied the pipe
24090Sstevel@tonic-gate 	 */
24100Sstevel@tonic-gate 	token_present = 0;
24110Sstevel@tonic-gate 	/*
24120Sstevel@tonic-gate 	 * If we're running out of a file, echo the line to
24130Sstevel@tonic-gate 	 * the user, otherwise if we're logging, copy the
24140Sstevel@tonic-gate 	 * input to the log file.
24150Sstevel@tonic-gate 	 */
24160Sstevel@tonic-gate 	if (option_f) {
24170Sstevel@tonic-gate 		fmt_print("%s\n", line);
24180Sstevel@tonic-gate 	} else if (log_file) {
24190Sstevel@tonic-gate 		log_print("%s\n", line);
24200Sstevel@tonic-gate 	}
24210Sstevel@tonic-gate }
24220Sstevel@tonic-gate 
24230Sstevel@tonic-gate /*
24240Sstevel@tonic-gate  * execute the shell escape command
24250Sstevel@tonic-gate  */
24260Sstevel@tonic-gate int
execute_shell(s,buff_size)24271383Spr131582 execute_shell(s, buff_size)
24280Sstevel@tonic-gate 	char	*s;
24291383Spr131582 	size_t	buff_size;
24300Sstevel@tonic-gate {
24310Sstevel@tonic-gate 	struct	termio	termio;
24320Sstevel@tonic-gate 	struct	termios	tty;
24330Sstevel@tonic-gate 	int	tty_flag, i, j;
24340Sstevel@tonic-gate 	char	*shell_name;
24350Sstevel@tonic-gate 	static char	*default_shell = "/bin/sh";
24360Sstevel@tonic-gate 
24370Sstevel@tonic-gate 	tty_flag = -1;
24380Sstevel@tonic-gate 
24390Sstevel@tonic-gate 	if (*s == NULL) {
24400Sstevel@tonic-gate 		shell_name = getenv("SHELL");
24410Sstevel@tonic-gate 
24420Sstevel@tonic-gate 		if (shell_name == NULL) {
24430Sstevel@tonic-gate 			shell_name = default_shell;
24440Sstevel@tonic-gate 		}
24451383Spr131582 		if (strlcpy(s, shell_name, buff_size) >=
24461383Spr131582 		    buff_size) {
24471383Spr131582 			err_print("Error: Shell command ($SHELL) too long.\n");
24480Sstevel@tonic-gate 			fullabort();
24490Sstevel@tonic-gate 		}
24500Sstevel@tonic-gate 	}
24510Sstevel@tonic-gate 
24520Sstevel@tonic-gate 	/* save tty information */
24530Sstevel@tonic-gate 
24540Sstevel@tonic-gate 	if (isatty(0)) {
24550Sstevel@tonic-gate 		if (ioctl(0, TCGETS, &tty) == 0)
24560Sstevel@tonic-gate 			tty_flag = 1;
24570Sstevel@tonic-gate 		else {
24580Sstevel@tonic-gate 			if (ioctl(0, TCGETA, &termio) == 0) {
24590Sstevel@tonic-gate 				tty_flag = 0;
24600Sstevel@tonic-gate 				tty.c_iflag = termio.c_iflag;
24610Sstevel@tonic-gate 				tty.c_oflag = termio.c_oflag;
24620Sstevel@tonic-gate 				tty.c_cflag = termio.c_cflag;
24630Sstevel@tonic-gate 				tty.c_lflag = termio.c_lflag;
24640Sstevel@tonic-gate 				for (i = 0; i < NCC; i++)
24650Sstevel@tonic-gate 					tty.c_cc[i] = termio.c_cc[i];
24660Sstevel@tonic-gate 			}
24670Sstevel@tonic-gate 		}
24680Sstevel@tonic-gate 	}
24690Sstevel@tonic-gate 
24700Sstevel@tonic-gate 	/* close the current file descriptor */
24710Sstevel@tonic-gate 	if (cur_disk != NULL) {
24720Sstevel@tonic-gate 		(void) close(cur_file);
24730Sstevel@tonic-gate 	}
24740Sstevel@tonic-gate 
24750Sstevel@tonic-gate 	/* execute the shell escape */
24760Sstevel@tonic-gate 	(void) system(s);
24770Sstevel@tonic-gate 
24780Sstevel@tonic-gate 	/* reopen file descriptor if one was open before */
24790Sstevel@tonic-gate 	if (cur_disk != NULL) {
24800Sstevel@tonic-gate 		if ((cur_file = open_disk(cur_disk->disk_path,
24810Sstevel@tonic-gate 			O_RDWR | O_NDELAY)) < 0) {
24820Sstevel@tonic-gate 			err_print("Error: can't reopen selected disk '%s'. \n",
24830Sstevel@tonic-gate 				cur_disk->disk_name);
24840Sstevel@tonic-gate 			fullabort();
24850Sstevel@tonic-gate 		}
24860Sstevel@tonic-gate 	}
24870Sstevel@tonic-gate 
24880Sstevel@tonic-gate 	/* Restore tty information */
24890Sstevel@tonic-gate 
24900Sstevel@tonic-gate 	if (isatty(0)) {
24910Sstevel@tonic-gate 		if (tty_flag > 0)
24920Sstevel@tonic-gate 			(void) ioctl(0, TCSETSW, &tty);
24930Sstevel@tonic-gate 		else if (tty_flag == 0) {
24940Sstevel@tonic-gate 			termio.c_iflag = tty.c_iflag;
24950Sstevel@tonic-gate 			termio.c_oflag = tty.c_oflag;
24960Sstevel@tonic-gate 			termio.c_cflag = tty.c_cflag;
24970Sstevel@tonic-gate 			termio.c_lflag = tty.c_lflag;
24980Sstevel@tonic-gate 			for (j = 0; j < NCC; j++)
24990Sstevel@tonic-gate 				termio.c_cc[j] = tty.c_cc[j];
25000Sstevel@tonic-gate 			(void) ioctl(0, TCSETAW, &termio);
25010Sstevel@tonic-gate 		}
25020Sstevel@tonic-gate 
25030Sstevel@tonic-gate 		if (isatty(1)) {
25040Sstevel@tonic-gate 			fmt_print("\n[Hit Return to continue] \n");
25050Sstevel@tonic-gate 			(void) fflush(stdin);
25060Sstevel@tonic-gate 			if (getchar() == EOF)
25070Sstevel@tonic-gate 				fullabort();
25080Sstevel@tonic-gate 		}
25090Sstevel@tonic-gate 	}
25100Sstevel@tonic-gate 	return (0);
25110Sstevel@tonic-gate }
25120Sstevel@tonic-gate 
25130Sstevel@tonic-gate void
print_efi_string(char * vendor,char * product,char * revision,uint64_t capacity)25140Sstevel@tonic-gate print_efi_string(char *vendor, char *product, char *revision,
25150Sstevel@tonic-gate     uint64_t capacity)
25160Sstevel@tonic-gate {
25170Sstevel@tonic-gate 	char new_vendor[9];
25180Sstevel@tonic-gate 	char new_product[17];
25190Sstevel@tonic-gate 	char new_revision[5];
25200Sstevel@tonic-gate 	char capacity_string[10];
25210Sstevel@tonic-gate 	float scaled;
25220Sstevel@tonic-gate 	int i;
25230Sstevel@tonic-gate 
25240Sstevel@tonic-gate 	/* Strip whitespace from the end of inquiry strings */
25250Sstevel@tonic-gate 	(void) strlcpy(new_vendor, vendor, sizeof (new_vendor));
25260Sstevel@tonic-gate 	for (i = (strlen(new_vendor) - 1); i >= 0; i--) {
25270Sstevel@tonic-gate 		if (new_vendor[i] != 0x20) {
25280Sstevel@tonic-gate 			new_vendor[i+1] = '\0';
25290Sstevel@tonic-gate 			break;
25300Sstevel@tonic-gate 		}
25310Sstevel@tonic-gate 	}
25320Sstevel@tonic-gate 
25330Sstevel@tonic-gate 	(void) strlcpy(new_product, product, sizeof (new_product));
25340Sstevel@tonic-gate 	for (i = (strlen(new_product) - 1); i >= 0; i--) {
25350Sstevel@tonic-gate 		if (new_product[i] != 0x20) {
25360Sstevel@tonic-gate 			new_product[i+1] = '\0';
25370Sstevel@tonic-gate 			break;
25380Sstevel@tonic-gate 		}
25390Sstevel@tonic-gate 	}
25400Sstevel@tonic-gate 
25410Sstevel@tonic-gate 	(void) strlcpy(new_revision, revision, sizeof (new_revision));
25420Sstevel@tonic-gate 	for (i = (strlen(new_revision) - 1); i >= 0; i--) {
25430Sstevel@tonic-gate 		if (new_revision[i] != 0x20) {
25440Sstevel@tonic-gate 			new_revision[i+1] = '\0';
25450Sstevel@tonic-gate 			break;
25460Sstevel@tonic-gate 		}
25470Sstevel@tonic-gate 	}
25480Sstevel@tonic-gate 
25490Sstevel@tonic-gate 	/* Now build size string */
25500Sstevel@tonic-gate 	scaled = bn2mb(capacity);
25510Sstevel@tonic-gate 	if (scaled >= (float)1024.0 * 1024) {
25520Sstevel@tonic-gate 		(void) snprintf(capacity_string, sizeof (capacity_string),
25530Sstevel@tonic-gate 		    "%.2fTB", scaled/((float)1024.0 * 1024));
25540Sstevel@tonic-gate 	} else if (scaled >= (float)1024.0) {
25550Sstevel@tonic-gate 		(void) snprintf(capacity_string, sizeof (capacity_string),
25560Sstevel@tonic-gate 		    "%.2fGB", scaled/(float)1024.0);
25570Sstevel@tonic-gate 	} else {
25580Sstevel@tonic-gate 		(void) snprintf(capacity_string, sizeof (capacity_string),
25590Sstevel@tonic-gate 		    "%.2fMB", scaled);
25600Sstevel@tonic-gate 	}
25610Sstevel@tonic-gate 
25620Sstevel@tonic-gate 	fmt_print("<%s-%s-%s-%s>",
25630Sstevel@tonic-gate 	    new_vendor, new_product, new_revision, capacity_string);
25640Sstevel@tonic-gate }
2565