diff options
author | Georgi Chorbadzhiyski <gf@unixsol.org> | 2012-03-16 06:42:08 -0500 |
---|---|---|
committer | Georgi Chorbadzhiyski <gf@unixsol.org> | 2012-03-16 06:42:08 -0500 |
commit | 522d90613ae7dc728a98d3ce3b939b4ad9b30f25 (patch) | |
tree | 3aa0a983f34e0d9c427bc012c532c324fbafdf15 /lib | |
parent | c4849f7e354d3c685c44ac2b2a7110238b17122b (diff) | |
download | toybox-522d90613ae7dc728a98d3ce3b939b4ad9b30f25.tar.gz |
Implement Apple and Android versions of getline(), getdelim(), and clearenv().
Diffstat (limited to 'lib')
-rw-r--r-- | lib/portability.c | 75 | ||||
-rw-r--r-- | lib/portability.h | 8 |
2 files changed, 82 insertions, 1 deletions
diff --git a/lib/portability.c b/lib/portability.c new file mode 100644 index 00000000..b1c448c8 --- /dev/null +++ b/lib/portability.c @@ -0,0 +1,75 @@ +/* vi: set sw=4 ts=4 :*/ +/* portability.c - code to workaround the deficiencies of various platforms. + * + * Copyright 2012 Rob Landley <rob@landley.net> + * Copyright 2012 Georgi Chorbadzhiyski <gf@unixsol.org> + */ + +#include "toys.h" + +#if defined(__APPLE__) || defined(__ANDROID__) +ssize_t getdelim(char **linep, size_t *np, int delim, FILE *stream) +{ + int ch; + size_t new_len; + ssize_t i = 0; + char *line, *new_line; + + // Invalid input + if (!linep || !np) { + errno = EINVAL; + return -1; + } + + if (*linep == NULL || *np == 0) { + *np = 1024; + *linep = calloc(1, *np); + if (*linep == NULL) + return -1; + } + line = *linep; + + while ((ch = getc(stream)) != EOF) { + if (i > *np) { + // Need more space + new_len = *np + 1024; + new_line = realloc(*linep, new_len); + if (!new_line) + return -1; + *np = new_len; + *linep = new_line; + } + + line[i] = ch; + if (ch == delim) + break; + i += 1; + } + + if (i > *np) { + // Need more space + new_len = i + 2; + new_line = realloc(*linep, new_len); + if (!new_line) + return -1; + *np = new_len; + *linep = new_line; + } + line[i + 1] = '\0'; + + return i > 0 ? i : -1; +} + +ssize_t getline(char **linep, size_t *np, FILE *stream) { + return getdelim(linep, np, '\n', stream); +} +#endif + +#if defined(__APPLE__) +extern char **environ; + +int clearenv(void) { + *environ = NULL; + return 0; +} +#endif diff --git a/lib/portability.h b/lib/portability.h index 0887d873..832dd123 100644 --- a/lib/portability.h +++ b/lib/portability.h @@ -1,5 +1,5 @@ // The tendency of gcc to produce stupid warnings continues with -// warn_unsed_result, which warns about things like ignoring the return code +// warn_unused_result, which warns about things like ignoring the return code // of nice(2) (which is completely useless since -1 is a legitimate return // value on success and even the man page tells you to use errno instead). @@ -33,6 +33,7 @@ #define IS_BIG_ENDIAN 0 #endif +int clearenv(void); #else #ifdef __BIG_ENDIAN__ @@ -72,3 +73,8 @@ #else #define GCC_BUG #endif + +#if defined(__APPLE__) || defined(__ANDROID__) +ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream); +ssize_t getline(char **lineptr, size_t *n, FILE *stream); +#endif |