From 7221c8c22dd527700204eb5cc4d0651af4273f4f Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Mon, 3 Dec 2007 10:45:14 +0000 Subject: [PATCH] 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 --- libbb/lineedit.c | 93 ++++++++++++++++++++------------------------ networking/netstat.c | 72 ++++++++++++++++++---------------- 2 files changed, 81 insertions(+), 84 deletions(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 07db6358d..1397409cc 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -91,7 +91,6 @@ struct statics { const char *cmdedit_prompt; #if ENABLE_FEATURE_EDITING_FANCY_PROMPT - char *hostname_buf; int num_ok_lines; /* = 1; */ #endif @@ -136,7 +135,6 @@ static struct statics *const ptr_to_statics __attribute__ ((section (".data"))); #define command_len (S.command_len ) #define command_ps (S.command_ps ) #define cmdedit_prompt (S.cmdedit_prompt ) -#define hostname_buf (S.hostname_buf ) #define num_ok_lines (S.num_ok_lines ) #define user_buf (S.user_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) { #if ENABLE_FEATURE_EDITING_FANCY_PROMPT - free(hostname_buf); /* This one is allocated only if FANCY_PROMPT is on * (otherwise it points to verbatim prompt (NOT malloced) */ 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/..." */ char *sav_ud = ud - 1; char *home = NULL; - char *temp; if (*ud == '/') { /* "~/..." */ home = home_pwd_buf; } else { /* "~user/..." */ + char *temp; temp = strchr(ud, '/'); - *temp = 0; /* ~user\0 */ + *temp = '\0'; /* ~user\0 */ entry = getpwnam(ud); *temp = '/'; /* restore ~user/... */ ud = temp; @@ -1163,21 +1160,23 @@ static void parse_and_put_prompt(const char *prmt_ptr) size_t cur_prmt_len = 0; char flg_not_length = '['; char *prmt_mem_ptr = xzalloc(1); - char *pwd_buf = xrealloc_getcwd_or_warn(NULL); - char buf2[PATH_MAX + 1]; - char buf[2]; + char *cwd_buf = xrealloc_getcwd_or_warn(NULL); + char cbuf[2]; char c; char *pbuf; cmdedit_prmt_len = 0; - if (!pwd_buf) { - pwd_buf = (char *)bb_msg_unknown; + if (!cwd_buf) { + cwd_buf = (char *)bb_msg_unknown; } + cbuf[1] = '\0'; /* never changes */ + while (*prmt_ptr) { - pbuf = buf; - pbuf[1] = 0; + char *free_me = NULL; + + pbuf = cbuf; c = *prmt_ptr++; if (c == '\\') { const char *cp = prmt_ptr; @@ -1188,6 +1187,7 @@ static void parse_and_put_prompt(const char *prmt_ptr) if (*cp == '\0') break; c = *prmt_ptr++; + switch (c) { #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR case 'u': @@ -1195,87 +1195,81 @@ static void parse_and_put_prompt(const char *prmt_ptr) break; #endif case 'h': - pbuf = hostname_buf; - if (!pbuf) { - pbuf = xzalloc(256); - if (gethostname(pbuf, 255) < 0) { - strcpy(pbuf, "?"); - } else { - char *s = strchr(pbuf, '.'); - if (s) - *s = '\0'; - } - hostname_buf = pbuf; + pbuf = free_me = xzalloc(256); + if (gethostname(pbuf, 255) < 0) { + pbuf[0] = '?'; + pbuf[1] = '\0'; } + *strchrnul(pbuf, '.') = '\0'; break; case '$': c = (geteuid() == 0 ? '#' : '$'); break; #if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR case 'w': - pbuf = pwd_buf; + /* /home/user[/something] -> ~[/something] */ + pbuf = cwd_buf; l = strlen(home_pwd_buf); if (l != 0 - && strncmp(home_pwd_buf, pbuf, l) == 0 - && (pbuf[l]=='/' || pbuf[l]=='\0') - && strlen(pwd_buf+l) < PATH_MAX + && strncmp(home_pwd_buf, cwd_buf, l) == 0 + && (cwd_buf[l]=='/' || cwd_buf[l]=='\0') + && strlen(cwd_buf + l) < PATH_MAX ) { - pbuf = buf2; - *pbuf = '~'; - strcpy(pbuf+1, pwd_buf+l); + pbuf = free_me = xasprintf("~%s", cwd_buf + l); } break; #endif case 'W': - pbuf = pwd_buf; + pbuf = cwd_buf; cp = strrchr(pbuf, '/'); if (cp != NULL && cp != pbuf) pbuf += (cp-pbuf) + 1; break; case '!': - pbuf = buf2; - snprintf(buf2, sizeof(buf2), "%d", num_ok_lines); + pbuf = free_me = xasprintf("%d", num_ok_lines); break; case 'e': case 'E': /* \e \E = \033 */ c = '\033'; break; - case 'x': case 'X': + case 'x': case 'X': { + char buf2[4]; for (l = 0; l < 3;) { - int h; + unsigned h; buf2[l++] = *prmt_ptr; - buf2[l] = 0; - h = strtol(buf2, &pbuf, 16); + buf2[l] = '\0'; + h = strtoul(buf2, &pbuf, 16); if (h > UCHAR_MAX || (pbuf - buf2) < l) { - l--; + buf2[--l] = '\0'; break; } prmt_ptr++; } - buf2[l] = 0; - c = (char)strtol(buf2, NULL, 16); + c = (char)strtoul(buf2, NULL, 16); if (c == 0) c = '?'; - pbuf = buf; + pbuf = cbuf; break; + } case '[': case ']': if (c == flg_not_length) { flg_not_length = (flg_not_length == '[' ? ']' : '['); continue; } break; - } - } - } - if (pbuf == buf) - *pbuf = c; + } /* switch */ + } /* if */ + } /* if */ + cbuf[0] = c; cur_prmt_len = strlen(pbuf); prmt_len += cur_prmt_len; if (flg_not_length != ']') cmdedit_prmt_len += cur_prmt_len; prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_len+1), pbuf); - } - if (pwd_buf != (char *)bb_msg_unknown) - free(pwd_buf); + free(free_me); + } /* while */ + + if (cwd_buf != (char *)bb_msg_unknown) + free(cwd_buf); cmdedit_prompt = prmt_mem_ptr; put_prompt(); } @@ -1397,7 +1391,6 @@ int read_line_input(const char *prompt, char *command, int maxsize, line_input_t if (entry) { user_buf = xstrdup(entry->pw_name); home_pwd_buf = xstrdup(entry->pw_dir); - /* They are not freed on exit (too small to bother) */ } } #endif diff --git a/networking/netstat.c b/networking/netstat.c index 11f141947..d86c2ff5e 100644 --- a/networking/netstat.c +++ b/networking/netstat.c @@ -148,7 +148,7 @@ static char *ip_port_str(struct sockaddr *addr, int port, const char *proto, int 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 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]; 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 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 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 (strstr(line, "Inode")) - has_inode = 1; + if (nr == 0) + return; /* skip header */ + + { + 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; } - 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 ((state == SS_UNCONNECTED) && (unix_flags & SO_ACCEPTCON)) { 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, "]"); - printf("%-5s %-6ld %-11s %-10s %-13s ", - ss_proto, refcnt, ss_flags, ss_type, ss_state); - if (has_inode) - printf("%-6d ", inode); - else - printf("- "); - puts(path); + printf("%-5s %-6ld %-11s %-10s %-13s %6lu %s\n", + ss_proto, refcnt, ss_flags, ss_type, ss_state, inode, + line + path_ofs); } #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_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; + char *buffer; procinfo = fopen(file, "r"); if (procinfo == NULL) { @@ -470,13 +473,14 @@ static void do_info(const char *file, const char *name, void (*proc)(int, const } return; } + lnr = 0; do { - char *buffer = xmalloc_fgets(procinfo); + buffer = xmalloc_fgets(procinfo); if (buffer) { (proc)(lnr++, buffer); free(buffer); } - } while (!feof(procinfo)); + } while (buffer); fclose(procinfo); }