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
prompt(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
prompt_input(int c)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
prompt_reset(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
prompt_yesno(int interactive)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
putchar(int c)183 putchar(int c)
184 {
185
186 __putchar(c);
187
188 __log[__log_cnt++] = c;
189 __log_cnt &= LOG_MASK;
190 }
191
192 int
cmd_log_save(int argc,char * argp[],int interactive)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