-
-/*
- * utils.c -- various utility routines
+/* utils.c -- various utility routines
*
* This code is Copyright (c) 2006, by the authors of nmh. See the
* COPYRIGHT file in the root directory of the nmh distribution for
#include <h/mh.h>
#include <h/utils.h>
+#include <h/signals.h>
+#include "m_mktemp.h"
+#include "makedir.h"
#include <fcntl.h>
-
-/* sbr/signals.c */
-extern int setup_signal_handlers();
-
-/* sbr/m_mktemp.c */
-extern void remove_registered_files_atexit();
+#include <limits.h>
+#include "read_line.h"
extern char *mhdocdir;
+/* plurals gives the letter ess to indicate a plural noun, or an empty
+ * string as plurals+1 for the singular noun. Used by the PLURALS
+ * macro. */
+const char plurals[] = "s";
+
/*
* We allocate space for messages (msgs array)
* this number of elements at a time.
/* Copy POSIX behaviour, coping with non-POSIX systems. */
if (size == 0) {
- mh_xfree(ptr);
+ free(ptr);
return mh_xmalloc(1); /* Get a unique pointer. */
}
if (!ptr)
return dest;
}
-/* Call free(3), if ptr isn't NULL. */
-void mh_xfree(void *ptr)
-{
- if (ptr)
- free(ptr); /* Some very old platforms can't cope with NULL. */
-}
-
/*
* Return the present working directory, if the current directory does not
* exist, or is too long, make / the pwd.
static char curwd[PATH_MAX];
if (!getcwd (curwd, PATH_MAX)) {
- admonish (NULL, "unable to determine working directory");
+ inform("unable to determine working directory, continuing...");
if (!mypath || !*mypath
|| (strcpy (curwd, mypath), chdir (curwd)) == -1) {
strcpy (curwd, "/");
msgs->msgnums[msgs->size++] = msgnum;
}
-/* Open a form or components file */
-int
-open_form(char **form, char *def)
-{
- int in;
- if (*form) {
- if ((in = open (etcpath (*form), O_RDONLY)) == NOTOK)
- adios (*form, "unable to open form file");
- } else {
- if ((in = open (etcpath (def), O_RDONLY)) == NOTOK)
- adios (def, "unable to open default components file");
- *form = def;
- }
- return in;
-}
-
/*
* Finds first occurrence of str in buf. buf is not a C string but a
void trunccpy(char *dst, const char *src, size_t size)
{
if (!size) {
- advise(NULL, "trunccpy: zero-length destination: \"%.20s\"",
+ inform("trunccpy: zero-length destination: \"%.20s\"",
src ? src : "null");
abort();
}
}
-/* TrimSuffixC deletes c from the end of non-NULL string s if it's
+/* trim_suffix_c deletes c from the end of non-NULL string s if it's
* present, shortening s by 1. Only one instance of c is removed. */
-void TrimSuffixC(char *s, int c)
+void trim_suffix_c(char *s, int c)
{
if (!*s)
return;
}
-/* ToLower runs all of s through tolower(3). */
-void ToLower(char *s)
+/* to_lower runs all of s through tolower(3). */
+void to_lower(char *s)
{
unsigned char *b;
}
-/* ToUpper runs all of s through toupper(3). */
-void ToUpper(char *s)
+/* to_upper runs all of s through toupper(3). */
+void to_upper(char *s)
{
unsigned char *b;
}
/* Check to see if the user is running a different (or older, if
- specified) version of nmh than they had run bfore, and notify them
+ specified) version of nmh than they had run before, and notify them
if so. But only if read_context was set to a value to enable. */
if (allow_version_check && isatty (fileno (stdin)) &&
isatty (fileno (stdout)) && isatty (fileno (stderr))) {
}
if (! setlocale (LC_ALL, locale)) {
- admonish (NULL, "setlocale failed, check your LC_ALL, LC_CTYPE, and "
- "LANG environment variables");
+ inform("setlocale failed, check your LC_ALL, LC_CTYPE, and LANG "
+ "environment variables, continuing...");
}
return status;
context_replace ("Version", "nmh-" VERSION);
}
- return old_version < current_version ? 1 : 0;
+ return old_version < current_version;
}
if (context_version == NULL || strcmp(context_version, "nmh-" VERSION) != 0) {
}
-/* Returns copy of argument str with all characters converted to upper
- case, and trimmed whitespace (see cpytrim()) . */
-char *
-upcase (const char *str) {
- char *up = cpytrim (str);
-
- ToUpper(up);
-
- return up;
-}
-
-
-/*
- * Scan for any 8-bit characters. Return 1 if they exist.
- *
- * Scan up until the given endpoint (but not the actual endpoint itself).
- * If the endpoint is NULL, scan until a '\0' is reached.
- */
-
-int
-contains8bit(const char *start, const char *end)
+/* contains8bit returns true if any byte from start onwards fails
+ * isascii(3), i.e. is outside [0, 0x7f]. If start is NULL it returns
+ * false. Bytes are examined until a NUL byte, or, if end is not NULL,
+ * whilst start is before end. */
+bool contains8bit(const char *start, const char *end)
{
- if (! start)
- return 0;
+ const char *p;
+ char c;
- while (*start != '\0' && (!end || (start < end)))
- if (! isascii((unsigned char) *start++))
- return 1;
+ if (!start)
+ return false;
- return 0;
+ p = start;
+ if (end) {
+ while (p < end && (c = (*p++)))
+ if (!isascii((unsigned char)c))
+ return true;
+ } else {
+ while ((c = (*p++)))
+ if (!isascii((unsigned char)c))
+ return true;
+ }
+
+ return false;
}
char buf[BUFSIZ];
*eightbit = 0;
- lseek (fd, (off_t) 0, SEEK_SET);
+ lseek(fd, 0, SEEK_SET);
while ((state = read (fd, buf, sizeof buf)) > 0) {
if (contains8bit (buf, buf + state)) {
return state == NOTOK ? NOTOK : OK;
}
+
+
+/*
+ * Convert an int to a char string.
+ */
+char *
+m_str(int value) {
+ return m_strn(value, 0);
+}
+
+
+/*
+ * Convert an int to a char string, of limited width if > 0.
+ */
+#define STR(s) #s
+/* SIZE(n) includes NUL. n must just be digits, not an equation. */
+#define SIZE(n) (sizeof STR(n))
+
+char *
+m_strn(int value, unsigned int width) {
+ /* Need to include space for negative sign. But don't use INT_MIN
+ because it could be a macro that would fool SIZE(n). */
+ static char buffer[SIZE(-INT_MAX)];
+ const int num_chars = snprintf(buffer, sizeof buffer, "%d", value);
+
+ return num_chars > 0 && (width == 0 || (unsigned int) num_chars <= width)
+ ? buffer
+ : "?";
+}