xref: /netbsd-src/sys/arch/ews4800mips/stand/common/prompt.c (revision 276d4f85dc8ab239bf90d57377b1804c2abef035)
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