summaryrefslogtreecommitdiffstats
path: root/src/gripes.c
blob: 505f8b83a2b2f908fe5d834aa7c0ce0bf8328983 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>

#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 <string.h>
#include <nl_types.h>
#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 : "<none>");
	    } 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);
}