xref: /minix/sys/arch/i386/stand/lib/menuutils.c (revision 0a6a1f1d)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: menuutils.c,v 1.4 2014/04/06 19:11:26 jakllsch Exp $	*/
258a2b000SEvgeniy Ivanov 
358a2b000SEvgeniy Ivanov /*
458a2b000SEvgeniy Ivanov  * Copyright (c) 1996, 1997
558a2b000SEvgeniy Ivanov  * 	Matthias Drochner.  All rights reserved.
658a2b000SEvgeniy Ivanov  * Copyright (c) 1996, 1997
758a2b000SEvgeniy Ivanov  * 	Perry E. Metzger.  All rights reserved.
858a2b000SEvgeniy Ivanov  * Copyright (c) 1997
958a2b000SEvgeniy Ivanov  *	Jason R. Thorpe.  All rights reserved
1058a2b000SEvgeniy Ivanov  *
1158a2b000SEvgeniy Ivanov  * Redistribution and use in source and binary forms, with or without
1258a2b000SEvgeniy Ivanov  * modification, are permitted provided that the following conditions
1358a2b000SEvgeniy Ivanov  * are met:
1458a2b000SEvgeniy Ivanov  * 1. Redistributions of source code must retain the above copyright
1558a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer.
1658a2b000SEvgeniy Ivanov  * 2. Redistributions in binary form must reproduce the above copyright
1758a2b000SEvgeniy Ivanov  *    notice, this list of conditions and the following disclaimer in the
1858a2b000SEvgeniy Ivanov  *    documentation and/or other materials provided with the distribution.
1958a2b000SEvgeniy Ivanov  * 3. All advertising materials mentioning features or use of this software
2058a2b000SEvgeniy Ivanov  *    must display the following acknowledgements:
2158a2b000SEvgeniy Ivanov  *	This product includes software developed for the NetBSD Project
2258a2b000SEvgeniy Ivanov  *	by Matthias Drochner.
2358a2b000SEvgeniy Ivanov  *	This product includes software developed for the NetBSD Project
2458a2b000SEvgeniy Ivanov  *	by Perry E. Metzger.
2558a2b000SEvgeniy Ivanov  * 4. The names of the authors may not be used to endorse or promote products
2658a2b000SEvgeniy Ivanov  *    derived from this software without specific prior written permission.
2758a2b000SEvgeniy Ivanov  *
2858a2b000SEvgeniy Ivanov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2958a2b000SEvgeniy Ivanov  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
3058a2b000SEvgeniy Ivanov  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
3158a2b000SEvgeniy Ivanov  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3258a2b000SEvgeniy Ivanov  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3358a2b000SEvgeniy Ivanov  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3458a2b000SEvgeniy Ivanov  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3558a2b000SEvgeniy Ivanov  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3658a2b000SEvgeniy Ivanov  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3758a2b000SEvgeniy Ivanov  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3858a2b000SEvgeniy Ivanov  */
3958a2b000SEvgeniy Ivanov 
4058a2b000SEvgeniy Ivanov #include <lib/libkern/libkern.h>
4158a2b000SEvgeniy Ivanov #include <lib/libsa/stand.h>
4258a2b000SEvgeniy Ivanov 
4358a2b000SEvgeniy Ivanov #include "libi386.h"
4458a2b000SEvgeniy Ivanov 
4558a2b000SEvgeniy Ivanov void
docommand(char * arg)4658a2b000SEvgeniy Ivanov docommand(char *arg)
4758a2b000SEvgeniy Ivanov {
4858a2b000SEvgeniy Ivanov 	char *options;
4958a2b000SEvgeniy Ivanov 	int i;
5058a2b000SEvgeniy Ivanov 
5158a2b000SEvgeniy Ivanov 	options = gettrailer(arg);
5258a2b000SEvgeniy Ivanov 
5358a2b000SEvgeniy Ivanov 	for (i = 0; commands[i].c_name != NULL; i++) {
5458a2b000SEvgeniy Ivanov 		if (strcmp(arg, commands[i].c_name) == 0) {
5558a2b000SEvgeniy Ivanov 			(*commands[i].c_fn)(options);
5658a2b000SEvgeniy Ivanov 			return;
5758a2b000SEvgeniy Ivanov 		}
5858a2b000SEvgeniy Ivanov 	}
5958a2b000SEvgeniy Ivanov 
6058a2b000SEvgeniy Ivanov 	printf("unknown command\n");
6158a2b000SEvgeniy Ivanov 	command_help(NULL);
6258a2b000SEvgeniy Ivanov }
6358a2b000SEvgeniy Ivanov 
64*0a6a1f1dSLionel Sambuc __dead void
bootmenu(void)6584d9c625SLionel Sambuc bootmenu(void)
6684d9c625SLionel Sambuc #if defined(__minix)
679733fcdbSDavid van Moolenbroek {
689733fcdbSDavid van Moolenbroek 	prompt(0);
69*0a6a1f1dSLionel Sambuc 	while(1); /* This should never return. */
709733fcdbSDavid van Moolenbroek }
719733fcdbSDavid van Moolenbroek 
729733fcdbSDavid van Moolenbroek /* Derived from libsa gets(). */
739733fcdbSDavid van Moolenbroek void
editline(char * buf,size_t size,char * input)749733fcdbSDavid van Moolenbroek editline(char *buf, size_t size, char *input)
759733fcdbSDavid van Moolenbroek {
769733fcdbSDavid van Moolenbroek 	int c, i, pos, len = 0;
779733fcdbSDavid van Moolenbroek 
789733fcdbSDavid van Moolenbroek 	/* If an initial input has been given, copy and print this first. */
799733fcdbSDavid van Moolenbroek 	if (input != NULL) {
809733fcdbSDavid van Moolenbroek 		while (*input && len < size - 1)
819733fcdbSDavid van Moolenbroek 			putchar(buf[len++] = *input++);
829733fcdbSDavid van Moolenbroek 	}
839733fcdbSDavid van Moolenbroek 	pos = len;
849733fcdbSDavid van Moolenbroek 
859733fcdbSDavid van Moolenbroek 	for (;;) {
869733fcdbSDavid van Moolenbroek 		c = getchar_ex();
879733fcdbSDavid van Moolenbroek 		switch (c & 0177) {
889733fcdbSDavid van Moolenbroek 		case '\0':
899733fcdbSDavid van Moolenbroek 			switch (c) {
909733fcdbSDavid van Moolenbroek 			case 0x4b00: /* Left arrow: move cursor to left. */
919733fcdbSDavid van Moolenbroek 				if (pos > 0) {
929733fcdbSDavid van Moolenbroek 					putchar('\b');
939733fcdbSDavid van Moolenbroek 					pos--;
949733fcdbSDavid van Moolenbroek 				}
959733fcdbSDavid van Moolenbroek 				break;
969733fcdbSDavid van Moolenbroek 			case 0x4d00: /* Right arrow: move cursor to right. */
979733fcdbSDavid van Moolenbroek 				if (pos < len) putchar(buf[pos++]);
989733fcdbSDavid van Moolenbroek 				break;
999733fcdbSDavid van Moolenbroek 			}
1009733fcdbSDavid van Moolenbroek 			break;
1019733fcdbSDavid van Moolenbroek 		case 'b' & 037: /* Ctrl+B: move cursor to left. */
1029733fcdbSDavid van Moolenbroek 			if (pos > 0) {
1039733fcdbSDavid van Moolenbroek 				putchar('\b');
1049733fcdbSDavid van Moolenbroek 				pos--;
1059733fcdbSDavid van Moolenbroek 			}
1069733fcdbSDavid van Moolenbroek 			break;
1079733fcdbSDavid van Moolenbroek 		case 'f' & 037: /* Ctrl+F: move cursor to right. */
1089733fcdbSDavid van Moolenbroek 			if (pos < len) putchar(buf[pos++]);
1099733fcdbSDavid van Moolenbroek 			break;
1109733fcdbSDavid van Moolenbroek 		case 'a' & 037: /* Ctrl+A: move cursor to start of line. */
1119733fcdbSDavid van Moolenbroek 			for ( ; pos > 0; pos--) putchar('\b');
1129733fcdbSDavid van Moolenbroek 			break;
1139733fcdbSDavid van Moolenbroek 		case 'e' & 037: /* Ctrl+E: move cursor to end of line. */
1149733fcdbSDavid van Moolenbroek 			for ( ; pos < len; pos++) putchar(buf[pos]);
1159733fcdbSDavid van Moolenbroek 			break;
1169733fcdbSDavid van Moolenbroek 		case '\n': /* Enter: return line. */
1179733fcdbSDavid van Moolenbroek 		case '\r':
1189733fcdbSDavid van Moolenbroek 			for ( ; pos < len; pos++) putchar(buf[pos]);
1199733fcdbSDavid van Moolenbroek 			buf[len] = '\0';
1209733fcdbSDavid van Moolenbroek 			putchar('\n');
1219733fcdbSDavid van Moolenbroek 			return;
1229733fcdbSDavid van Moolenbroek #if HASH_ERASE
1239733fcdbSDavid van Moolenbroek 		case '#':
1249733fcdbSDavid van Moolenbroek #endif
1259733fcdbSDavid van Moolenbroek 		case '\b': /* Backspace: erase character before cursor. */
1269733fcdbSDavid van Moolenbroek 		case '\177':
1279733fcdbSDavid van Moolenbroek 			if (pos > 0) {
1289733fcdbSDavid van Moolenbroek 				pos--;
1299733fcdbSDavid van Moolenbroek 				len--;
1309733fcdbSDavid van Moolenbroek 				putchar('\b');
1319733fcdbSDavid van Moolenbroek 				for (i = pos; i < len; i++)
1329733fcdbSDavid van Moolenbroek 					putchar(buf[i] = buf[i + 1]);
1339733fcdbSDavid van Moolenbroek 				putchar(' ');
1349733fcdbSDavid van Moolenbroek 				for (i = pos; i < len; i++) putchar('\b');
1359733fcdbSDavid van Moolenbroek 				putchar('\b');
1369733fcdbSDavid van Moolenbroek 			}
1379733fcdbSDavid van Moolenbroek 			break;
1389733fcdbSDavid van Moolenbroek 		case 'r' & 037: /* Ctrl+R: reprint line. */
1399733fcdbSDavid van Moolenbroek 			putchar('\n');
1409733fcdbSDavid van Moolenbroek 			for (i = 0; i < len; i++) putchar(buf[i]);
1419733fcdbSDavid van Moolenbroek 			for (i = len; i > pos; i--) putchar('\b');
1429733fcdbSDavid van Moolenbroek 			break;
1439733fcdbSDavid van Moolenbroek #if AT_ERASE
1449733fcdbSDavid van Moolenbroek 		case '@':
1459733fcdbSDavid van Moolenbroek #endif
1469733fcdbSDavid van Moolenbroek 		case 'u' & 037: /* Ctrl+U: clear entire line. */
1479733fcdbSDavid van Moolenbroek 		case 'w' & 037:
1489733fcdbSDavid van Moolenbroek 			for ( ; pos > 0; pos--) putchar('\b');
1499733fcdbSDavid van Moolenbroek 			for ( ; pos < len; pos++) putchar(' ');
1509733fcdbSDavid van Moolenbroek 			for ( ; pos > 0; pos--) putchar('\b');
1519733fcdbSDavid van Moolenbroek 			len = 0;
1529733fcdbSDavid van Moolenbroek 			break;
1539733fcdbSDavid van Moolenbroek 		case '\a': /* Ctrl+G: sound bell but do not store character. */
1549733fcdbSDavid van Moolenbroek 			putchar(c);
1559733fcdbSDavid van Moolenbroek 			break;
1569733fcdbSDavid van Moolenbroek 		case '\t': /* Tab: convert to single space. */
1579733fcdbSDavid van Moolenbroek 			c = ' ';
1589733fcdbSDavid van Moolenbroek 			/*FALLTHROUGH*/
1599733fcdbSDavid van Moolenbroek 		default: /* Insert character at cursor position. */
1609733fcdbSDavid van Moolenbroek 			if (len < size - 1) {
1619733fcdbSDavid van Moolenbroek 				for (i = len; i > pos; i--)
1629733fcdbSDavid van Moolenbroek 					buf[i] = buf[i - 1];
1639733fcdbSDavid van Moolenbroek 				buf[pos] = c;
1649733fcdbSDavid van Moolenbroek 				pos++;
1659733fcdbSDavid van Moolenbroek 				len++;
1669733fcdbSDavid van Moolenbroek 				putchar(c);
1679733fcdbSDavid van Moolenbroek 				for (i = pos; i < len; i++) putchar(buf[i]);
1689733fcdbSDavid van Moolenbroek 				for (i = pos; i < len; i++) putchar('\b');
1699733fcdbSDavid van Moolenbroek 			} else {
1709733fcdbSDavid van Moolenbroek 				putchar('\a');
1719733fcdbSDavid van Moolenbroek 			}
1729733fcdbSDavid van Moolenbroek 			break;
1739733fcdbSDavid van Moolenbroek 		}
1749733fcdbSDavid van Moolenbroek 	}
1759733fcdbSDavid van Moolenbroek 	/*NOTREACHED*/
1769733fcdbSDavid van Moolenbroek }
177*0a6a1f1dSLionel Sambuc 
178*0a6a1f1dSLionel Sambuc void
prompt(int allowreturn)179*0a6a1f1dSLionel Sambuc prompt(int allowreturn)
18084d9c625SLionel Sambuc #endif /* defined(__minix) */
181*0a6a1f1dSLionel Sambuc {
182*0a6a1f1dSLionel Sambuc 	char input[80];
183*0a6a1f1dSLionel Sambuc 
184*0a6a1f1dSLionel Sambuc 	for (;;) {
185*0a6a1f1dSLionel Sambuc 		char *c = input;
186*0a6a1f1dSLionel Sambuc 
187*0a6a1f1dSLionel Sambuc 		input[0] = '\0';
188*0a6a1f1dSLionel Sambuc 		printf("> ");
189*0a6a1f1dSLionel Sambuc #if !defined(__minix)
190*0a6a1f1dSLionel Sambuc 		gets(input);
191*0a6a1f1dSLionel Sambuc #else
192*0a6a1f1dSLionel Sambuc 		editline(input, sizeof(input), NULL);
193*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
194*0a6a1f1dSLionel Sambuc 
195*0a6a1f1dSLionel Sambuc 		/*
196*0a6a1f1dSLionel Sambuc 		 * Skip leading whitespace.
197*0a6a1f1dSLionel Sambuc 		 */
198*0a6a1f1dSLionel Sambuc 		while (*c == ' ')
199*0a6a1f1dSLionel Sambuc 			c++;
200*0a6a1f1dSLionel Sambuc #if defined(__minix)
201*0a6a1f1dSLionel Sambuc 		if (allowreturn && !strcmp(c, "menu"))
202*0a6a1f1dSLionel Sambuc 			break;
203*0a6a1f1dSLionel Sambuc #endif /* defined(__minix) */
204*0a6a1f1dSLionel Sambuc 		if (*c)
205*0a6a1f1dSLionel Sambuc 			docommand(c);
206*0a6a1f1dSLionel Sambuc 	}
207*0a6a1f1dSLionel Sambuc }
208