Author: Kev <klmitch@mit.edu>
[ircu2.10.12-pk.git] / ircd / ircd_features.c
1 /*
2  * IRC - Internet Relay Chat, ircd/features.c
3  * Copyright (C) 2000 Kevin L. Mitchell <klmitch@mit.edu>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 1, or (at your option)
8  * any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  * $Id$
20  */
21 #include "features.h"
22 #include "client.h"
23 #include "hash.h"
24 #include "ircd.h"
25 #include "ircd_alloc.h"
26 #include "ircd_log.h"
27 #include "ircd_reply.h"
28 #include "ircd_string.h"
29 #include "match.h"
30 #include "msg.h"
31 #include "numeric.h"
32 #include "numnicks.h"
33 #include "s_bsd.h"
34 #include "s_debug.h"
35 #include "s_misc.h"
36 #include "send.h"
37 #include "struct.h"
38 #include "support.h"
39 #include "sys.h"    /* FALSE bleah */
40
41 #include <assert.h>
42 #include <string.h>
43
44 static struct LogTypes {
45   char *type;
46   int (*set)(const char *, const char *);
47   char *(*get)(const char *);
48 } logTypes[] = {
49   { "FILE", log_set_file, log_get_file },
50   { "FACILITY", log_set_facility, log_get_facility },
51   { "SNOMASK", log_set_snomask, log_get_snomask },
52   { "LEVEL", log_set_level, log_get_level },
53   { 0, 0, 0 }
54 };
55
56 static struct LogTypes *
57 feature_log_desc(struct Client* from, const char *type)
58 {
59   int i;
60
61   assert(0 != type);
62
63   for (i = 0; logTypes[i].type; i++) /* find appropriate descriptor */
64     if (!ircd_strcmp(type, logTypes[i].type))
65       return &logTypes[i];
66
67   Debug((DEBUG_ERROR, "Unknown log feature type \"%s\"", type));
68   if (from)
69     send_reply(from, ERR_BADLOGTYPE, type);
70   else
71     log_write(LS_CONFIG, L_ERROR, 0, "Unknown log feature type \"%s\"", type);
72
73   return 0; /* not found */
74 }
75
76 static void
77 feature_log_set(struct Client* from, const char* const* fields, int count)
78 {
79   struct LogTypes *desc;
80   char *subsys;
81
82   if (count < 2) { /* set default facility */
83     if (log_set_default(count < 1 ? 0 : fields[0])) {
84       assert(count >= 1); /* should always accept default */
85
86       if (from)
87         send_reply(from, ERR_BADLOGVALUE, fields[0]);
88       else
89         log_write(LS_CONFIG, L_ERROR, 0,
90                   "Bad value \"%s\" for default facility", fields[0]);
91     }
92   } else if (!(subsys = log_canon(fields[0]))) { /* no such subsystem */
93     if (from)
94       send_reply(from, ERR_BADLOGSYS, fields[0]);
95     else
96       log_write(LS_CONFIG, L_ERROR, 0,
97                 "No such logging subsystem \"%s\"", fields[0]);
98   } else if ((desc = feature_log_desc(from, fields[1]))) { /* set value */
99     if ((*desc->set)(fields[0], count < 3 ? 0 : fields[2])) {
100       assert(count >= 3); /* should always accept default */
101
102       if (from)
103         send_reply(from, ERR_BADLOGVALUE, fields[2]);
104       else
105         log_write(LS_CONFIG, L_ERROR, 0,
106                   "Bad value \"%s\" for log type %s (subsystem %s)",
107                   fields[2], desc->type, subsys);
108     }
109   }
110 }
111
112 static void
113 feature_log_reset(struct Client* from, const char* const* fields, int count)
114 {
115   struct LogTypes *desc;
116   char *subsys;
117
118   assert(0 != from);
119
120   if (count < 1) /* reset default facility */
121     log_set_default(0);
122   else if (count < 2)
123     need_more_params(from, "RESET");
124   else if (!(subsys = log_canon(fields[0]))) /* no such subsystem */
125     send_reply(from, ERR_BADLOGSYS, fields[0]);
126   else if ((desc = feature_log_desc(from, fields[1]))) /* reset value */
127     (*desc->set)(fields[0], 0);
128 }
129
130 static void
131 feature_log_get(struct Client* from, const char* const* fields, int count)
132 {
133   struct LogTypes *desc;
134   char *value, *subsys;
135
136   assert(0 != from);
137
138   if (count < 1) /* return default facility */
139     send_reply(from, SND_EXPLICIT | RPL_FEATURE, ":Log facility: %s",
140                log_get_default());
141   else if (count < 2)
142     need_more_params(from, "GET");
143   else if (!(subsys = log_canon(fields[0]))) { /* no such subsystem */
144     send_reply(from, ERR_BADLOGSYS, fields[0]);
145   } else if ((desc = feature_log_desc(from, fields[1]))) {
146     if ((value = (*desc->get)(fields[0]))) /* send along value */
147       send_reply(from, SND_EXPLICIT | RPL_FEATURE,
148                  ":Log %s for subsystem %s: %s", desc->type, subsys,
149                  (*desc->get)(subsys));
150     else
151       send_reply(from, SND_EXPLICIT | RPL_FEATURE,
152                  ":No log %s is set for subsystem %s", desc->type, subsys);
153   }
154 }
155
156 typedef void (*feature_call)(struct Client*, const char* const*, int);
157
158 static struct FeatureDesc {
159   char *type;
160   feature_call set;   /* set feature values */
161   feature_call reset; /* reset feature values to defaults */
162   feature_call get;   /* get feature values */
163 } features[] = {
164   { "LOG", feature_log_set, feature_log_reset, feature_log_get },
165   { 0, 0, 0, 0 }
166 };
167
168 static struct FeatureDesc *
169 feature_desc(struct Client* from, const char *feature)
170 {
171   int i;
172
173   assert(0 != feature);
174
175   for (i = 0; features[i].type; i++) /* find appropriate descriptor */
176     if (!ircd_strcmp(feature, features[i].type))
177       return &features[i];
178
179   Debug((DEBUG_ERROR, "Unknown feature \"%s\"", feature));
180   if (from)
181     send_reply(from, ERR_NOFEATURE, feature);
182   else
183     log_write(LS_CONFIG, L_ERROR, 0, "Unknown feature \"%s\"", feature);
184
185   return 0; /* not found */
186 }
187
188 int
189 feature_set(struct Client* from, const char* const* fields, int count)
190 {
191   struct FeatureDesc *feat;
192
193   if (count < 1) {
194     if (from)
195       need_more_params(from, "SET");
196     else
197       log_write(LS_CONFIG, L_ERROR, 0, "Not enough fields in F line");
198   } else if ((feat = feature_desc(from, fields[0])))
199     (*feat->set)(from, fields + 1, count - 1);
200
201   return 0;
202 }
203
204 int
205 feature_reset(struct Client* from, const char* const* fields, int count)
206 {
207   struct FeatureDesc *feat;
208
209   assert(0 != from);
210
211   if (count < 1)
212     need_more_params(from, "RESET");
213   else if ((feat = feature_desc(from, fields[0])))
214     (*feat->reset)(from, fields + 1, count - 1);
215
216   return 0;
217 }
218
219 int
220 feature_get(struct Client* from, const char* const* fields, int count)
221 {
222   struct FeatureDesc *feat;
223
224   assert(0 != from);
225
226   if (count < 1)
227     need_more_params(from, "GET");
228   else if ((feat = feature_desc(from, fields[0])))
229     (*feat->get)(from, fields + 1, count - 1);
230
231   return 0;
232 }