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
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 07db635..1397409 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -91,7 +91,6 @@
const char *cmdedit_prompt;
#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
- char *hostname_buf;
int num_ok_lines; /* = 1; */
#endif
@@ -136,7 +135,6 @@
#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 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 @@
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 @@
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 @@
if (*cp == '\0')
break;
c = *prmt_ptr++;
+
switch (c) {
#if ENABLE_FEATURE_GETUSERNAME_AND_HOMEDIR
case 'u':
@@ -1195,87 +1195,81 @@
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 @@
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 11f1419..d86c2ff 100644
--- a/networking/netstat.c
+++ b/networking/netstat.c
@@ -148,7 +148,7 @@
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 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 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 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 @@
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 @@
#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 @@
}
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);
}