1#include <stdio.h>
2#include <stdarg.h>
3#include <stdlib.h>
4
5#include "gripes.h"
6#include "man.h"		/* for progname */
7
8extern char *msg[];
9
10static char *mantexts = "man";		/* e.g. /usr/lib/locale/%L/man.cat */
11
12#ifdef NONLS
13
14static char *
15getmsg (int n) {
16    char *s;
17
18    if (0 < n && n <= MAXMSG)
19      s = msg[n];
20    else {
21	fprintf (stderr, "man: internal error - cannot find message %d\n", n);
22	exit (1);
23    }
24    return s;
25}
26
27#else /* NONLS */
28
29#include <string.h>
30#include <nl_types.h>
31#include "../catopen/catopen.c"
32
33nl_catd catfd = (nl_catd) -1;
34int cat_is_open = 0;
35
36static void
37catinit (void) {
38    if (!cat_is_open) {
39#ifdef NL_CAT_LOCALE
40	catfd = my_catopen(mantexts,NL_CAT_LOCALE);
41#else
42	catfd = my_catopen(mantexts,0);
43#endif
44	if (catfd == (nl_catd) -1) {
45	    /*
46	     * Only complain if LANG exists, and LANG != "en"
47	     * (or when debugging). Also accept en_ZA etc.
48	     * No messages for C locale.
49	     */
50	    if (debug) {
51		fprintf(stderr,
52"Looked whether there exists a message catalog %s, but there is none\n"
53"(and for English messages none is needed)\n\n",
54			mantexts);
55            }
56	}
57    }
58    cat_is_open = 1;
59}
60
61/*
62 * This routine is unnecessary, but people ask for such things.
63 *
64 * Maybe man is suid or sgid to some user that owns the cat directories.
65 * Maybe NLSPATH can be manipulated by the user - even though
66 * modern glibc avoids using environment variables when the
67 * program is suid or sgid.
68 * So, maybe the string s that we are returning was user invented
69 * and we have to avoid %n and the like.
70 *
71 * As a random hack, only allow %s,%d,%o, and only two %-signs.
72 */
73static int
74is_suspect (char *s) {
75	int ct = 0;
76
77	while (*s) {
78		if (*s++ == '%') {
79			ct++;
80			if (*s != 's' && *s != 'd' && *s != 'o')
81				return 1;
82		}
83	}
84	return (ct > 2);
85}
86
87static char *
88getmsg (int n) {
89	char *s = "";
90
91	catinit ();
92	if (catfd != (nl_catd) -1) {
93		s = catgets(catfd, 1, n, "");
94		if (*s && is_suspect(s))
95			s = "";
96	}
97	if (*s == 0 && 0 < n && n <= MAXMSG)
98		s = msg[n];
99	if (*s == 0) {
100		fprintf(stderr,
101			"man: internal error - cannot find message %d\n", n);
102		exit (1);
103        }
104	return s;
105}
106
107#endif /* NONLS */
108
109void
110gripe (int n, ...) {
111    va_list p;
112
113    va_start(p, n);
114    vfprintf (stderr, getmsg(n), p);
115    va_end(p);
116    fflush (stderr);
117}
118
119void
120fatal (int n, ...) {
121    va_list p;
122    fprintf (stderr, "%s: ", progname);
123    va_start(p, n);
124    vfprintf (stderr, getmsg(n), p);
125    va_end(p);
126    exit (1);
127}
128