aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGeorgi Chorbadzhiyski <gf@unixsol.org>2012-03-16 06:42:08 -0500
committerGeorgi Chorbadzhiyski <gf@unixsol.org>2012-03-16 06:42:08 -0500
commit522d90613ae7dc728a98d3ce3b939b4ad9b30f25 (patch)
tree3aa0a983f34e0d9c427bc012c532c324fbafdf15 /lib
parentc4849f7e354d3c685c44ac2b2a7110238b17122b (diff)
downloadtoybox-522d90613ae7dc728a98d3ce3b939b4ad9b30f25.tar.gz
Implement Apple and Android versions of getline(), getdelim(), and clearenv().
Diffstat (limited to 'lib')
-rw-r--r--lib/portability.c75
-rw-r--r--lib/portability.h8
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