⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmdedit.c

📁 手机嵌入式Linux下可用的busybox源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* vi: set sw=4 ts=4: *//* * Termios command line History and Editting. * * Copyright (c) 1986-2001 may safely be consumed by a BSD or GPL license. * Written by:   Vladimir Oleynik <dzo@simtreas.ru> * * Used ideas: *      Adam Rogoyski    <rogoyski@cs.utexas.edu> *      Dave Cinege      <dcinege@psychosis.com> *      Jakub Jelinek (c) 1995 *      Erik Andersen    <andersee@debian.org> (Majorly adjusted for busybox) * * This code is 'as is' with no warranty. * * *//*   Usage and Known bugs:   Terminal key codes are not extensive, and more will probably   need to be added. This version was created on Debian GNU/Linux 2.x.   Delete, Backspace, Home, End, and the arrow keys were tested   to work in an Xterm and console. Ctrl-A also works as Home.   Ctrl-E also works as End.   Small bugs (simple effect):   - not true viewing if terminal size (x*y symbols) less     size (prompt + editor`s line + 2 symbols)   - not true viewing if length prompt less terminal width */#include <stdio.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/ioctl.h>#include <ctype.h>#include <signal.h>#include <limits.h>#include "busybox.h"#ifdef BB_LOCALE_SUPPORT#define Isprint(c) isprint((c))#else#define Isprint(c) ( (c) >= ' ' && (c) != ((unsigned char)'\233') )#endif#ifndef TEST#define D(x)#else#define BB_FEATURE_COMMAND_EDITING#define BB_FEATURE_COMMAND_TAB_COMPLETION#define BB_FEATURE_COMMAND_USERNAME_COMPLETION#define BB_FEATURE_NONPRINTABLE_INVERSE_PUT#define BB_FEATURE_CLEAN_UP#define D(x)  x#endif							/* TEST */#ifdef BB_FEATURE_COMMAND_TAB_COMPLETION#include <dirent.h>#include <sys/stat.h>#endif#ifdef BB_FEATURE_COMMAND_EDITING#ifndef BB_FEATURE_COMMAND_TAB_COMPLETION#undef  BB_FEATURE_COMMAND_USERNAME_COMPLETION#endif#if defined(BB_FEATURE_COMMAND_USERNAME_COMPLETION) || defined(BB_FEATURE_SH_FANCY_PROMPT)#define BB_FEATURE_GETUSERNAME_AND_HOMEDIR#endif#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR#       ifndef TEST#               include "pwd_grp/pwd.h"#       else#               include <pwd.h>#       endif  /* TEST */#endif							/* advanced FEATURES */struct history {	char *s;	struct history *p;	struct history *n;};/* Maximum length of the linked list for the command line history */static const int MAX_HISTORY = 15;/* First element in command line list */static struct history *his_front = NULL;/* Last element in command line list */static struct history *his_end = NULL;#include <termios.h>#define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)#define getTermSettings(fd,argp) tcgetattr(fd, argp);/* Current termio and the previous termio before starting sh */static struct termios initial_settings, new_settings;staticvolatile int cmdedit_termw = 80;	/* actual terminal width */static int history_counter = 0;	/* Number of commands in history list */staticvolatile int handlers_sets = 0;	/* Set next bites: */enum {	SET_ATEXIT = 1,		/* when atexit() has been called 				   and get euid,uid,gid to fast compare */	SET_WCHG_HANDLERS = 2,  /* winchg signal handler */	SET_RESET_TERM = 4,     /* if the terminal needs to be reset upon exit */};static int cmdedit_x;		/* real x terminal position */static int cmdedit_y;		/* pseudoreal y terminal position */static int cmdedit_prmt_len;	/* lenght prompt without colores string */static int cursor;		/* required global for signal handler */static int len;			/* --- "" - - "" - -"- --""-- --""--- */static char *command_ps;	/* --- "" - - "" - -"- --""-- --""--- */static#ifndef BB_FEATURE_SH_FANCY_PROMPT	const#endifchar *cmdedit_prompt;		/* --- "" - - "" - -"- --""-- --""--- */#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIRstatic char *user_buf = "";static char *home_pwd_buf = "";static int my_euid;#endif#ifdef BB_FEATURE_SH_FANCY_PROMPTstatic char *hostname_buf = "";static int num_ok_lines = 1;#endif#ifdef  BB_FEATURE_COMMAND_TAB_COMPLETION#ifndef BB_FEATURE_GETUSERNAME_AND_HOMEDIRstatic int my_euid;#endifstatic int my_uid;static int my_gid;#endif	/* BB_FEATURE_COMMAND_TAB_COMPLETION *//* It seems that libc5 doesn't know what a sighandler_t is... */#if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ < 1)typedef void (*sighandler_t) (int);#endifstatic void cmdedit_setwidth(int w, int redraw_flg);static void win_changed(int nsig){	struct winsize win = { 0, 0, 0, 0 };	static sighandler_t previous_SIGWINCH_handler;	/* for reset */	/*   emulate      || signal call */	if (nsig == -SIGWINCH || nsig == SIGWINCH) {		ioctl(0, TIOCGWINSZ, &win);		if (win.ws_col > 0) {			cmdedit_setwidth(win.ws_col, nsig == SIGWINCH);		} 	}	/* Unix not all standart in recall signal */	if (nsig == -SIGWINCH)		/* save previous handler   */		previous_SIGWINCH_handler = signal(SIGWINCH, win_changed);	else if (nsig == SIGWINCH)	/* signaled called handler */		signal(SIGWINCH, win_changed);	/* set for next call       */	else						/* nsig == 0 */		/* set previous handler    */		signal(SIGWINCH, previous_SIGWINCH_handler);	/* reset    */}static void cmdedit_reset_term(void){	if ((handlers_sets & SET_RESET_TERM) != 0) {/* sparc and other have broken termios support: use old termio handling. */		setTermSettings(fileno(stdin), (void *) &initial_settings);		handlers_sets &= ~SET_RESET_TERM;	}	if ((handlers_sets & SET_WCHG_HANDLERS) != 0) {		/* reset SIGWINCH handler to previous (default) */		win_changed(0);		handlers_sets &= ~SET_WCHG_HANDLERS;	}	fflush(stdout);#if 0//#ifdef BB_FEATURE_CLEAN_UP	if (his_front) {		struct history *n;		while (his_front != his_end) {			n = his_front->n;			free(his_front->s);			free(his_front);			his_front = n;		}	}#endif}/* special for recount position for scroll and remove terminal margin effect */static void cmdedit_set_out_char(int next_char){	int c = (int)((unsigned char) command_ps[cursor]);	if (c == 0)		c = ' ';	/* destroy end char? */#ifdef BB_FEATURE_NONPRINTABLE_INVERSE_PUT	if (!Isprint(c)) {	/* Inverse put non-printable characters */		if (c >= 128)			c -= 128;		if (c < ' ')			c += '@';		if (c == 127)			c = '?';		printf("\033[7m%c\033[0m", c);	} else#endif		putchar(c);	if (++cmdedit_x >= cmdedit_termw) {		/* terminal is scrolled down */		cmdedit_y++;		cmdedit_x = 0;		if (!next_char)			next_char = ' ';		/* destroy "(auto)margin" */		putchar(next_char);		putchar('\b');	}	cursor++;}/* Move to end line. Bonus: rewrite line from cursor */static void input_end(void){	while (cursor < len)		cmdedit_set_out_char(0);}/* Go to the next line */static void goto_new_line(void){	input_end();	if (cmdedit_x)		putchar('\n');}static inline void out1str(const char *s){	fputs(s, stdout);}static inline void beep(void){	putchar('\007');}/* Move back one charactor *//* special for slow terminal */static void input_backward(int num){	if (num > cursor)		num = cursor;	cursor -= num;		/* new cursor (in command, not terminal) */	if (cmdedit_x >= num) {		/* no to up line */		cmdedit_x -= num;		if (num < 4)			while (num-- > 0)				putchar('\b');		else			printf("\033[%dD", num);	} else {		int count_y;		if (cmdedit_x) {			putchar('\r');		/* back to first terminal pos.  */			num -= cmdedit_x;	/* set previous backward        */		}		count_y = 1 + num / cmdedit_termw;		printf("\033[%dA", count_y);		cmdedit_y -= count_y;		/*  require  forward  after  uping   */		cmdedit_x = cmdedit_termw * count_y - num;		printf("\033[%dC", cmdedit_x);	/* set term cursor   */	}}static void put_prompt(void){	out1str(cmdedit_prompt);	cmdedit_x = cmdedit_prmt_len;	/* count real x terminal position */	cursor = 0;	cmdedit_y = 0;                  /* new quasireal y */}#ifndef BB_FEATURE_SH_FANCY_PROMPTstatic void parse_prompt(const char *prmt_ptr){	cmdedit_prompt = prmt_ptr;	cmdedit_prmt_len = strlen(prmt_ptr);	put_prompt();}#elsestatic void parse_prompt(const char *prmt_ptr){	int prmt_len = 0;	int sub_len = 0;	char  flg_not_length = '[';	char *prmt_mem_ptr = xcalloc(1, 1);	char *pwd_buf = xgetcwd(0);	char  buf2[PATH_MAX + 1];	char  buf[2];	char  c;	char *pbuf;	if (!pwd_buf) {		pwd_buf=(char *)unknown;	}	while (*prmt_ptr) {		pbuf    = buf;		pbuf[1] = 0;		c = *prmt_ptr++;		if (c == '\\') {			const char *cp = prmt_ptr;			int l;						c = process_escape_sequence(&prmt_ptr);			if(prmt_ptr==cp) {			  if (*cp == 0)				break;			  c = *prmt_ptr++;			  switch (c) {#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR			  case 'u':				pbuf = user_buf;				break;#endif				  case 'h':				pbuf = hostname_buf;				if (*pbuf == 0) {					pbuf = xcalloc(256, 1);					if (gethostname(pbuf, 255) < 0) {						strcpy(pbuf, "?");					} else {						char *s = strchr(pbuf, '.');						if (s)							*s = 0;					}					hostname_buf = pbuf;				}				break;			  case '$':				c = my_euid == 0 ? '#' : '$';				break;#ifdef BB_FEATURE_GETUSERNAME_AND_HOMEDIR			  case 'w':				pbuf = pwd_buf;				l = strlen(home_pwd_buf);				if (home_pwd_buf[0] != 0 &&				    strncmp(home_pwd_buf, pbuf, l) == 0 &&				    (pbuf[l]=='/' || pbuf[l]=='\0') &&				    strlen(pwd_buf+l)<PATH_MAX) {					pbuf = buf2;					*pbuf = '~';					strcpy(pbuf+1, pwd_buf+l);					}				break;#endif				  case 'W':				pbuf = pwd_buf;				cp = strrchr(pbuf,'/');				if ( (cp != NULL) && (cp != pbuf) )					pbuf += (cp-pbuf)+1;				break;			  case '!':				snprintf(pbuf = buf2, sizeof(buf2), "%d", num_ok_lines);				break;			  case 'e': case 'E':     /* \e \E = \033 */				c = '\033';				break;			  case 'x': case 'X': 				for (l = 0; l < 3;) {					int h;					buf2[l++] = *prmt_ptr;					buf2[l] = 0;					h = strtol(buf2, &pbuf, 16);					if (h > UCHAR_MAX || (pbuf - buf2) < l) {						l--;						break;					}					prmt_ptr++;				}				buf2[l] = 0;				c = (char)strtol(buf2, 0, 16);				if(c==0)					c = '?';				pbuf = buf;				break;			  case '[': case ']':				if (c == flg_not_length) {					flg_not_length = flg_not_length == '[' ? ']' : '[';					continue;				}				break;			  }			} 		}		if(pbuf == buf)			*pbuf = c;		prmt_len += strlen(pbuf);		prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf);		if (flg_not_length == ']')			sub_len++;	}	if(pwd_buf!=(char *)unknown)		free(pwd_buf);	cmdedit_prompt = prmt_mem_ptr;	cmdedit_prmt_len = prmt_len - sub_len;	put_prompt();}#endif/* draw promt, editor line, and clear tail */static void redraw(int y, int back_cursor){	if (y > 0)				/* up to start y */		printf("\033[%dA", y);	putchar('\r');	put_prompt();	input_end();				/* rewrite */	printf("\033[J");			/* destroy tail after cursor */	input_backward(back_cursor);}/* Delete the char in front of the cursor */static void input_delete(void){	int j = cursor;	if (j == len)		return;	strcpy(command_ps + j, command_ps + j + 1);	len--;	input_end();			/* rewtite new line */	cmdedit_set_out_char(0);	/* destroy end char */	input_backward(cursor - j);	/* back to old pos cursor */}/* Delete the char in back of the cursor */static void input_backspace(void){	if (cursor > 0) {		input_backward(1);		input_delete();	}}/* Move forward one charactor */static void input_forward(void){	if (cursor < len)		cmdedit_set_out_char(command_ps[cursor + 1]);}static void cmdedit_setwidth(int w, int redraw_flg){	cmdedit_termw = cmdedit_prmt_len + 2;	if (w <= cmdedit_termw) {		cmdedit_termw = cmdedit_termw % w;	}	if (w > cmdedit_termw) {		cmdedit_termw = w;		if (redraw_flg) {			/* new y for current cursor */			int new_y = (cursor + cmdedit_prmt_len) / w;			/* redraw */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -