From 5280f9a0cd1f9ba200422ebba65d1e0133410995 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Sat, 13 Sep 2014 09:43:21 -0700 Subject: Initial. --- src/gripes.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 src/gripes.c (limited to 'src/gripes.c') diff --git a/src/gripes.c b/src/gripes.c new file mode 100644 index 0000000..505f8b8 --- /dev/null +++ b/src/gripes.c @@ -0,0 +1,139 @@ +#include +#include +#include + +#include "gripes.h" +#include "man.h" /* for progname */ + +extern char *msg[]; + +static char *mantexts = "man"; /* e.g. /usr/lib/locale/%L/man.cat */ + +#ifdef NONLS + +static char * +getmsg (int n) { + char *s; + + if (0 < n && n <= MAXMSG) + s = msg[n]; + else { + fprintf (stderr, "man: internal error - cannot find message %d\n", n); + exit (1); + } + return s; +} + +#else /* NONLS */ + +#include +#include +#include "../catopen/catopen.c" + +nl_catd catfd = (nl_catd) -1; +int cat_is_open = 0; + +static void +catinit (void) { + if (!cat_is_open) { +#ifdef NL_CAT_LOCALE + catfd = my_catopen(mantexts,NL_CAT_LOCALE); +#else + catfd = my_catopen(mantexts,0); +#endif + if (catfd == (nl_catd) -1) { + /* + * Only complain if LANG exists, and LANG != "en" + * (or when debugging). Also accept en_ZA etc. + * No messages for C locale. + */ + char *s, *lg; + s = getenv("NLSPATH"); + lg = getenv("LANG"); + if (!lg) + lg = getenv("LC_MESSAGES"); + if (!lg) + lg = getenv("LC_ALL"); + if (lg && strncmp(lg, "en", 2) && strcmp(lg, "C") && strcmp(lg, "POSIX")) { + fprintf(stderr, + "Cannot open the message catalog \"%s\" for locale \"%s\"\n" + "(NLSPATH=\"%s\")\n\n", + mantexts, lg, s ? s : ""); + } else if (debug) { + fprintf(stderr, +"Looked whether there exists a message catalog %s, but there is none\n" +"(and for English messages none is needed)\n\n", + mantexts); + } + } + } + cat_is_open = 1; +} + +/* + * This routine is unnecessary, but people ask for such things. + * + * Maybe man is suid or sgid to some user that owns the cat directories. + * Maybe NLSPATH can be manipulated by the user - even though + * modern glibc avoids using environment variables when the + * program is suid or sgid. + * So, maybe the string s that we are returning was user invented + * and we have to avoid %n and the like. + * + * As a random hack, only allow %s,%d,%o, and only two %-signs. + */ +static int +is_suspect (char *s) { + int ct = 0; + + while (*s) { + if (*s++ == '%') { + ct++; + if (*s != 's' && *s != 'd' && *s != 'o') + return 1; + } + } + return (ct > 2); +} + +static char * +getmsg (int n) { + char *s = ""; + + catinit (); + if (catfd != (nl_catd) -1) { + s = catgets(catfd, 1, n, ""); + if (*s && is_suspect(s)) + s = ""; + } + if (*s == 0 && 0 < n && n <= MAXMSG) + s = msg[n]; + if (*s == 0) { + fprintf(stderr, + "man: internal error - cannot find message %d\n", n); + exit (1); + } + return s; +} + +#endif /* NONLS */ + +void +gripe (int n, ...) { + va_list p; + + va_start(p, n); + vfprintf (stderr, getmsg(n), p); + va_end(p); + fflush (stderr); +} + +void +fatal (int n, ...) { + va_list p; + fprintf (stderr, "%s: ", progname); + va_start(p, n); + vfprintf (stderr, getmsg(n), p); + va_end(p); + exit (1); +} -- cgit v1.2.3