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