lineedit: reduce stack usage

netstat: reduce stack usage; fix handling of NULs in unix socket filenames

static.has_inode                                       1       -      -1
do_info                                              119     116      -3
deinit_S                                              60      51      -9
unix_do_one                                          578     451    -127
parse_and_put_prompt                                 966     825    -141
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 0/4 up/down: 0/-281)           Total: -281 bytes
This commit is contained in:
Denis Vlasenko 2007-12-03 10:45:14 +00:00
parent 2bec513996
commit 7221c8c22d
2 changed files with 81 additions and 84 deletions

View File

@ -91,7 +91,6 @@ struct statics {
const char *cmdedit_prompt; const char *cmdedit_prompt;
#if ENABLE_FEATURE_EDITING_FANCY_PROMPT #if ENABLE_FEATURE_EDITING_FANCY_PROMPT
char *hostname_buf;
int num_ok_lines; /* = 1; */ int num_ok_lines; /* = 1; */
#endif #endif
@ -136,7 +135,6 @@ static struct statics *const ptr_to_statics __attribute__ ((section (".data")));
#define command_len (S.command_len ) #define command_len (S.command_len )
#define command_ps (S.command_ps ) #define command_ps (S.command_ps )
#define cmdedit_prompt (S.cmdedit_prompt ) #define cmdedit_prompt (S.cmdedit_prompt )
#define hostname_buf (S.hostname_buf )
#define num_ok_lines (S.num_ok_lines ) #define num_ok_lines (S.num_ok_lines )
#define user_buf (S.user_buf ) #define user_buf (S.user_buf )
#define home_pwd_buf (S.home_pwd_buf ) #define home_pwd_buf (S.home_pwd_buf )
@ -155,7 +153,6 @@ static struct statics *const ptr_to_statics __attribute__ ((section (".data")));
static void deinit_S(void) static void deinit_S(void)
{ {
#if ENABLE_FEATURE_EDITING_FANCY_PROMPT #if ENABLE_FEATURE_EDITING_FANCY_PROMPT
free(hostname_buf);
/* This one is allocated only if FANCY_PROMPT is on /* This one is allocated only if FANCY_PROMPT is on
* (otherwise it points to verbatim prompt (NOT malloced) */ * (otherwise it points to verbatim prompt (NOT malloced) */
free((char*)cmdedit_prompt); free((char*)cmdedit_prompt);
@ -381,14 +378,14 @@ static void username_tab_completion(char *ud, char *with_shash_flg)
if (with_shash_flg) { /* "~/..." or "~user/..." */ if (with_shash_flg) { /* "~/..." or "~user/..." */
char *sav_ud = ud - 1; char *sav_ud = ud - 1;
char *home = NULL; char *home = NULL;
char *temp;
if (*ud == '/') { /* "~/..." */ if (*ud == '/') { /* "~/..." */
home = home_pwd_buf; home = home_pwd_buf;
} else { } else {
/* "~user/..." */ /* "~user/..." */
char *temp;
temp = strchr(ud, '/'); temp = strchr(ud, '/');
*temp = 0; /* ~user\0 */ *temp = '\0'; /* ~user\0 */
entry = getpwnam(ud); entry = getpwnam(ud);
*temp = '/'; /* restore ~user/... */ *temp = '/'; /* restore ~user/... */
ud = temp; ud = temp;
@ -1163,21 +1160,23 @@ static void parse_and_put_prompt(const char *prmt_ptr)
size_t cur_prmt_len = 0; size_t cur_prmt_len = 0;
char flg_not_length = '['; char flg_not_length = '[';
char *prmt_mem_ptr = xzalloc(1); char *prmt_mem_ptr = xzalloc(1);
char *pwd_buf = xrealloc_getcwd_or_warn(NULL); char *cwd_buf = xrealloc_getcwd_or_warn(NULL);
char buf2[PATH_MAX + 1]; char cbuf[2];
char buf[2];
char c; char c;
char *pbuf; char *pbuf;
cmdedit_prmt_len = 0; cmdedit_prmt_len = 0;
if (!pwd_buf) { if (!cwd_buf) {
pwd_buf = (char *)bb_msg_unknown; cwd_buf = (char *)bb_msg_unknown;
} }
cbuf[1] = '\0'; /* never changes */
while (*prmt_ptr) { while (*prmt_ptr) {
pbuf = buf; char *free_me = NULL;
pbuf[1] = 0;
pbuf = cbuf;
c = *prmt_ptr++; c = *prmt_ptr++;
if (c == '\\') { if (c == '\\') {
const char *cp = prmt_ptr; const char *cp = prmt_ptr;
@ -1188,6 +1187,7 @@ static void parse_and_put_prompt(const char *prmt_ptr)
if (*cp == '\0') if (*cp == '\0')
break; break;
c = *prmt_ptr++; c = *prmt_ptr++;
switch (c) { switch (c) {
#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
case 'u': case 'u':
@ -1195,87 +1195,81 @@ static void parse_and_put_prompt(const char *prmt_ptr)
break; break;
#endif #endif
case 'h': case 'h':
pbuf = hostname_buf; pbuf = free_me = xzalloc(256);
if (!pbuf) { if (gethostname(pbuf, 255) < 0) {
pbuf = xzalloc(256); pbuf[0] = '?';
if (gethostname(pbuf, 255) < 0) { pbuf[1] = '\0';
strcpy(pbuf, "?");
} else {
char *s = strchr(pbuf, '.');
if (s)
*s = '\0';
}
hostname_buf = pbuf;
} }
*strchrnul(pbuf, '.') = '\0';
break; break;
case '$': case '$':
c = (geteuid() == 0 ? '#' : '$'); c = (geteuid() == 0 ? '#' : '$');
break; break;
#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
case 'w': case 'w':
pbuf = pwd_buf; /* /home/user[/something] -> ~[/something] */
pbuf = cwd_buf;
l = strlen(home_pwd_buf); l = strlen(home_pwd_buf);
if (l != 0 if (l != 0
&& strncmp(home_pwd_buf, pbuf, l) == 0 && strncmp(home_pwd_buf, cwd_buf, l) == 0
&& (pbuf[l]=='/' || pbuf[l]=='\0') && (cwd_buf[l]=='/' || cwd_buf[l]=='\0')
&& strlen(pwd_buf+l) < PATH_MAX && strlen(cwd_buf + l) < PATH_MAX
) { ) {
pbuf = buf2; pbuf = free_me = xasprintf("~%s", cwd_buf + l);
*pbuf = '~';
strcpy(pbuf+1, pwd_buf+l);
} }
break; break;
#endif #endif
case 'W': case 'W':
pbuf = pwd_buf; pbuf = cwd_buf;
cp = strrchr(pbuf, '/'); cp = strrchr(pbuf, '/');
if (cp != NULL && cp != pbuf) if (cp != NULL && cp != pbuf)
pbuf += (cp-pbuf) + 1; pbuf += (cp-pbuf) + 1;
break; break;
case '!': case '!':
pbuf = buf2; pbuf = free_me = xasprintf("%d", num_ok_lines);
snprintf(buf2, sizeof(buf2), "%d", num_ok_lines);
break; break;
case 'e': case 'E': /* \e \E = \033 */ case 'e': case 'E': /* \e \E = \033 */
c = '\033'; c = '\033';
break; break;
case 'x': case 'X': case 'x': case 'X': {
char buf2[4];
for (l = 0; l < 3;) { for (l = 0; l < 3;) {
int h; unsigned h;
buf2[l++] = *prmt_ptr; buf2[l++] = *prmt_ptr;
buf2[l] = 0; buf2[l] = '\0';
h = strtol(buf2, &pbuf, 16); h = strtoul(buf2, &pbuf, 16);
if (h > UCHAR_MAX || (pbuf - buf2) < l) { if (h > UCHAR_MAX || (pbuf - buf2) < l) {
l--; buf2[--l] = '\0';
break; break;
} }
prmt_ptr++; prmt_ptr++;
} }
buf2[l] = 0; c = (char)strtoul(buf2, NULL, 16);
c = (char)strtol(buf2, NULL, 16);
if (c == 0) if (c == 0)
c = '?'; c = '?';
pbuf = buf; pbuf = cbuf;
break; break;
}
case '[': case ']': case '[': case ']':
if (c == flg_not_length) { if (c == flg_not_length) {
flg_not_length = (flg_not_length == '[' ? ']' : '['); flg_not_length = (flg_not_length == '[' ? ']' : '[');
continue; continue;
} }
break; break;
} } /* switch */
} } /* if */
} } /* if */
if (pbuf == buf) cbuf[0] = c;
*pbuf = c;
cur_prmt_len = strlen(pbuf); cur_prmt_len = strlen(pbuf);
prmt_len += cur_prmt_len; prmt_len += cur_prmt_len;
if (flg_not_length != ']') if (flg_not_length != ']')
cmdedit_prmt_len += cur_prmt_len; cmdedit_prmt_len += cur_prmt_len;
prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf); prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf);
} free(free_me);
if (pwd_buf != (char *)bb_msg_unknown) } /* while */
free(pwd_buf);
if (cwd_buf != (char *)bb_msg_unknown)
free(cwd_buf);
cmdedit_prompt = prmt_mem_ptr; cmdedit_prompt = prmt_mem_ptr;
put_prompt(); put_prompt();
} }
@ -1397,7 +1391,6 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t
if (entry) { if (entry) {
user_buf = xstrdup(entry->pw_name); user_buf = xstrdup(entry->pw_name);
home_pwd_buf = xstrdup(entry->pw_dir); home_pwd_buf = xstrdup(entry->pw_dir);
/* They are not freed on exit (too small to bother) */
} }
} }
#endif #endif

View File

@ -148,7 +148,7 @@ static char *ip_port_str(struct sockaddr *addr, int port, const char *proto, int
return host_port; return host_port;
} }
static void tcp_do_one(int lnr, const char *line) static void tcp_do_one(int lnr, char *line)
{ {
char local_addr[64], rem_addr[64]; char local_addr[64], rem_addr[64];
char more[512]; char more[512];
@ -201,7 +201,7 @@ static void tcp_do_one(int lnr, const char *line)
} }
} }
static void udp_do_one(int lnr, const char *line) static void udp_do_one(int lnr, char *line)
{ {
char local_addr[64], rem_addr[64]; char local_addr[64], rem_addr[64];
const char *state_str; const char *state_str;
@ -283,7 +283,7 @@ static void udp_do_one(int lnr, const char *line)
} }
} }
static void raw_do_one(int lnr, const char *line) static void raw_do_one(int lnr, char *line)
{ {
char local_addr[64], rem_addr[64]; char local_addr[64], rem_addr[64];
char more[512]; char more[512];
@ -339,31 +339,37 @@ static void raw_do_one(int lnr, const char *line)
} }
} }
static void unix_do_one(int nr, const char *line) static void unix_do_one(int nr, char *line)
{ {
static smallint has_inode = 0;
char path[PATH_MAX], ss_flags[32];
const char *ss_proto, *ss_state, *ss_type;
int num, state, type, inode;
void *d;
unsigned long refcnt, proto, unix_flags; unsigned long refcnt, proto, unix_flags;
unsigned long inode;
int type, state;
int num, path_ofs;
void *d;
const char *ss_proto, *ss_state, *ss_type;
char ss_flags[32];
if (nr == 0) { if (nr == 0)
if (strstr(line, "Inode")) return; /* skip header */
has_inode = 1;
{
char *last = last_char_is(line, '\n');
if (last)
*last = '\0';
}
/* 2.6.15 may report lines like "... @/tmp/fam-user-^@^@^@^@^@^@^@..."
* (those ^@ are NUL bytes). fgets sees them as tons of empty lines. */
if (!line[0])
return;
path_ofs = 0; /* paranoia */
num = sscanf(line, "%p: %lX %lX %lX %X %X %lu %n",
&d, &refcnt, &proto, &unix_flags, &type, &state, &inode, &path_ofs);
if (num < 7) {
bb_error_msg("got bogus unix line '%s'", line);
return; return;
} }
path[0] = '\0';
num = sscanf(line, "%p: %lX %lX %lX %X %X %d %s",
&d, &refcnt, &proto, &unix_flags, &type, &state, &inode, path);
if (num < 6) {
bb_error_msg("warning, got bogus unix line");
return;
}
if (!has_inode)
sprintf(path, "%d", inode);
if ((flags & (NETSTAT_LISTENING|NETSTAT_CONNECTED)) != (NETSTAT_LISTENING|NETSTAT_CONNECTED)) { if ((flags & (NETSTAT_LISTENING|NETSTAT_CONNECTED)) != (NETSTAT_LISTENING|NETSTAT_CONNECTED)) {
if ((state == SS_UNCONNECTED) && (unix_flags & SO_ACCEPTCON)) { if ((state == SS_UNCONNECTED) && (unix_flags & SO_ACCEPTCON)) {
if (!(flags & NETSTAT_LISTENING)) if (!(flags & NETSTAT_LISTENING))
@ -439,13 +445,9 @@ static void unix_do_one(int nr, const char *line)
strcat(ss_flags, "N "); strcat(ss_flags, "N ");
strcat(ss_flags, "]"); strcat(ss_flags, "]");
printf("%-5s %-6ld %-11s %-10s %-13s ", printf("%-5s %-6ld %-11s %-10s %-13s %6lu %s\n",
ss_proto, refcnt, ss_flags, ss_type, ss_state); ss_proto, refcnt, ss_flags, ss_type, ss_state, inode,
if (has_inode) line + path_ofs);
printf("%-6d ", inode);
else
printf("- ");
puts(path);
} }
#define _PATH_PROCNET_UDP "/proc/net/udp" #define _PATH_PROCNET_UDP "/proc/net/udp"
@ -456,10 +458,11 @@ static void unix_do_one(int nr, const char *line)
#define _PATH_PROCNET_RAW6 "/proc/net/raw6" #define _PATH_PROCNET_RAW6 "/proc/net/raw6"
#define _PATH_PROCNET_UNIX "/proc/net/unix" #define _PATH_PROCNET_UNIX "/proc/net/unix"
static void do_info(const char *file, const char *name, void (*proc)(int, const char *)) static void do_info(const char *file, const char *name, void (*proc)(int, char *))
{ {
int lnr = 0; int lnr;
FILE *procinfo; FILE *procinfo;
char *buffer;
procinfo = fopen(file, "r"); procinfo = fopen(file, "r");
if (procinfo == NULL) { if (procinfo == NULL) {
@ -470,13 +473,14 @@ static void do_info(const char *file, const char *name, void (*proc)(int, const
} }
return; return;
} }
lnr = 0;
do { do {
char *buffer = xmalloc_fgets(procinfo); buffer = xmalloc_fgets(procinfo);
if (buffer) { if (buffer) {
(proc)(lnr++, buffer); (proc)(lnr++, buffer);
free(buffer); free(buffer);
} }
} while (!feof(procinfo)); } while (buffer);
fclose(procinfo); fclose(procinfo);
} }