1 /* $NetBSD: menuutils.c,v 1.3 2008/12/14 18:46:33 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1996, 1997 5 * Matthias Drochner. All rights reserved. 6 * Copyright (c) 1996, 1997 7 * Perry E. Metzger. All rights reserved. 8 * Copyright (c) 1997 9 * Jason R. Thorpe. All rights reserved 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgements: 21 * This product includes software developed for the NetBSD Project 22 * by Matthias Drochner. 23 * This product includes software developed for the NetBSD Project 24 * by Perry E. Metzger. 25 * 4. The names of the authors may not be used to endorse or promote products 26 * derived from this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 29 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 30 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 31 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 32 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 33 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 37 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include <lib/libkern/libkern.h> 41 #include <lib/libsa/stand.h> 42 43 #include "libi386.h" 44 45 void 46 docommand(char *arg) 47 { 48 char *options; 49 int i; 50 51 options = gettrailer(arg); 52 53 for (i = 0; commands[i].c_name != NULL; i++) { 54 if (strcmp(arg, commands[i].c_name) == 0) { 55 (*commands[i].c_fn)(options); 56 return; 57 } 58 } 59 60 printf("unknown command\n"); 61 command_help(NULL); 62 } 63 64 void 65 #if !defined(__minix) 66 bootmenu(void) 67 #else 68 prompt(int allowreturn) 69 #endif /* !defined(__minix) */ 70 { 71 char input[80]; 72 73 for (;;) { 74 char *c = input; 75 76 input[0] = '\0'; 77 printf("> "); 78 #if !defined(__minix) 79 gets(input); 80 #else 81 editline(input, sizeof(input), NULL); 82 #endif /* !defined(__minix) */ 83 84 /* 85 * Skip leading whitespace. 86 */ 87 while (*c == ' ') 88 c++; 89 #if defined(__minix) 90 if (allowreturn && !strcmp(c, "menu")) 91 break; 92 #endif /* defined(__minix) */ 93 if (*c) 94 docommand(c); 95 } 96 } 97 98 #if defined(__minix) 99 void 100 bootmenu(void) 101 { 102 prompt(0); 103 } 104 105 /* Derived from libsa gets(). */ 106 void 107 editline(char *buf, size_t size, char *input) 108 { 109 int c, i, pos, len = 0; 110 111 /* If an initial input has been given, copy and print this first. */ 112 if (input != NULL) { 113 while (*input && len < size - 1) 114 putchar(buf[len++] = *input++); 115 } 116 pos = len; 117 118 for (;;) { 119 c = getchar_ex(); 120 switch (c & 0177) { 121 case '\0': 122 switch (c) { 123 case 0x4b00: /* Left arrow: move cursor to left. */ 124 if (pos > 0) { 125 putchar('\b'); 126 pos--; 127 } 128 break; 129 case 0x4d00: /* Right arrow: move cursor to right. */ 130 if (pos < len) putchar(buf[pos++]); 131 break; 132 } 133 break; 134 case 'b' & 037: /* Ctrl+B: move cursor to left. */ 135 if (pos > 0) { 136 putchar('\b'); 137 pos--; 138 } 139 break; 140 case 'f' & 037: /* Ctrl+F: move cursor to right. */ 141 if (pos < len) putchar(buf[pos++]); 142 break; 143 case 'a' & 037: /* Ctrl+A: move cursor to start of line. */ 144 for ( ; pos > 0; pos--) putchar('\b'); 145 break; 146 case 'e' & 037: /* Ctrl+E: move cursor to end of line. */ 147 for ( ; pos < len; pos++) putchar(buf[pos]); 148 break; 149 case '\n': /* Enter: return line. */ 150 case '\r': 151 for ( ; pos < len; pos++) putchar(buf[pos]); 152 buf[len] = '\0'; 153 putchar('\n'); 154 return; 155 #if HASH_ERASE 156 case '#': 157 #endif 158 case '\b': /* Backspace: erase character before cursor. */ 159 case '\177': 160 if (pos > 0) { 161 pos--; 162 len--; 163 putchar('\b'); 164 for (i = pos; i < len; i++) 165 putchar(buf[i] = buf[i + 1]); 166 putchar(' '); 167 for (i = pos; i < len; i++) putchar('\b'); 168 putchar('\b'); 169 } 170 break; 171 case 'r' & 037: /* Ctrl+R: reprint line. */ 172 putchar('\n'); 173 for (i = 0; i < len; i++) putchar(buf[i]); 174 for (i = len; i > pos; i--) putchar('\b'); 175 break; 176 #if AT_ERASE 177 case '@': 178 #endif 179 case 'u' & 037: /* Ctrl+U: clear entire line. */ 180 case 'w' & 037: 181 for ( ; pos > 0; pos--) putchar('\b'); 182 for ( ; pos < len; pos++) putchar(' '); 183 for ( ; pos > 0; pos--) putchar('\b'); 184 len = 0; 185 break; 186 case '\a': /* Ctrl+G: sound bell but do not store character. */ 187 putchar(c); 188 break; 189 case '\t': /* Tab: convert to single space. */ 190 c = ' '; 191 /*FALLTHROUGH*/ 192 default: /* Insert character at cursor position. */ 193 if (len < size - 1) { 194 for (i = len; i > pos; i--) 195 buf[i] = buf[i - 1]; 196 buf[pos] = c; 197 pos++; 198 len++; 199 putchar(c); 200 for (i = pos; i < len; i++) putchar(buf[i]); 201 for (i = pos; i < len; i++) putchar('\b'); 202 } else { 203 putchar('\a'); 204 } 205 break; 206 } 207 } 208 /*NOTREACHED*/ 209 } 210 #endif /* defined(__minix) */ 211