moved biggest stack buffers to malloc space, or made their size configurable

(8k of shell line edit buffer is an overkill)

# make ARCH=i386 bloatcheck
function                                             old     new   delta
read_line_input                                     3933    3967     +34
ifaddrlist                                           348     345      -3
do_loadfont                                          208     191     -17
edit_file                                            840     819     -21
.rodata                                           129112  129080     -32
uncompress                                          1305    1268     -37
loadfont_main                                        566     495     -71
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/6 up/down: 34/-181)          Total: -147 bytes
This commit is contained in:
Denis Vlasenko 2007-06-10 15:08:44 +00:00
parent d4fea900bd
commit e8a0788b24
8 changed files with 179 additions and 149 deletions

View File

@ -70,4 +70,5 @@ endif
#LDFLAGS += -nostdlib #LDFLAGS += -nostdlib
# Busybox is a stack-fatty so make sure we increase default size # Busybox is a stack-fatty so make sure we increase default size
# (TODO: use "make stksizes" to find & fix big stack users)
FLTFLAGS += -s 20000 FLTFLAGS += -s 20000

View File

@ -7,7 +7,6 @@
* (see disclaimer below) * (see disclaimer below)
*/ */
/* (N)compress42.c - File compression ala IEEE Computer, Mar 1992. /* (N)compress42.c - File compression ala IEEE Computer, Mar 1992.
* *
* Authors: * Authors:
@ -34,53 +33,48 @@
#define OBUFSIZ 2048 #define OBUFSIZ 2048
/* Defines for third byte of header */ /* Defines for third byte of header */
#define MAGIC_1 (char_type)'\037' /* First byte of compressed file */ #define BIT_MASK 0x1f /* Mask for 'number of compresssion bits' */
#define MAGIC_2 (char_type)'\235' /* Second byte of compressed file */ /* Masks 0x20 and 0x40 are free. */
#define BIT_MASK 0x1f /* Mask for 'number of compresssion bits' */ /* I think 0x20 should mean that there is */
/* Masks 0x20 and 0x40 are free. */ /* a fourth header byte (for expansion). */
/* I think 0x20 should mean that there is */ #define BLOCK_MODE 0x80 /* Block compression if table is full and */
/* a fourth header byte (for expansion). */ /* compression rate is dropping flush tables */
#define BLOCK_MODE 0x80 /* Block compresssion if table is full and */ /* the next two codes should not be changed lightly, as they must not */
/* compression rate is dropping flush tables */ /* lie within the contiguous general code space. */
/* the next two codes should not be changed lightly, as they must not */ #define FIRST 257 /* first free entry */
/* lie within the contiguous general code space. */ #define CLEAR 256 /* table clear output code */
#define FIRST 257 /* first free entry */
#define CLEAR 256 /* table clear output code */
#define INIT_BITS 9 /* initial number of bits/code */ #define INIT_BITS 9 /* initial number of bits/code */
/* machine variants which require cc -Dmachine: pdp11, z8000, DOS */ /* machine variants which require cc -Dmachine: pdp11, z8000, DOS */
#define FAST #define HBITS 17 /* 50% occupancy */
#define HSIZE (1<<HBITS)
#define HBITS 17 /* 50% occupancy */ #define HMASK (HSIZE-1) /* unused */
#define HSIZE (1<<HBITS) #define HPRIME 9941 /* unused */
#define HMASK (HSIZE-1) #define BITS 16
#define HPRIME 9941 #define BITS_STR "16"
#define BITS 16 #undef MAXSEG_64K /* unused */
#undef MAXSEG_64K #define MAXCODE(n) (1L << (n))
#define MAXCODE(n) (1L << (n))
#define htabof(i) htab[i]
#define codetabof(i) codetab[i]
#define tab_prefixof(i) codetabof(i)
#define tab_suffixof(i) ((unsigned char *)(htab))[i]
#define de_stack ((unsigned char *)&(htab[HSIZE-1]))
#define clear_htab() memset(htab, -1, HSIZE)
#define clear_tab_prefixof() memset(codetab, 0, 256);
#define htabof(i) htab[i]
#define codetabof(i) codetab[i]
#define tab_prefixof(i) codetabof(i)
#define tab_suffixof(i) ((unsigned char *)(htab))[i]
#define de_stack ((unsigned char *)&(htab[HSIZE-1]))
#define clear_tab_prefixof() memset(codetab, 0, 256)
/* /*
* Decompress stdin to stdout. This routine adapts to the codes in the * Decompress stdin to stdout. This routine adapts to the codes in the
* file building the "string" table on-the-fly; requiring no table to * file building the "string" table on-the-fly; requiring no table to
* be stored in the compressed file. The tables used herein are shared * be stored in the compressed file.
* with those of the compress() routine. See the definitions above.
*/ */
USE_DESKTOP(long long) int USE_DESKTOP(long long) int
uncompress(int fd_in, int fd_out) uncompress(int fd_in, int fd_out)
{ {
USE_DESKTOP(long long total_written = 0;) USE_DESKTOP(long long total_written = 0;)
USE_DESKTOP(long long) int retval = -1;
unsigned char *stackp; unsigned char *stackp;
long code; long code;
int finchar; int finchar;
@ -96,10 +90,10 @@ uncompress(int fd_in, int fd_out)
long maxmaxcode; long maxmaxcode;
int n_bits; int n_bits;
int rsize = 0; int rsize = 0;
RESERVE_CONFIG_UBUFFER(inbuf, IBUFSIZ + 64); unsigned char *inbuf; /* were eating insane amounts of stack - */
RESERVE_CONFIG_UBUFFER(outbuf, OBUFSIZ + 2048); unsigned char *outbuf; /* bad for some embedded targets */
unsigned char htab[HSIZE]; unsigned char *htab;
unsigned short codetab[HSIZE]; unsigned short *codetab;
/* Hmm, these were statics - why?! */ /* Hmm, these were statics - why?! */
/* user settable max # bits/code */ /* user settable max # bits/code */
@ -107,8 +101,10 @@ uncompress(int fd_in, int fd_out)
/* block compress mode -C compatible with 2.0 */ /* block compress mode -C compatible with 2.0 */
int block_mode; /* = BLOCK_MODE; */ int block_mode; /* = BLOCK_MODE; */
memset(inbuf, 0, IBUFSIZ + 64); inbuf = xzalloc(IBUFSIZ + 64);
memset(outbuf, 0, OBUFSIZ + 2048); outbuf = xzalloc(OBUFSIZ + 2048);
htab = xzalloc(HSIZE); /* wsn't zeroed out before, maybe can xmalloc? */
codetab = xzalloc(HSIZE * sizeof(codetab[0]));
insize = 0; insize = 0;
@ -116,7 +112,7 @@ uncompress(int fd_in, int fd_out)
* to do some cleanup (e.g. delete incomplete unpacked file etc) */ * to do some cleanup (e.g. delete incomplete unpacked file etc) */
if (full_read(fd_in, inbuf, 1) != 1) { if (full_read(fd_in, inbuf, 1) != 1) {
bb_error_msg("short read"); bb_error_msg("short read");
return -1; goto err;
} }
maxbits = inbuf[0] & BIT_MASK; maxbits = inbuf[0] & BIT_MASK;
@ -125,8 +121,8 @@ uncompress(int fd_in, int fd_out)
if (maxbits > BITS) { if (maxbits > BITS) {
bb_error_msg("compressed with %d bits, can only handle " bb_error_msg("compressed with %d bits, can only handle "
"%d bits", maxbits, BITS); BITS_STR" bits", maxbits);
return -1; goto err;
} }
n_bits = INIT_BITS; n_bits = INIT_BITS;
@ -140,7 +136,7 @@ uncompress(int fd_in, int fd_out)
free_ent = ((block_mode) ? FIRST : 256); free_ent = ((block_mode) ? FIRST : 256);
/* As above, initialize the first 256 entries in the table. */ /* As above, initialize the first 256 entries in the table. */
clear_tab_prefixof(); /*clear_tab_prefixof(); - done by xzalloc */
for (code = 255; code >= 0; --code) { for (code = 255; code >= 0; --code) {
tab_suffixof(code) = (unsigned char) code; tab_suffixof(code) = (unsigned char) code;
@ -232,7 +228,7 @@ uncompress(int fd_in, int fd_out)
insize, posbits, p[-1], p[0], p[1], p[2], p[3], insize, posbits, p[-1], p[0], p[1], p[2], p[3],
(posbits & 07)); (posbits & 07));
bb_error_msg("uncompress: corrupt input"); bb_error_msg("uncompress: corrupt input");
return -1; goto err;
} }
*--stackp = (unsigned char) finchar; *--stackp = (unsigned char) finchar;
@ -299,7 +295,11 @@ uncompress(int fd_in, int fd_out)
USE_DESKTOP(total_written += outpos;) USE_DESKTOP(total_written += outpos;)
} }
RELEASE_CONFIG_BUFFER(inbuf); retval = USE_DESKTOP(total_written) + 0;
RELEASE_CONFIG_BUFFER(outbuf); err:
return USE_DESKTOP(total_written) + 0; free(inbuf);
free(outbuf);
free(htab);
free(codetab);
return retval;
} }

View File

@ -21,43 +21,27 @@ enum {
}; };
struct psf_header { struct psf_header {
unsigned char magic1, magic2; /* Magic number */ unsigned char magic1, magic2; /* Magic number */
unsigned char mode; /* PSF font mode */ unsigned char mode; /* PSF font mode */
unsigned char charsize; /* Character size */ unsigned char charsize; /* Character size */
}; };
#define PSF_MAGIC_OK(x) ((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2) #define PSF_MAGIC_OK(x) ((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2)
static void loadnewfont(int fd);
int loadfont_main(int argc, char **argv);
int loadfont_main(int argc, char **argv)
{
int fd;
if (argc != 1)
bb_show_usage();
fd = xopen(CURRENT_VC, O_RDWR);
loadnewfont(fd);
return EXIT_SUCCESS;
}
static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize) static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize)
{ {
char buf[16384]; char *buf;
int i; int i;
memset(buf, 0, sizeof(buf));
if (unit < 1 || unit > 32) if (unit < 1 || unit > 32)
bb_error_msg_and_die("bad character size %d", unit); bb_error_msg_and_die("bad character size %d", unit);
buf = xzalloc(16 * 1024);
/*memset(buf, 0, 16 * 1024);*/
for (i = 0; i < fontsize; i++) for (i = 0; i < fontsize; i++)
memcpy(buf + (32 * i), inbuf + (unit * i), unit); memcpy(buf + (32 * i), inbuf + (unit * i), unit);
#if defined( PIO_FONTX ) && !defined( __sparc__ ) #if defined(PIO_FONTX) && !defined(__sparc__)
{ {
struct consolefontdesc cfd; struct consolefontdesc cfd;
@ -66,12 +50,14 @@ static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize)
cfd.chardata = buf; cfd.chardata = buf;
if (ioctl(fd, PIO_FONTX, &cfd) == 0) if (ioctl(fd, PIO_FONTX, &cfd) == 0)
return; /* success */ goto ret; /* success */
bb_perror_msg("PIO_FONTX ioctl error (trying PIO_FONT)"); bb_perror_msg("PIO_FONTX ioctl (will try PIO_FONT)");
} }
#endif #endif
if (ioctl(fd, PIO_FONT, buf)) if (ioctl(fd, PIO_FONT, buf))
bb_perror_msg_and_die("PIO_FONT ioctl error"); bb_perror_msg_and_die("PIO_FONT ioctl");
ret:
free(buf);
} }
static void static void
@ -124,31 +110,30 @@ do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize)
static void loadnewfont(int fd) static void loadnewfont(int fd)
{ {
enum { INBUF_SIZE = 32*1024 + 1 };
int unit; int unit;
unsigned char inbuf[32768]; /* primitive */ unsigned inputlth, offset;
unsigned int inputlth, offset; /* Was on stack, but 32k is a bit too much: */
unsigned char *inbuf = xmalloc(INBUF_SIZE);
/* /*
* We used to look at the length of the input file * We used to look at the length of the input file
* with stat(); now that we accept compressed files, * with stat(); now that we accept compressed files,
* just read the entire file. * just read the entire file.
*/ */
inputlth = fread(inbuf, 1, sizeof(inbuf), stdin); inputlth = full_read(STDIN_FILENO, inbuf, INBUF_SIZE);
if (ferror(stdin)) if (inputlth < 0)
bb_perror_msg_and_die("error reading input font"); bb_perror_msg_and_die("error reading input font");
/* use malloc/realloc in case of giant files; if (inputlth >= INBUF_SIZE)
maybe these do not occur: 16kB for the font, bb_error_msg_and_die("font too large");
and 16kB for the map leaves 32 unicode values
for each font position */
if (!feof(stdin))
bb_perror_msg_and_die("font too large");
/* test for psf first */ /* test for psf first */
{ {
struct psf_header psfhdr; struct psf_header psfhdr;
int fontsize; int fontsize;
int hastable; int hastable;
unsigned int head0, head; unsigned head0, head;
if (inputlth < sizeof(struct psf_header)) if (inputlth < sizeof(struct psf_header))
goto no_psf; goto no_psf;
@ -161,7 +146,7 @@ static void loadnewfont(int fd)
if (psfhdr.mode > PSF_MAXMODE) if (psfhdr.mode > PSF_MAXMODE)
bb_error_msg_and_die("unsupported psf file mode"); bb_error_msg_and_die("unsupported psf file mode");
fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256); fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256);
#if !defined( PIO_FONTX ) || defined( __sparc__ ) #if !defined(PIO_FONTX) || defined(__sparc__)
if (fontsize != 256) if (fontsize != 256)
bb_error_msg_and_die("only fontsize 256 supported"); bb_error_msg_and_die("only fontsize 256 supported");
#endif #endif
@ -177,8 +162,8 @@ static void loadnewfont(int fd)
do_loadtable(fd, inbuf + head, inputlth - head, fontsize); do_loadtable(fd, inbuf + head, inputlth - head, fontsize);
return; return;
} }
no_psf:
no_psf:
/* file with three code pages? */ /* file with three code pages? */
if (inputlth == 9780) { if (inputlth == 9780) {
offset = 40; offset = 40;
@ -192,3 +177,17 @@ static void loadnewfont(int fd)
} }
do_loadfont(fd, inbuf + offset, unit, 256); do_loadfont(fd, inbuf + offset, unit, 256);
} }
int loadfont_main(int argc, char **argv);
int loadfont_main(int argc, char **argv)
{
int fd;
if (argc != 1)
bb_show_usage();
fd = xopen(CURRENT_VC, O_RDWR);
loadnewfont(fd);
return EXIT_SUCCESS;
}

View File

@ -50,6 +50,16 @@ config VI
learning curve. If you are not already comfortable with 'vi' learning curve. If you are not already comfortable with 'vi'
you may wish to use something else. you may wish to use something else.
config FEATURE_VI_MAX_LEN
int "Maximum line length in vi"
range 256 16384
default 1024
depends on VI
help
vi uses on-stack buffers for intermediate line buffers.
You may want to decrease this parameter if your target machine
benefits from smaller stack usage.
config FEATURE_VI_COLON config FEATURE_VI_COLON
bool "Enable \":\" colon commands (no \"ex\" mode)" bool "Enable \":\" colon commands (no \"ex\" mode)"
default y default y

View File

@ -32,7 +32,10 @@
#define Isprint(c) ((unsigned char)(c) >= ' ' && (c) != 0x7f && (unsigned char)(c) != 0x9b) #define Isprint(c) ((unsigned char)(c) >= ' ' && (c) != 0x7f && (unsigned char)(c) != 0x9b)
#endif #endif
#define MAX_SCR_COLS BUFSIZ enum {
MAX_LINELEN = CONFIG_FEATURE_VI_MAX_LEN,
MAX_SCR_COLS = CONFIG_FEATURE_VI_MAX_LEN,
};
// Misc. non-Ascii keys that report an escape sequence // Misc. non-Ascii keys that report an escape sequence
#define VI_K_UP (char)128 // cursor key Up #define VI_K_UP (char)128 // cursor key Up
@ -545,7 +548,7 @@ static char *get_one_address(char * p, int *addr) // get colon addr, if present
char c; char c;
#endif #endif
#if ENABLE_FEATURE_VI_SEARCH #if ENABLE_FEATURE_VI_SEARCH
char *pat, buf[BUFSIZ]; char *pat, buf[MAX_LINELEN];
#endif #endif
*addr = -1; // assume no addr *addr = -1; // assume no addr
@ -648,7 +651,7 @@ static void setops(const char *args, const char *opname, int flg_no,
static void colon(char * buf) static void colon(char * buf)
{ {
char c, *orig_buf, *buf1, *q, *r; char c, *orig_buf, *buf1, *q, *r;
char *fn, cmd[BUFSIZ], args[BUFSIZ]; char *fn, cmd[MAX_LINELEN], args[MAX_LINELEN];
int i, l, li, ch, b, e; int i, l, li, ch, b, e;
int useforce = FALSE, forced = FALSE; int useforce = FALSE, forced = FALSE;
struct stat st_buf; struct stat st_buf;
@ -679,8 +682,8 @@ static void colon(char * buf)
r = end - 1; r = end - 1;
li = count_lines(text, end - 1); li = count_lines(text, end - 1);
fn = cfn; // default to current file fn = cfn; // default to current file
memset(cmd, '\0', BUFSIZ); // clear cmd[] memset(cmd, '\0', MAX_LINELEN); // clear cmd[]
memset(args, '\0', BUFSIZ); // clear args[] memset(args, '\0', MAX_LINELEN); // clear args[]
// look for optional address(es) :. :1 :1,9 :'q,'a :% // look for optional address(es) :. :1 :1,9 :'q,'a :%
buf = get_address(buf, &b, &e); buf = get_address(buf, &b, &e);
@ -763,10 +766,10 @@ static void colon(char * buf)
} }
if (args[0]) { if (args[0]) {
// the user supplied a file name // the user supplied a file name
fn= args; fn = args;
} else if (cfn && cfn[0]) { } else if (cfn && cfn[0]) {
// no user supplied name- use the current filename // no user supplied name- use the current filename
fn= cfn; fn = cfn;
goto vc5; goto vc5;
} else { } else {
// no user file name, no current name- punt // no user file name, no current name- punt
@ -1984,8 +1987,7 @@ static void start_new_cmd_q(char c)
// release old cmd // release old cmd
free(last_modifying_cmd); free(last_modifying_cmd);
// get buffer for new cmd // get buffer for new cmd
last_modifying_cmd = xmalloc(BUFSIZ); last_modifying_cmd = xzalloc(MAX_LINELEN);
memset(last_modifying_cmd, '\0', BUFSIZ); // clear new cmd queue
// if there is a current cmd count put it in the buffer first // if there is a current cmd count put it in the buffer first
if (cmdcnt > 0) if (cmdcnt > 0)
sprintf(last_modifying_cmd, "%d%c", cmdcnt, c); sprintf(last_modifying_cmd, "%d%c", cmdcnt, c);
@ -2238,7 +2240,7 @@ static char readit(void) // read (maybe cursor) key from stdin
if (n <= 0) { if (n <= 0) {
ri0: ri0:
// the Q is empty, wait for a typed char // the Q is empty, wait for a typed char
n = read(0, readbuffer, BUFSIZ - 1); n = read(0, readbuffer, MAX_LINELEN - 1);
if (n < 0) { if (n < 0) {
if (errno == EINTR) if (errno == EINTR)
goto ri0; // interrupted sys call goto ri0; // interrupted sys call
@ -2268,9 +2270,9 @@ static char readit(void) // read (maybe cursor) key from stdin
tv.tv_usec = 50000; // Wait 5/100 seconds- 1 Sec=1000000 tv.tv_usec = 50000; // Wait 5/100 seconds- 1 Sec=1000000
// keep reading while there are input chars and room in buffer // keep reading while there are input chars and room in buffer
while (select(1, &rfds, NULL, NULL, &tv) > 0 && n <= (BUFSIZ - 5)) { while (select(1, &rfds, NULL, NULL, &tv) > 0 && n <= (MAX_LINELEN - 5)) {
// read the rest of the ESC string // read the rest of the ESC string
int r = read(0, (void *) (readbuffer + n), BUFSIZ - n); int r = read(0, (void *) (readbuffer + n), MAX_LINELEN - n);
if (r > 0) { if (r > 0) {
n += r; n += r;
} }
@ -2305,7 +2307,7 @@ static char readit(void) // read (maybe cursor) key from stdin
} }
// remove key sequence from Q // remove key sequence from Q
readed_for_parse -= n; readed_for_parse -= n;
memmove(readbuffer, readbuffer + n, BUFSIZ - n); memmove(readbuffer, readbuffer + n, MAX_LINELEN - n);
alarm(3); // we are done waiting for input, turn alarm ON alarm(3); // we are done waiting for input, turn alarm ON
return c; return c;
} }
@ -2340,7 +2342,7 @@ static char get_one_char(void)
c = readit(); // get the users input c = readit(); // get the users input
if (last_modifying_cmd != 0) { if (last_modifying_cmd != 0) {
int len = strlen(last_modifying_cmd); int len = strlen(last_modifying_cmd);
if (len + 1 >= BUFSIZ) { if (len >= MAX_LINELEN - 1) {
psbs("last_modifying_cmd overrun"); psbs("last_modifying_cmd overrun");
} else { } else {
// add new char to q // add new char to q
@ -2358,7 +2360,7 @@ static char *get_input_line(const char * prompt) // get input line- use "status
{ {
static char *obufp; static char *obufp;
char buf[BUFSIZ]; char buf[MAX_LINELEN];
char c; char c;
int i; int i;
@ -2369,7 +2371,7 @@ static char *get_input_line(const char * prompt) // get input line- use "status
write1(prompt); // write out the :, /, or ? prompt write1(prompt); // write out the :, /, or ? prompt
i = strlen(buf); i = strlen(buf);
while (i < BUFSIZ) { while (i < MAX_LINELEN) {
c = get_one_char(); // read user input c = get_one_char(); // read user input
if (c == '\n' || c == '\r' || c == 27) if (c == '\n' || c == '\r' || c == 27)
break; // is this end of input break; // is this end of input
@ -2514,16 +2516,16 @@ static int file_write(char * fn, char * first, char * last)
//----- Move the cursor to row x col (count from 0, not 1) ------- //----- Move the cursor to row x col (count from 0, not 1) -------
static void place_cursor(int row, int col, int opti) static void place_cursor(int row, int col, int opti)
{ {
char cm1[BUFSIZ]; char cm1[MAX_LINELEN];
char *cm; char *cm;
#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR #if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
char cm2[BUFSIZ]; char cm2[MAX_LINELEN];
char *screenp; char *screenp;
// char cm3[BUFSIZ]; // char cm3[MAX_LINELEN];
int Rrow = last_row; int Rrow = last_row;
#endif #endif
memset(cm1, '\0', BUFSIZ - 1); // clear the buffer memset(cm1, '\0', MAX_LINELEN); // clear the buffer
if (row < 0) row = 0; if (row < 0) row = 0;
if (row >= rows) row = rows - 1; if (row >= rows) row = rows - 1;
@ -2539,7 +2541,7 @@ static void place_cursor(int row, int col, int opti)
#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR #if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
//----- find the minimum # of chars to move cursor ------------- //----- find the minimum # of chars to move cursor -------------
//----- 2. Try moving with discreet chars (Newline, [back]space, ...) //----- 2. Try moving with discreet chars (Newline, [back]space, ...)
memset(cm2, '\0', BUFSIZ - 1); // clear the buffer memset(cm2, '\0', MAX_LINELEN); // clear the buffer
// move to the correct row // move to the correct row
while (row < Rrow) { while (row < Rrow) {
@ -2696,7 +2698,7 @@ static void psb(const char *format, ...)
static void ni(const char * s) // display messages static void ni(const char * s) // display messages
{ {
char buf[BUFSIZ]; char buf[MAX_LINELEN];
print_literal(buf, s); print_literal(buf, s);
psbs("\'%s\' is not implemented", buf); psbs("\'%s\' is not implemented", buf);
@ -3900,7 +3902,7 @@ static void crash_dummy()
cd0: cd0:
startrbi = rbi = 0; startrbi = rbi = 0;
sleeptime = 0; // how long to pause between commands sleeptime = 0; // how long to pause between commands
memset(readbuffer, '\0', BUFSIZ); // clear the read buffer memset(readbuffer, '\0', MAX_LINELEN); // clear the read buffer
// generate a command by percentages // generate a command by percentages
percent = (int) lrand48() % 100; // get a number from 0-99 percent = (int) lrand48() % 100; // get a number from 0-99
if (percent < Mp) { // Movement commands if (percent < Mp) { // Movement commands
@ -3985,7 +3987,7 @@ static void crash_test()
static time_t oldtim; static time_t oldtim;
time_t tim; time_t tim;
char d[2], msg[BUFSIZ]; char d[2], msg[MAX_LINELEN];
msg[0] = '\0'; msg[0] = '\0';
if (end < text) { if (end < text) {

View File

@ -30,7 +30,17 @@ config FEATURE_EDITING
bool "Command line editing" bool "Command line editing"
default n default n
help help
Enable command editing (mainly for shell). Enable line editing (mainly for shell command line).
config FEATURE_EDITING_MAX_LEN
int "Maximum length of input"
range 128 8192
default 1024
depends on FEATURE_EDITING
help
Line editing code uses on-stack buffers for storage.
You may want to decrease this parameter if your target machine
benefits from smaller stack usage.
config FEATURE_EDITING_FANCY_KEYS config FEATURE_EDITING_FANCY_KEYS
bool "Additional editing keys" bool "Additional editing keys"

View File

@ -28,7 +28,6 @@
- not true viewing if length prompt less terminal width - not true viewing if length prompt less terminal width
*/ */
//#include <sys/ioctl.h>
#include "libbb.h" #include "libbb.h"
@ -59,6 +58,7 @@
#define ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR \ #define ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR \
(ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT) (ENABLE_FEATURE_USERNAME_COMPLETION || ENABLE_FEATURE_EDITING_FANCY_PROMPT)
enum { MAX_LINELEN = CONFIG_FEATURE_EDITING_MAX_LEN };
static line_input_t *state; static line_input_t *state;
@ -327,8 +327,8 @@ static void username_tab_completion(char *ud, char *with_shash_flg)
home = entry->pw_dir; home = entry->pw_dir;
} }
if (home) { if (home) {
if ((userlen + strlen(home) + 1) < BUFSIZ) { if ((userlen + strlen(home) + 1) < MAX_LINELEN) {
char temp2[BUFSIZ]; /* argument size */ char temp2[MAX_LINELEN]; /* argument size */
/* /home/user/... */ /* /home/user/... */
sprintf(temp2, "%s%s", home, ud); sprintf(temp2, "%s%s", home, ud);
@ -410,7 +410,7 @@ static void exe_n_cwd_tab_completion(char *command, int type)
{ {
DIR *dir; DIR *dir;
struct dirent *next; struct dirent *next;
char dirbuf[BUFSIZ]; char dirbuf[MAX_LINELEN];
struct stat st; struct stat st;
char *path1[1]; char *path1[1];
char **paths = path1; char **paths = path1;
@ -496,16 +496,16 @@ static void exe_n_cwd_tab_completion(char *command, int type)
#define QUOT (UCHAR_MAX+1) #define QUOT (UCHAR_MAX+1)
#define collapse_pos(is, in) { \ #define collapse_pos(is, in) { \
memmove(int_buf+(is), int_buf+(in), (BUFSIZ+1-(is)-(in))*sizeof(int)); \ memmove(int_buf+(is), int_buf+(in), (MAX_LINELEN+1-(is)-(in))*sizeof(int)); \
memmove(pos_buf+(is), pos_buf+(in), (BUFSIZ+1-(is)-(in))*sizeof(int)); } memmove(pos_buf+(is), pos_buf+(in), (MAX_LINELEN+1-(is)-(in))*sizeof(int)); }
static int find_match(char *matchBuf, int *len_with_quotes) static int find_match(char *matchBuf, int *len_with_quotes)
{ {
int i, j; int i, j;
int command_mode; int command_mode;
int c, c2; int c, c2;
int int_buf[BUFSIZ + 1]; int int_buf[MAX_LINELEN + 1];
int pos_buf[BUFSIZ + 1]; int pos_buf[MAX_LINELEN + 1];
/* set to integer dimension characters and own positions */ /* set to integer dimension characters and own positions */
for (i = 0;; i++) { for (i = 0;; i++) {
@ -731,7 +731,7 @@ static void input_tab(int *lastWasTab)
if (!*lastWasTab) { if (!*lastWasTab) {
char *tmp, *tmp1; char *tmp, *tmp1;
int len_found; int len_found;
char matchBuf[BUFSIZ]; char matchBuf[MAX_LINELEN];
int find_type; int find_type;
int recalc_pos; int recalc_pos;
@ -781,6 +781,7 @@ static void input_tab(int *lastWasTab)
if (!matches) if (!matches)
return; /* not found */ return; /* not found */
/* find minimal match */ /* find minimal match */
// ash: yet another failure in trying to achieve "we don't die on OOM"
tmp1 = xstrdup(matches[0]); tmp1 = xstrdup(matches[0]);
for (tmp = tmp1; *tmp; tmp++) for (tmp = tmp1; *tmp; tmp++)
for (len_found = 1; len_found < num_matches; len_found++) for (len_found = 1; len_found < num_matches; len_found++)
@ -807,7 +808,7 @@ static void input_tab(int *lastWasTab)
} }
len_found = strlen(tmp); len_found = strlen(tmp);
/* have space to placed match? */ /* have space to placed match? */
if ((len_found - strlen(matchBuf) + command_len) < BUFSIZ) { if ((len_found - strlen(matchBuf) + command_len) < MAX_LINELEN) {
/* before word for match */ /* before word for match */
command_ps[cursor - recalc_pos] = 0; command_ps[cursor - recalc_pos] = 0;
/* save tail line */ /* save tail line */
@ -888,14 +889,14 @@ static void load_history(const char *fromfile)
fp = fopen(fromfile, "r"); fp = fopen(fromfile, "r");
if (fp) { if (fp) {
for (hi = 0; hi < MAX_HISTORY;) { for (hi = 0; hi < MAX_HISTORY;) {
char * hl = xmalloc_getline(fp); char *hl = xmalloc_getline(fp);
int l; int l;
if (!hl) if (!hl)
break; break;
l = strlen(hl); l = strlen(hl);
if (l >= BUFSIZ) if (l >= MAX_LINELEN)
hl[BUFSIZ-1] = 0; hl[MAX_LINELEN-1] = '\0';
if (l == 0 || hl[0] == ' ') { if (l == 0 || hl[0] == ' ') {
free(hl); free(hl);
continue; continue;
@ -1264,8 +1265,8 @@ int read_line_input(const char* prompt, char* command, int maxsize, line_input_t
#endif #endif
// FIXME: audit & improve this // FIXME: audit & improve this
if (maxsize > BUFSIZ) if (maxsize > MAX_LINELEN)
maxsize = BUFSIZ; maxsize = MAX_LINELEN;
/* With null flags, no other fields are ever used */ /* With null flags, no other fields are ever used */
state = st ? st : (line_input_t*) &const_int_0; state = st ? st : (line_input_t*) &const_int_0;
@ -1646,14 +1647,14 @@ int read_line_input(const char* prompt, char* command, int maxsize, line_input_t
/* Delete */ /* Delete */
input_delete(0); input_delete(0);
break; break;
case '1': case '1': // vt100? linux vt? or what?
case 'H': case '7': // vt100? linux vt? or what?
/* <Home> */ case 'H': /* xterm's <Home> */
input_backward(cursor); input_backward(cursor);
break; break;
case '4': case '4': // vt100? linux vt? or what?
case 'F': case '8': // vt100? linux vt? or what?
/* <End> */ case 'F': /* xterm's <End> */
input_end(); input_end();
break; break;
default: default:
@ -1766,7 +1767,7 @@ const char *applet_name = "debug stuff usage";
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
char buff[BUFSIZ]; char buff[MAX_LINELEN];
char *prompt = char *prompt =
#if ENABLE_FEATURE_EDITING_FANCY_PROMPT #if ENABLE_FEATURE_EDITING_FANCY_PROMPT
"\\[\\033[32;1m\\]\\u@\\[\\x1b[33;1m\\]\\h:" "\\[\\033[32;1m\\]\\u@\\[\\x1b[33;1m\\]\\h:"

View File

@ -371,6 +371,8 @@ struct globals {
static int static int
ifaddrlist(struct IFADDRLIST **ipaddrp) ifaddrlist(struct IFADDRLIST **ipaddrp)
{ {
enum { IFREQ_BUFSIZE = (32 * 1024) / sizeof(struct ifreq) };
int fd, nipaddr; int fd, nipaddr;
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
int n; int n;
@ -379,22 +381,24 @@ ifaddrlist(struct IFADDRLIST **ipaddrp)
struct sockaddr_in *addr_sin; struct sockaddr_in *addr_sin;
struct IFADDRLIST *al; struct IFADDRLIST *al;
struct ifconf ifc; struct ifconf ifc;
struct ifreq ibuf[(32 * 1024) / sizeof(struct ifreq)], ifr; struct ifreq ifr;
/* Was on stack, but 32k is a bit too much: */
struct ifreq *ibuf = xmalloc(IFREQ_BUFSIZE * sizeof(ibuf[0]));
struct IFADDRLIST *st_ifaddrlist; struct IFADDRLIST *st_ifaddrlist;
fd = xsocket(AF_INET, SOCK_DGRAM, 0); fd = xsocket(AF_INET, SOCK_DGRAM, 0);
ifc.ifc_len = sizeof(ibuf); ifc.ifc_len = IFREQ_BUFSIZE * sizeof(ibuf[0]);
ifc.ifc_buf = (caddr_t)ibuf; ifc.ifc_buf = (caddr_t)ibuf;
if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0
ifc.ifc_len < sizeof(struct ifreq)) { || ifc.ifc_len < sizeof(struct ifreq)
) {
if (errno == EINVAL) if (errno == EINVAL)
bb_error_msg_and_die( bb_error_msg_and_die(
"SIOCGIFCONF: ifreq struct too small (%d bytes)", "SIOCGIFCONF: ifreq struct too small (%d bytes)",
(int)sizeof(ibuf)); IFREQ_BUFSIZE * sizeof(ibuf[0]));
else bb_perror_msg_and_die("SIOCGIFCONF");
bb_perror_msg_and_die("SIOCGIFCONF");
} }
ifrp = ibuf; ifrp = ibuf;
ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
@ -449,9 +453,10 @@ ifaddrlist(struct IFADDRLIST **ipaddrp)
++nipaddr; ++nipaddr;
} }
if (nipaddr == 0) if (nipaddr == 0)
bb_error_msg_and_die ("can't find any network interfaces"); bb_error_msg_and_die("can't find any network interfaces");
(void)close(fd);
free(ibuf);
close(fd);
*ipaddrp = st_ifaddrlist; *ipaddrp = st_ifaddrlist;
return nipaddr; return nipaddr;
} }
@ -492,11 +497,13 @@ findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from)
++n; ++n;
if (n == 1 && strncmp(buf, "Iface", 5) == 0) if (n == 1 && strncmp(buf, "Iface", 5) == 0)
continue; continue;
if ((i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x", i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x",
tdevice, &dest, &tmask)) != 3) tdevice, &dest, &tmask);
bb_error_msg_and_die ("junk in buffer"); if (i != 3)
if ((to->sin_addr.s_addr & tmask) == dest && bb_error_msg_and_die("junk in buffer");
(tmask > mask || mask == 0)) { if ((to->sin_addr.s_addr & tmask) == dest
&& (tmask > mask || mask == 0)
) {
mask = tmask; mask = tmask;
strcpy(device, tdevice); strcpy(device, tdevice);
} }
@ -504,7 +511,7 @@ findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from)
fclose(f); fclose(f);
if (device[0] == '\0') if (device[0] == '\0')
bb_error_msg_and_die ("can't find interface"); bb_error_msg_and_die("can't find interface");
/* Get the interface address list */ /* Get the interface address list */
n = ifaddrlist(&al); n = ifaddrlist(&al);
@ -808,7 +815,7 @@ packet_ok(unsigned char *buf, int cc, struct sockaddr_in *from, int seq)
"%s: icmp type %d (%s) code %d\n", "%s: icmp type %d (%s) code %d\n",
cc, inet_ntoa(from->sin_addr), cc, inet_ntoa(from->sin_addr),
inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
for (i = 4; i < cc ; i += sizeof(*lp)) for (i = 4; i < cc; i += sizeof(*lp))
printf("%2d: x%8.8x\n", i, *lp++); printf("%2d: x%8.8x\n", i, *lp++);
} }
#endif #endif