Home | History | Annotate | Line # | Download | only in common
      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