1 /* $NetBSD: prompt.c,v 1.5 2019/01/09 03:28:31 christos 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <lib/libsa/stand.h> 33 #include <lib/libkern/libkern.h> 34 35 #include <sys/param.h> 36 #include <machine/bfs.h> 37 38 #include "cmd.h" 39 #include "local.h" 40 41 #define LOG_SIZE 2048 42 #define LOG_MASK (LOG_SIZE - 1) 43 uint8_t __log[LOG_SIZE]; 44 int __log_cnt; 45 46 #define CMDBUF_HISTORY_MAX 8 47 #define PROMPT ">> " 48 49 struct cmd_buf { 50 char buf[CMDBUF_SIZE]; 51 int cur, min, max; 52 } __cmd_buf[CMDBUF_HISTORY_MAX]; 53 54 struct cmd_buf *__cmd; 55 int __cur_cmd; 56 57 void prompt_reset(void); 58 void prompt_input(int); 59 extern void __putchar(int); 60 61 void 62 prompt(void) 63 { 64 int c; 65 66 prompt_reset(); 67 while (/*CONSTCOND*/1) 68 if ((c = getchar()) != 0) 69 prompt_input(c); 70 /* NOTREACHED */ 71 } 72 73 void 74 prompt_input(int c) 75 { 76 int i; 77 78 switch (c) { 79 case 32 ... 127: 80 __cmd->buf[__cmd->cur] = c; 81 __cmd->cur = (__cmd->cur >= CMDBUF_SIZE - 1) ? __cmd->cur : 82 __cmd->cur + 1; 83 if (__cmd->cur >= __cmd->max) 84 __cmd->max = __cmd->cur; 85 putchar(c); 86 break; 87 case '\r': 88 putchar('\n'); 89 if (__cmd->max > 0) { 90 cmd_exec(__cmd->buf); 91 prompt_reset(); 92 } else { 93 printf(PROMPT); 94 } 95 break; 96 case '\b': 97 if (__cmd->cur > 0) { 98 __cmd->buf[--__cmd->cur] = 0; 99 putchar(c); 100 } 101 break; 102 case 1: /* Ctrl a */ 103 __cmd->cur = __cmd->min; 104 putchar('\r'); 105 printf("%s", PROMPT); 106 break; 107 case 5: /* Ctrl e */ 108 __cmd->cur = __cmd->max; 109 goto redraw; 110 case 2: /* Ctrl b */ 111 if (__cmd->cur == __cmd->min) 112 return; 113 __cmd->cur--; 114 putchar(c); 115 break; 116 case 6: /* Ctrl f */ 117 if (__cmd->cur == __cmd->max) 118 return; 119 __cmd->cur++; 120 putchar(c); 121 break; 122 case 4: /* Ctrl d */ 123 if (__cmd->cur == __cmd->max) 124 return; 125 for (i = __cmd->cur; i < __cmd->max; i++) 126 __cmd->buf[i] = __cmd->buf[i + 1]; 127 __cmd->buf[i] = '\0'; 128 __cmd->max--; 129 goto redraw; 130 case 11: /* Ctrl k */ 131 for (i = __cmd->cur; i < __cmd->max; i++) { 132 __cmd->buf[i] = 0; 133 __cmd->max = __cmd->cur; 134 } 135 putchar(c); 136 break; 137 case 14: /* Ctrl n */ 138 __cur_cmd = (__cur_cmd + 1) & 0x7; 139 goto history_redraw; 140 case 16: /* Ctrl p */ 141 __cur_cmd = (__cur_cmd - 1) & 0x7; 142 history_redraw: 143 __cmd = &__cmd_buf[__cur_cmd]; 144 __cmd->cur = __cmd->max; 145 case 12: /* Ctrl l */ 146 redraw: 147 putchar('\r'); 148 putchar(11); 149 printf("%s%s", PROMPT, __cmd->buf); 150 break; 151 } 152 } 153 154 void 155 prompt_reset(void) 156 { 157 158 __cur_cmd = (__cur_cmd + 1) & 0x7; 159 __cmd = &__cmd_buf[__cur_cmd]; 160 memset(__cmd, 0, sizeof *__cmd); 161 printf(PROMPT); 162 } 163 164 bool 165 prompt_yesno(int interactive) 166 { 167 int i; 168 169 if (!interactive) 170 return true; 171 /* block until user input */ 172 while (/*CONSTCOND*/1) { 173 if ((i = getchar()) == 0) 174 continue; 175 if (i == 'N' || i == 'n') 176 return false; 177 if (i == 'Y' || i == 'y') 178 return true; 179 } 180 } 181 182 void 183 putchar(int c) 184 { 185 186 __putchar(c); 187 188 __log[__log_cnt++] = c; 189 __log_cnt &= LOG_MASK; 190 } 191 192 int 193 cmd_log_save(int argc, char *argp[], int interactive) 194 { 195 struct bfs *bfs; 196 197 if (bfs_init(&bfs) != 0) { 198 printf("no BFS partition.\n"); 199 return 1; 200 } 201 202 if (bfs_file_write(bfs, "boot.log", __log, LOG_SIZE) != 0) 203 printf("BFS write failed.\n"); 204 205 bfs_fini(bfs); 206 207 return 0; 208 } 209