ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/src/numeric.c
Revision: 34
Committed: Sun Oct 2 21:05:51 2005 UTC (18 years, 6 months ago) by lusky
Content type: text/x-csrc
File size: 5932 byte(s)
Log Message:
create 7.2 branch, we can move/rename it as needed.


File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * numeric.c: Numeric handling functions.
4 *
5 * Copyright (C) 2002 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26
27 #include "numeric.h"
28 #include "irc_string.h"
29 #include "common.h" /* NULL cripes */
30 #include "memory.h"
31 #include "s_log.h"
32 #include "fileio.h"
33 #include "send.h"
34 #include "client.h"
35 #include "messages.tab"
36
37 static char used_locale[LOCALE_LENGTH] = "standard";
38
39 /*
40 * form_str
41 *
42 * inputs - numeric
43 * output - corresponding string
44 * side effects - NONE
45 */
46 const char* form_str(int numeric)
47 {
48 assert(-1 < numeric);
49 assert(numeric < ERR_LAST_ERR_MSG);
50
51 if (numeric > ERR_LAST_ERR_MSG)
52 numeric = ERR_LAST_ERR_MSG;
53 if (numeric < 0)
54 numeric = ERR_LAST_ERR_MSG;
55
56 assert(replies[numeric].standard != NULL);
57
58 return (replies[numeric].translated != NULL ? replies[numeric].translated :
59 replies[numeric].standard);
60 }
61
62 /* Attempts to change a numeric with index "reply" to "new_reply".
63 * Returns 1 if ok, 0 otherwise.
64 */
65 static int
66 change_reply(const char *locale, int linecnt, int reply, char *new_reply)
67 {
68 int found;
69 char *new = new_reply;
70 const char *old = replies[reply].standard;
71
72 for (; *new; new++)
73 {
74 if (*new == '%')
75 {
76 if (!*++new) break;
77 if (*new != '%')
78 {
79 /* We've just found a format symbol. Check if it is the next format
80 * symbol in the original reply.
81 */
82 for (; *new >= '0' && *new <= '9'; new++); /* skip size prefix */
83 found = 0;
84 for (; *old; old++)
85 {
86 if (*old == '%')
87 {
88 if (!*++old) break; /* shouldn't happen */
89 if (*old != '%')
90 {
91 for (; *old >= '0' && *old <= '9'; old++); /* skip size prefix */
92 if (*new != *old++)
93 {
94 ilog(L_ERROR, "Incompatible format symbols (%s.lang, %d)",
95 locale, linecnt);
96 return 0;
97 }
98 found = 1;
99 break;
100 }
101 }
102 }
103 if (!found)
104 {
105 ilog(L_ERROR, "Too many format symbols (%s.lang, %d)", locale, linecnt);
106 return(0);
107 }
108 }
109 }
110 }
111
112 MyFree(replies[reply].translated);
113 DupString(replies[reply].translated, new_reply);
114 return(1);
115 }
116
117 /* Loads a language file. Errors are logged into the log file. */
118 void
119 set_locale(const char *locale)
120 {
121 int i, res = 1, linecnt = 0;
122 char buffer[IRCD_BUFSIZE + 1];
123 char *ident, *reply;
124 FBFILE *f;
125
126 /* Restore standard replies */
127 for (i = 0; i <= ERR_LAST_ERR_MSG; i++) /* 0 isn't a magic number! ;> */
128 {
129 if (replies[i].translated != NULL)
130 {
131 MyFree(replies[i].translated);
132 replies[i].translated = NULL;
133 }
134 }
135
136 if (strchr(locale, '/') != NULL)
137 {
138 strlcpy(used_locale, "standard", sizeof(used_locale)); /* XXX paranoid */
139 return;
140 }
141
142 /* yes, I know - the slash isn't necessary. But I have to be sure
143 * that it'll work even if some lame admin won't put "/" at the end
144 * of MSGPATH.
145 */
146 snprintf(buffer, sizeof(buffer), "%s/%s.lang", MSGPATH, locale);
147 if ((f = fbopen(buffer, "r")) == NULL)
148 {
149 strlcpy(used_locale, "standard", sizeof(used_locale)); /* XXX */
150 return;
151 }
152
153 /* Process the language file */
154 while (fbgets(buffer, sizeof(buffer), f))
155 {
156 ++linecnt;
157 if (buffer[0] == ';')
158 continue; /* that's a comment */
159
160 if ((ident = strpbrk(buffer, "\r\n")) != NULL)
161 *ident = '\0';
162
163 /* skip spaces if there are any */
164 for (ident = buffer; *ident == ' ' || *ident == '\t'; ident++)/* null */;
165 if (*ident == '\0')
166 continue; /* empty line */
167
168 /* skip after the reply identificator */
169 for (reply = ident; *reply != ' ' && *reply != '\t' && *reply != ':';
170 reply++)
171 if (*reply == '\0') goto error;
172
173 if (*reply == ' ' || *reply == '\t')
174 {
175 for (*reply++ = '\0'; *reply == ' ' || *reply == '\t'; reply++);
176 if (*reply != ':')
177 {
178 error:
179 ilog(L_ERROR, "Invalid line in language file (%s.lang, %d)",
180 locale, linecnt);
181 res = 0;
182 continue;
183 }
184 }
185 else
186 *reply++ = '\0';
187 if (*ident == '\0')
188 goto error;
189
190 /* skip to the beginning of reply */
191 while (*reply == ' ' || *reply == '\t') reply++;
192 if (*reply == '\0')
193 goto error;
194
195 for (i = 0; i <= ERR_LAST_ERR_MSG; i++)
196 {
197 if (replies[i].name != NULL)
198 {
199 if (irccmp(replies[i].name, ident) == 0)
200 {
201 if (!change_reply(locale, linecnt, i, reply)) res = 0;
202 i = -1;
203 break;
204 }
205 }
206 }
207 if (i != -1)
208 {
209 ilog(L_ERROR,
210 "Unknown numeric %s (%s.lang, %d)", ident, locale, linecnt);
211 res = 0;
212 }
213 }
214 fbclose(f);
215
216 strlcpy(used_locale, locale, sizeof(used_locale));
217 if (!res)
218 sendto_realops_flags(UMODE_ALL, L_ADMIN, "Language file [%s] contains "
219 "errors, check server log file for more details",
220 used_locale);
221 }
222
223 /* Returns the name of current locale. */
224 const char *
225 get_locale(void)
226 {
227 return used_locale;
228 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision