svn commit: trunk/busybox: include miscutils

vda at busybox.net vda at busybox.net
Sat Feb 23 01:25:38 UTC 2008


Author: vda
Date: 2008-02-22 17:25:38 -0800 (Fri, 22 Feb 2008)
New Revision: 21090

Log:
less: update line input so that it doesn't interfere with
screen update. Makes "man bash", [enter], [/],
<enter search pattern>, [enter] more usable - manpage
draws as you enter the pattern! Yay!!
less: fix bug where backspace wasn't actually deleting chars
less: "examine file with empty name" doesn't abort anymore.
libbb: add "all fatal signals" mask.

getch_nowait                                           -     207    +207
status_print                                           -     105    +105
examine_file                                          64      87     +23
move_cursor                                            -      16     +16
m_status_print                                       185     195     +10
less_main                                           1656    1663      +7
decode_format_string                                 790     795      +5
test_main                                            403     405      +2
process0_stdin                                       247     249      +2
passwd_main                                         1070    1072      +2
less_gets                                            196     178     -18
buffer_print                                         169      71     -98
less_getch                                           362     138    -224
------------------------------------------------------------------------------
(add/remove: 3/0 grow/shrink: 7/3 up/down: 379/-340)           Total: 39 bytes
   text    data     bss     dec     hex filename
 798329     740    7484  806553   c4e99 busybox_old
 798368     740    7484  806592   c4ec0 busybox_unstripped



Modified:
   trunk/busybox/include/libbb.h
   trunk/busybox/miscutils/less.c


Changeset:
Modified: trunk/busybox/include/libbb.h
===================================================================
--- trunk/busybox/include/libbb.h	2008-02-22 23:21:31 UTC (rev 21089)
+++ trunk/busybox/include/libbb.h	2008-02-23 01:25:38 UTC (rev 21090)
@@ -274,9 +274,32 @@
 
 char *xmalloc_follow_symlinks(const char *path);
 
-//enum {
-//	BB_SIGS_FATAL = ,
-//};
+enum {
+	/* bb_signals(BB_SIGS_FATAL, handler) catches all signals which
+	 * otherwise would kill us, except for those resulting from bugs:
+	 * SIGSEGV, SIGILL, SIGFPE.
+	 * Other fatal signals not included (TODO?):
+	 * SIGBUS   Bus error (bad memory access)
+	 * SIGPOLL  Pollable event. Synonym of SIGIO
+	 * SIGPROF  Profiling timer expired
+	 * SIGSYS   Bad argument to routine
+	 * SIGTRAP  Trace/breakpoint trap
+	 */
+	BB_SIGS_FATAL = 0
+		+ (1 << SIGHUP)
+		+ (1 << SIGINT)
+		+ (1 << SIGTERM)
+		+ (1 << SIGPIPE)   // Write to pipe with no readers
+		+ (1 << SIGQUIT)   // Quit from keyboard
+		+ (1 << SIGABRT)   // Abort signal from abort(3)
+		+ (1 << SIGALRM)   // Timer signal from alarm(2)
+		+ (1 << SIGVTALRM) // Virtual alarm clock
+		+ (1 << SIGXCPU)   // CPU time limit exceeded
+		+ (1 << SIGXFSZ)   // File size limit exceeded
+		+ (1 << SIGUSR1)   // Yes kids, these are also fatal!
+		+ (1 << SIGUSR2)
+		+ 0,
+};
 void bb_signals(int sigs, void (*f)(int));
 /* Unlike signal() and bb_signals, sets handler with sigaction()
  * and in a way that while signal handler is run, no other signals

Modified: trunk/busybox/miscutils/less.c
===================================================================
--- trunk/busybox/miscutils/less.c	2008-02-22 23:21:31 UTC (rev 21089)
+++ trunk/busybox/miscutils/less.c	2008-02-23 01:25:38 UTC (rev 21090)
@@ -90,6 +90,7 @@
 struct globals {
 	int cur_fline; /* signed */
 	int kbd_fd;  /* fd to get input from */
+	int less_gets_pos;
 /* last position in last line, taking into account tabs */
 	size_t linepos;
 	unsigned max_displayed_line;
@@ -123,6 +124,7 @@
 #define G (*ptr_to_globals)
 #define cur_fline           (G.cur_fline         )
 #define kbd_fd              (G.kbd_fd            )
+#define less_gets_pos       (G.less_gets_pos     )
 #define linepos             (G.linepos           )
 #define max_displayed_line  (G.max_displayed_line)
 #define max_fline           (G.max_fline         )
@@ -152,6 +154,7 @@
 #define term_less           (G.term_less         )
 #define INIT_G() do { \
 		PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
+		less_gets_pos = -1; \
 		empty_line_marker = "~"; \
 		num_files = 1; \
 		current_file = 1; \
@@ -385,6 +388,9 @@
 {
 	int percentage;
 
+	if (less_gets_pos >= 0)	/* don't touch statusline while input is done! */
+		return;
+
 	clear_line();
 	printf(HIGHLIGHT"%s", filename);
 	if (num_files > 1)
@@ -408,6 +414,9 @@
 {
 	const char *p;
 
+	if (less_gets_pos >= 0)	/* don't touch statusline while input is done! */
+		return;
+
 	/* Change the status if flags have been set */
 #if ENABLE_FEATURE_LESS_FLAGS
 	if (option_mask32 & (FLAG_M|FLAG_m)) {
@@ -652,43 +661,46 @@
 	buffer_fill_and_print();
 }
 
-static void getch_nowait(char* input, int sz)
+static ssize_t getch_nowait(char* input, int sz)
 {
 	ssize_t rd;
-	fd_set readfds;
+	struct pollfd pfd[2];
+
+	pfd[0].fd = STDIN_FILENO;
+	pfd[0].events = POLLIN;
+	pfd[1].fd = kbd_fd;
+	pfd[1].events = POLLIN;
  again:
-	fflush(stdout);
-
-	/* NB: select returns whenever read will not block. Therefore:
-	 * (a) with O_NONBLOCK'ed fds select will return immediately
-	 * (b) if eof is reached, select will also return
-	 *     because read will immediately return 0 bytes.
-	 * Even if select says that input is available, read CAN block
+	tcsetattr(kbd_fd, TCSANOW, &term_less);
+	/* NB: select/poll returns whenever read will not block. Therefore:
+	 * if eof is reached, select/poll will return immediately
+	 * because read will immediately return 0 bytes.
+	 * Even if select/poll says that input is available, read CAN block
 	 * (switch fd into O_NONBLOCK'ed mode to avoid it)
 	 */
-	FD_ZERO(&readfds);
+	rd = 1;
 	if (max_fline <= cur_fline + max_displayed_line
 	 && eof_error > 0 /* did NOT reach eof yet */
 	) {
 		/* We are interested in stdin */
-		FD_SET(0, &readfds);
+		rd = 0;
 	}
-	FD_SET(kbd_fd, &readfds);
-	tcsetattr(kbd_fd, TCSANOW, &term_less);
-	select(kbd_fd + 1, &readfds, NULL, NULL, NULL);
+	/* position cursor if line input is done */
+	if (less_gets_pos >= 0)
+		move_cursor(max_displayed_line + 2, less_gets_pos + 1);
+	fflush(stdout);
+	safe_poll(pfd + rd, 2 - rd, -1);
 
 	input[0] = '\0';
-	ndelay_on(kbd_fd);
-	rd = read(kbd_fd, input, sz);
-	ndelay_off(kbd_fd);
-	if (rd < 0) {
-		/* No keyboard input, but we have input on stdin! */
-		if (errno != EAGAIN) /* Huh?? */
-			return;
+	rd = safe_read(kbd_fd, input, sz); /* NB: kbd_fd is in O_NONBLOCK mode */
+	if (rd < 0 && errno == EAGAIN) {
+		/* No keyboard input -> we have input on stdin! */
 		read_lines();
 		buffer_fill_and_print();
 		goto again;
 	}
+	set_tty_cooked();
+	return rd;
 }
 
 /* Grab a character from input without requiring the return key. If the
@@ -696,7 +708,7 @@
  * special return codes. Note that this function works best with raw input. */
 static int less_getch(void)
 {
-	char input[16];
+	unsigned char input[16];
 	unsigned i;
  again:
 	memset(input, 0, sizeof(input));
@@ -705,7 +717,6 @@
 	/* Detect escape sequences (i.e. arrow keys) and handle
 	 * them accordingly */
 	if (input[0] == '\033' && input[1] == '[') {
-		set_tty_cooked();
 		i = input[2] - REAL_KEY_UP;
 		if (i < 4)
 			return 20 + i;
@@ -724,8 +735,8 @@
 	}
 	/* Reject almost all control chars */
 	i = input[0];
-	if (i < ' ' && i != 0x0d && i != 8) goto again;
-	set_tty_cooked();
+	if (i < ' ' && i != 0x0d && i != 8)
+		goto again;
 	return i;
 }
 
@@ -734,22 +745,21 @@
 	char c;
 	int i = 0;
 	char *result = xzalloc(1);
+
 	while (1) {
-		fflush(stdout);
-
-		/* I be damned if I know why is it needed *repeatedly*,
-		 * but it is needed. Is it because of stdio? */
-		tcsetattr(kbd_fd, TCSANOW, &term_less);
-
 		c = '\0';
-		read(kbd_fd, &c, 1);
-		if (c == 0x0d)
+		less_gets_pos = sz + i;
+		getch_nowait(&c, 1);
+		if (c == 0x0d) {
+			less_gets_pos = -1;
 			return result;
+		}
 		if (c == 0x7f)
 			c = 8;
 		if (c == 8 && i) {
 			printf("\x8 \x8");
 			i--;
+			result[i] = '\0';
 		}
 		if (c < ' ')
 			continue;
@@ -764,9 +774,17 @@
 
 static void examine_file(void)
 {
+	char *new_fname;
+
 	print_statusline("Examine: ");
+	new_fname = less_gets(sizeof("Examine: ")-1);
+	if (!new_fname[0]) {
+		free(new_fname);
+		status_print();
+		return;
+	}
 	free(filename);
-	filename = less_gets(sizeof("Examine: ")-1);
+	filename = new_fname;
 	/* files start by = argv. why we assume that argv is infinitely long??
 	files[num_files] = filename;
 	current_file = num_files + 1;
@@ -1087,7 +1105,7 @@
 
 	print_statusline("Log file: ");
 	current_line = less_gets(sizeof("Log file: ")-1);
-	if (strlen(current_line) > 0) {
+	if (current_line[0]) {
 		fp = fopen(current_line, "w");
 		if (!fp) {
 			msg = "Error opening log file";
@@ -1334,6 +1352,7 @@
 	kbd_fd = open(CURRENT_TTY, O_RDONLY);
 	if (kbd_fd < 0)
 		return bb_cat(argv);
+	ndelay_on(kbd_fd);
 
 	if (!num_files) {
 		if (isatty(STDIN_FILENO)) {
@@ -1354,11 +1373,9 @@
 	if (option_mask32 & FLAG_TILDE)
 		empty_line_marker = "";
 
+	bb_signals(BB_SIGS_FATAL, sig_catcher);
+
 	tcgetattr(kbd_fd, &term_orig);
-	bb_signals(0
-		+ (1 << SIGTERM)
-		+ (1 << SIGINT)
-		, sig_catcher);
 	term_less = term_orig;
 	term_less.c_lflag &= ~(ICANON | ECHO);
 	term_less.c_iflag &= ~(IXON | ICRNL);
@@ -1366,10 +1383,6 @@
 	term_less.c_cc[VMIN] = 1;
 	term_less.c_cc[VTIME] = 0;
 
-	/* Want to do it just once, but it doesn't work, */
-	/* so we are redoing it (see code above). Mystery... */
-	/*tcsetattr(kbd_fd, TCSANOW, &term_less);*/
-
 	reinitialize();
 	while (1) {
 		keypress = less_getch();




More information about the busybox-cvs mailing list