aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc/posix/wordexp.c
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2012-10-09 12:05:51 +0000
committerCorinna Vinschen <corinna@vinschen.de>2012-10-09 12:05:51 +0000
commit509212aa98c5e38adb67481a079c9a09d3829f44 (patch)
treeb5cdc614c48c429cb7bd1f595795485d51a44a0a /newlib/libc/posix/wordexp.c
parent277e7f0e2e6fc9fb533b301fc0627cfe4fd9d1ae (diff)
downloadnewlib-509212aa98c5e38adb67481a079c9a09d3829f44.zip
newlib-509212aa98c5e38adb67481a079c9a09d3829f44.tar.gz
newlib-509212aa98c5e38adb67481a079c9a09d3829f44.tar.bz2
* libc/posix/wordfree.c (wordfree): The wrong words are freed
when WRDE_DOOFFS is in use. Restructure the code so that the memory needed to be freed is instead kept in an internal linked list... * libc/posix/wordexp2.h: ...as defined here... * libc/posix/wordexp.c (wordexp): ...and build this internal linked list here, avoiding wasteful strdup calls in the process.
Diffstat (limited to 'newlib/libc/posix/wordexp.c')
-rw-r--r--newlib/libc/posix/wordexp.c61
1 files changed, 33 insertions, 28 deletions
diff --git a/newlib/libc/posix/wordexp.c b/newlib/libc/posix/wordexp.c
index b2f63cf..5c58e46 100644
--- a/newlib/libc/posix/wordexp.c
+++ b/newlib/libc/posix/wordexp.c
@@ -18,8 +18,10 @@
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
+#include <sys/queue.h>
#include <wordexp.h>
+#include "wordexp2.h"
#define MAXLINELEN 500
@@ -41,9 +43,9 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
int fd[2];
int fd_err[2];
int err = WRDE_NOSPACE;
- char **wordv;
- char *ewords = NULL;
+ ext_wordv_t *wordv = NULL;
char *eword;
+ struct ewords_entry *entry;
if (pwordexp == NULL)
{
@@ -63,10 +65,14 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
{
offs = pwordexp->we_offs;
- wordv = (char **)realloc(pwordexp->we_wordv, (pwordexp->we_wordc + offs + 1) * sizeof(char *));
+ if (pwordexp->we_wordv)
+ wordv = WE_WORDV_TO_EXT_WORDV(pwordexp->we_wordv);
+ wordv = (ext_wordv_t *)realloc(wordv, sizeof(ext_wordv_t) + (offs + pwordexp->we_wordc) * sizeof(char *));
if (!wordv)
return err;
- pwordexp->we_wordv = wordv;
+ if (!pwordexp->we_wordv)
+ SLIST_INIT(&wordv->list);
+ pwordexp->we_wordv = wordv->we_wordv;
for (i = 0; i < offs; i++)
pwordexp->we_wordv[i] = NULL;
@@ -142,11 +148,14 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
num_words = atoi(tmp);
- wordv = (char **)realloc(pwordexp->we_wordv,
- (pwordexp->we_wordc + num_words + offs + 1) * sizeof(char *));
+ if (pwordexp->we_wordv)
+ wordv = WE_WORDV_TO_EXT_WORDV(pwordexp->we_wordv);
+ wordv = (ext_wordv_t *)realloc(wordv, sizeof(ext_wordv_t) + (offs + pwordexp->we_wordc + num_words) * sizeof(char *));
if (!wordv)
- goto cleanup;
- pwordexp->we_wordv = wordv;
+ return err;
+ if (!pwordexp->we_wordv)
+ SLIST_INIT(&wordv->list);
+ pwordexp->we_wordv = wordv->we_wordv;
/* Get number of bytes required for storage of all num_words words. */
if (!fgets(tmp, MAXLINELEN, f))
@@ -157,36 +166,32 @@ wordexp(const char *words, wordexp_t *pwordexp, int flags)
num_bytes = atoi(tmp);
- /* Get expansion from the shell output. */
- if (!(ewords = (char *)malloc(num_bytes + num_words + 1)))
+ if (!(entry = (struct ewords_entry *)malloc(sizeof(struct ewords_entry) + num_bytes + num_words)))
goto cleanup;
- if (!fread(ewords, 1, num_bytes + num_words, f))
+ SLIST_INSERT_HEAD(&wordv->list, entry, next);
+
+ /* Get expansion from the shell output. */
+ if (!fread(entry->ewords, 1, num_bytes + num_words, f))
goto cleanup;
- ewords[num_bytes + num_words] = 0;
+ entry->ewords[num_bytes + num_words] = 0;
/* Store each entry in pwordexp's we_wordv vector. */
- eword = ewords;
- for(i = 0; i < num_words; i++)
+ eword = entry->ewords;
+ for(i = 0; i < num_words; i++, eword = iter)
{
- if (eword && (iter = strchr(eword, '\n')))
- *iter = '\0';
-
- if (!eword ||
- !(pwordexp->we_wordv[pwordexp->we_wordc + offs + i] = strdup(eword)))
- {
- pwordexp->we_wordv[pwordexp->we_wordc + offs + i] = NULL;
- pwordexp->we_wordc += i;
- goto cleanup;
- }
- eword = iter ? iter + 1 : iter;
+ if (!eword)
+ break;
+ pwordexp->we_wordv[offs + pwordexp->we_wordc + i] = eword;
+ if ((iter = strchr(eword, '\n')))
+ *iter++ = '\0';
}
- pwordexp->we_wordv[pwordexp->we_wordc + offs + i] = NULL;
+ pwordexp->we_wordv[offs + pwordexp->we_wordc + i] = NULL;
pwordexp->we_wordc += num_words;
- err = WRDE_SUCCESS;
+ if (i == num_words)
+ err = WRDE_SUCCESS;
cleanup:
- free(ewords);
if (f)
fclose(f);
else