1 /* $NetBSD: prompt.c,v 1.3 2007/02/22 05:31:54 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by UCHIYAMA Yasushi. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <lib/libsa/stand.h> 40 #include <lib/libkern/libkern.h> 41 42 #include <machine/param.h> 43 #include <machine/bfs.h> 44 45 #include "cmd.h" 46 #include "local.h" 47 48 #define LOG_SIZE 2048 49 #define LOG_MASK (LOG_SIZE - 1) 50 uint8_t __log[LOG_SIZE]; 51 int __log_cnt; 52 53 #define CMDBUF_HISTORY_MAX 8 54 #define PROMPT ">> " 55 56 struct cmd_buf { 57 char buf[CMDBUF_SIZE]; 58 int cur, min, max; 59 } __cmd_buf[CMDBUF_HISTORY_MAX]; 60 61 struct cmd_buf *__cmd; 62 int __cur_cmd; 63 64 void prompt_reset(void); 65 void prompt_input(int); 66 extern void __putchar(int); 67 68 void 69 prompt(void) 70 { 71 int c; 72 73 prompt_reset(); 74 while (/*CONSTCOND*/1) 75 if ((c = getchar()) != 0) 76 prompt_input(c); 77 /* NOTREACHED */ 78 } 79 80 void 81 prompt_input(int c) 82 { 83 int i; 84 85 switch (c) { 86 case 32 ... 127: 87 __cmd->buf[__cmd->cur] = c; 88 __cmd->cur = (__cmd->cur >= CMDBUF_SIZE - 1) ? __cmd->cur : 89 __cmd->cur + 1; 90 if (__cmd->cur >= __cmd->max) 91 __cmd->max = __cmd->cur; 92 putchar(c); 93 break; 94 case '\r': 95 putchar('\n'); 96 if (__cmd->max > 0) { 97 cmd_exec(__cmd->buf); 98 prompt_reset(); 99 } else { 100 printf(PROMPT); 101 } 102 break; 103 case '\b': 104 if (__cmd->cur > 0) { 105 __cmd->buf[--__cmd->cur] = 0; 106 putchar(c); 107 } 108 break; 109 case 1: /* Ctrl a */ 110 __cmd->cur = __cmd->min; 111 putchar('\r'); 112 printf("%s", PROMPT); 113 break; 114 case 5: /* Ctrl e */ 115 __cmd->cur = __cmd->max; 116 goto redraw; 117 case 2: /* Ctrl b */ 118 if (__cmd->cur == __cmd->min) 119 return; 120 __cmd->cur--; 121 putchar(c); 122 break; 123 case 6: /* Ctrl f */ 124 if (__cmd->cur == __cmd->max) 125 return; 126 __cmd->cur++; 127 putchar(c); 128 break; 129 case 4: /* Ctrl d */ 130 if (__cmd->cur == __cmd->max) 131 return; 132 for (i = __cmd->cur; i < __cmd->max; i++) 133 __cmd->buf[i] = __cmd->buf[i + 1]; 134 __cmd->buf[i] = '\0'; 135 __cmd->max--; 136 goto redraw; 137 case 11: /* Ctrl k */ 138 for (i = __cmd->cur; i < __cmd->max; i++) { 139 __cmd->buf[i] = 0; 140 __cmd->max = __cmd->cur; 141 } 142 putchar(c); 143 break; 144 case 14: /* Ctrl n */ 145 __cur_cmd = (__cur_cmd + 1) & 0x7; 146 goto history_redraw; 147 case 16: /* Ctrl p */ 148 __cur_cmd = (__cur_cmd - 1) & 0x7; 149 history_redraw: 150 __cmd = &__cmd_buf[__cur_cmd]; 151 __cmd->cur = __cmd->max; 152 case 12: /* Ctrl l */ 153 redraw: 154 putchar('\r'); 155 putchar(11); 156 printf("%s%s", PROMPT, __cmd->buf); 157 break; 158 } 159 } 160 161 void 162 prompt_reset(void) 163 { 164 165 __cur_cmd = (__cur_cmd + 1) & 0x7; 166 __cmd = &__cmd_buf[__cur_cmd]; 167 memset(__cmd, 0, sizeof *__cmd); 168 printf(PROMPT); 169 } 170 171 bool 172 prompt_yesno(int interactive) 173 { 174 int i; 175 176 if (!interactive) 177 return true; 178 /* block until user input */ 179 while (/*CONSTCOND*/1) { 180 if ((i = getchar()) == 0) 181 continue; 182 if (i == 'N' || i == 'n') 183 return false; 184 if (i == 'Y' || i == 'y') 185 return true; 186 } 187 } 188 189 void 190 putchar(int c) 191 { 192 193 __putchar(c); 194 195 __log[__log_cnt++] = c; 196 __log_cnt &= LOG_MASK; 197 } 198 199 int 200 cmd_log_save(int argc, char *argp[], int interactive) 201 { 202 struct bfs *bfs; 203 204 if (bfs_init(&bfs) != 0) { 205 printf("no BFS partition.\n"); 206 return 1; 207 } 208 209 if (bfs_file_write(bfs, "boot.log", __log, LOG_SIZE) != 0) 210 printf("BFS write failed.\n"); 211 212 bfs_fini(bfs); 213 214 return 0; 215 } 216