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