summaryrefslogtreecommitdiff
path: root/libc/string
diff options
context:
space:
mode:
Diffstat (limited to 'libc/string')
-rw-r--r--libc/string/strerror.c61
-rw-r--r--libc/string/strsignal.c75
2 files changed, 113 insertions, 23 deletions
diff --git a/libc/string/strerror.c b/libc/string/strerror.c
index 91565965f..3aa8b57e2 100644
--- a/libc/string/strerror.c
+++ b/libc/string/strerror.c
@@ -16,31 +16,70 @@ License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
+/*
+ * Manuel Novoa III Dec 2000
+ *
+ * Converted to use my new (un)signed long (long) to string routines, which
+ * are smaller than the previous functions and don't require static buffers.
+ * Removed dependence on strcat in the process.
+ *
+ * Also appended a test routine ( -DSTRERROR_TEST ) to allow a quick check
+ * on the buffer length when the sys_errorlist is modified.
+ */
+
#include <stdio.h>
#include <string.h>
#include <errno.h>
+#include <limits.h>
+
+#if (INT_MAX >> 31)
+/* We're set up for 32 bit ints */
+#error need to check size allocation for static buffer 'retbuf'
+#endif
-extern char *itoa(int);
+extern char *__ltostr(char *buf, long uval, int base, int uppercase);
+
+static char retbuf[33]; /* 33 is sufficient for 32 bit ints */
+static const char unknown_error[] = "Unknown Error: errno"; /* = */
/* Return a string descibing the errno code in ERRNUM.
The storage is good only until the next call to strerror.
Writing to the storage causes undefined behavior. */
char *strerror(int err)
{
- static char retbuf[80];
+ char *pos;
- if (sys_nerr) {
- if (err < 0 || err >= sys_nerr)
- goto unknown;
+ if ((err >= 0) && (err < sys_nerr)) {
strcpy(retbuf, sys_errlist[err]);
return retbuf;
}
- if (err <= 0)
- goto unknown;
+ /* unknown error */
+ pos = __ltostr(retbuf + sizeof(retbuf) + 1, err, 10, 0)
+ - sizeof(unknown_error); /* leave space for the '=' */
+ strcpy(pos, unknown_error);
+ *(pos + sizeof(unknown_error) - 1) = '=';
+ return pos;
+}
+
+#if STRERROR_TEST
+/* quick way to check for sufficient buffer length */
+#include <stdio.h>
+#include <stdlib.h>
+int main(void)
+{
+ int max = 0;
+ int i, j;
+ char *p;
+ for ( i=0 ; i < sys_nerr ; i++ ) {
+ j = strlen(sys_errlist[i])+1;
+ if (j > max) max = j;
+ }
+ printf("max len = %i\n", j);
- unknown:
- strcpy(retbuf, "Unknown Error: errno=");
- strcat(retbuf, (char *) itoa(err));
- return retbuf;
+ p = strerror(INT_MIN);
+ printf("<%s> %d\n", p, strlen(p)+1);
+ printf("current buffer length is %d\n", sizeof(retbuf));
+ return EXIT_SUCCESS;
}
+#endif
diff --git a/libc/string/strsignal.c b/libc/string/strsignal.c
index 4cadb144a..1a0a6ca47 100644
--- a/libc/string/strsignal.c
+++ b/libc/string/strsignal.c
@@ -4,11 +4,25 @@
* GNU Library General Public License.
*/
+/*
+ * Manuel Novoa III Dec 2000
+ *
+ * Converted to use my new (un)signed long (long) to string routines, which
+ * are smaller than the previous functions and don't require static buffers.
+ * Removed dependence on strcat in the process.
+ *
+ * Also fixed a bug in the signal name lookup code. While the table is
+ * declared with dimension > 60, there are currently on 32 signals listed.
+ *
+ * Also appended a test routine ( -DSTRSIGNAL_TEST ) to allow a quick check
+ * on the buffer length when the sys_errorlist is modified.
+ */
+
#include <string.h>
#include <malloc.h>
#include <signal.h>
-extern char *itoa(int i);
+extern char *__ltostr(char *buf, long uval, int base, int uppercase);
const char *const sys_siglist[] = {
"Unknown signal",
@@ -46,26 +60,63 @@ const char *const sys_siglist[] = {
NULL
};
+#include <limits.h>
+
+#if (INT_MAX >> 31)
+/* We're set up for 32 bit ints */
+#error need to check size allocation for static buffer 'retbuf'
+#endif
+
/********************** Function strsignal ************************************/
char *strsignal(int sig)
{
- static char retbuf[80];
+ static char retbuf[28]; /* 28 is sufficient for 32 bit ints */
+ static const char unknown_signal[] = "Unknown Signal:";
+ char *pos;
- if (sys_siglist) {
- if (sig < 0 || sig >= _NSIG)
- goto unknown;
+ /* if ((sig >= 0) && (sig < _NSIG)) { */
+ if ((sig >= 0) && (sig < 32)) { /* WARNING!!! NOT ALL _NSIG DEFINED!!! */
strcpy(retbuf, sys_siglist[sig]);
return retbuf;
}
- if (sig <= 0)
- goto unknown;
-
- unknown:
- strcpy(retbuf, "Unknown Signal: ");
- strcat(retbuf, (char *) itoa(sig));
- return retbuf;
+ pos = __ltostr(retbuf + sizeof(unknown_signal) + 1, sig, 10, 0)
+ - sizeof(unknown_signal);
+ strcpy(pos, unknown_signal);
+ *(pos + sizeof(unknown_signal) - 1) = ' ';
+ return pos;
}
/********************** THE END ********************************************/
+
+#if STRSIGNAL_TEST
+/* quick way to check for sufficient buffer length */
+#include <stdio.h>
+#include <stdlib.h>
+int main(void)
+{
+ int max = 0;
+ int i, j;
+ const char *p;
+
+ printf("_NSIG = %d from headers\n", _NSIG);
+ for ( i=0 ; i < _NSIG ; i++ ) {
+ p = sys_siglist[i];
+ if (!p) {
+ printf("Warning! I only count %d signals!\n", i);
+ break;
+ }
+ j = strlen(sys_siglist[i])+1;
+ if (j > max) max = j;
+ }
+ printf("max len = %i\n", j);
+
+ p = strsignal(INT_MIN);
+ printf("<%s> %d\n", p, strlen(p)+1);
+
+ p = strsignal(i-1);
+ printf("last signal %d is %s\n", i-1, p);
+ return EXIT_SUCCESS;
+}
+#endif