1 /************
2  *  cset.c  *
3  ************
4  *
5  * My code for creating all the "Channel Sets" on a per channel
6  * basis. We manage them here, and then just insert/remove/return them
7  * when a channel calls for them.
8  * Code for creating and modifying "Window Sets" on a per window
9  * basis.
10  *
11  * Note: Notice the shameless use of typecasting to get these functions
12  *	 to work as painlessly as possible.
13  *
14  * Written by Scott H Kilau
15  * Modified by Colten D Edwards for /wset
16  *
17  * Copyright(c) 1997
18  *
19  * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
20  */
21 
22 #if 0
23 [Sheik(~sheik@spartan.pei.edu)] notice in struct.h that the cset struct *does*
24           have a ->next pointer.. thats for the future when we may want to
25                     daisy chain cset's that don't have channels yet..  ie  a user can
26                               /cset *warez*  and know that all warez channels would get defaulted
27 #endif
28 
29 #include "irc.h"
30 static char cvsrevision[] = "$Id: cset.c 512 2014-10-26 13:08:43Z keaston $";
31 CVS_REVISION(cset_c)
32 #include "struct.h"
33 #include "vars.h"    /* for do_boolean() and var_settings[] */
34 #include "window.h"  /* for get_current_channel_by_refnum() */
35 #include "screen.h"  /* for curr_scr_win */
36 #include "names.h"   /* for lookup_channel() */
37 #include "log.h"
38 #include "ircaux.h"
39 #include "status.h"
40 #include "server.h"
41 #include "output.h"
42 #include "misc.h"
43 #include "list.h"
44 #include "cset.h"
45 #include "hash2.h"
46 #define MAIN_SOURCE
47 #include "modval.h"
48 
49 void log_channel(CSetArray *, CSetList *);
50 void limit_channel(CSetArray *, CSetList *);
51 void set_msglog_channel_level(CSetArray *, CSetList *);
52 
53 /*
54  * Array of structures for each of the cset vars... allows us to
55  * get an offset into the CSetList struct to that var
56  */
57 static CSetArray cset_array[] = {
58 { "AINV",			INT_TYPE_VAR,	offsetof(CSetList, set_ainv) ,NULL, 0 },
59 { "ANNOY_KICK",			BOOL_TYPE_VAR,	offsetof(CSetList, set_annoy_kick) ,NULL, 0 },
60 { "AOP",			BOOL_TYPE_VAR,	offsetof(CSetList, set_aop) ,NULL, 0 },
61 { "AUTO_JOIN_ON_INVITE",	BOOL_TYPE_VAR,	offsetof(CSetList, set_auto_join_on_invite), NULL, 0 },
62 { "AUTO_LIMIT",			INT_TYPE_VAR,	offsetof(CSetList, set_auto_limit), limit_channel, 0 },
63 { "AUTO_REJOIN",		INT_TYPE_VAR,   offsetof(CSetList, set_auto_rejoin) ,NULL, 0 },
64 { "BANTIME",			INT_TYPE_VAR,	offsetof(CSetList, set_bantime), NULL, 0 },
65 { "BITCH",			BOOL_TYPE_VAR,	offsetof(CSetList, bitch_mode) ,NULL, 0 },
66 { "CHANMODE",			STR_TYPE_VAR,	offsetof(CSetList, chanmode), NULL, 0 },
67 { "CHANNEL_LOG",		BOOL_TYPE_VAR,	offsetof(CSetList, channel_log) ,log_channel, 0 },
68 { "CHANNEL_LOG_FILE",		STR_TYPE_VAR,	offsetof(CSetList, channel_log_file), NULL, 0 },
69 { "CHANNEL_LOG_LEVEL",		STR_TYPE_VAR,	offsetof(CSetList, log_level), set_msglog_channel_level, 0 },
70 { "COMPRESS_MODES",		BOOL_TYPE_VAR,	offsetof(CSetList, compress_modes) ,NULL, 0 },
71 { "CTCP_FLOOD_BAN",		BOOL_TYPE_VAR,	offsetof(CSetList, set_ctcp_flood_ban), NULL, 0 },
72 { "DEOPFLOOD",			BOOL_TYPE_VAR,	offsetof(CSetList, set_deopflood) ,NULL, 0 },
73 { "DEOPFLOOD_TIME",		INT_TYPE_VAR,	offsetof(CSetList, set_deopflood_time) ,NULL, 0 },
74 { "DEOP_ON_DEOPFLOOD",		INT_TYPE_VAR,	offsetof(CSetList, set_deop_on_deopflood) ,NULL, 0 },
75 { "DEOP_ON_KICKFLOOD",		INT_TYPE_VAR,	offsetof(CSetList, set_deop_on_kickflood) ,NULL, 0 },
76 { "HACKING",			INT_TYPE_VAR,	offsetof(CSetList, set_hacking) ,NULL, 0 },
77 { "JOINFLOOD",			BOOL_TYPE_VAR,	offsetof(CSetList, set_joinflood) ,NULL, 0 },
78 { "JOINFLOOD_TIME",		INT_TYPE_VAR,	offsetof(CSetList, set_joinflood_time) ,NULL, 0 },
79 { "KICKFLOOD",			BOOL_TYPE_VAR,	offsetof(CSetList, set_kickflood) ,NULL, 0 },
80 { "KICKFLOOD_TIME",		INT_TYPE_VAR,	offsetof(CSetList, set_kickflood_time) ,NULL, 0 },
81 { "KICK_IF_BANNED",		BOOL_TYPE_VAR,  offsetof(CSetList, set_kick_if_banned) ,NULL, 0 },
82 { "KICK_ON_DEOPFLOOD",		INT_TYPE_VAR,   offsetof(CSetList, set_kick_on_deopflood) ,NULL, 0 },
83 { "KICK_ON_JOINFLOOD",		INT_TYPE_VAR,	offsetof(CSetList, set_kick_on_joinflood) ,NULL, 0 },
84 { "KICK_ON_KICKFLOOD",		INT_TYPE_VAR,   offsetof(CSetList, set_kick_on_kickflood) ,NULL, 0 },
85 { "KICK_ON_NICKFLOOD",		INT_TYPE_VAR,   offsetof(CSetList, set_kick_on_nickflood) ,NULL, 0 },
86 { "KICK_ON_PUBFLOOD",		INT_TYPE_VAR,   offsetof(CSetList, set_kick_on_pubflood) ,NULL, 0 },
87 { "KICK_OPS",			BOOL_TYPE_VAR,	offsetof(CSetList, set_kick_ops), NULL, 0 },
88 { "LAMEIDENT",			BOOL_TYPE_VAR,	offsetof(CSetList, set_lame_ident), NULL, 0},
89 { "LAMELIST",			BOOL_TYPE_VAR,  offsetof(CSetList, set_lamelist) ,NULL, 0 },
90 { "NICKFLOOD",			BOOL_TYPE_VAR,	offsetof(CSetList, set_nickflood) ,NULL, 0 },
91 { "NICKFLOOD_TIME",		INT_TYPE_VAR,	offsetof(CSetList, set_nickflood_time) ,NULL, 0 },
92 { "PUBFLOOD",			BOOL_TYPE_VAR,	offsetof(CSetList, set_pubflood) ,NULL, 0 },
93 { "PUBFLOOD_IGNORE_TIME",	INT_TYPE_VAR,	offsetof(CSetList, set_pubflood_ignore) ,NULL, 0 },
94 { "PUBFLOOD_TIME",		INT_TYPE_VAR,	offsetof(CSetList, set_pubflood_time) ,NULL, 0 },
95 { "SHITLIST",			BOOL_TYPE_VAR,  offsetof(CSetList, set_shitlist) ,NULL, 0 },
96 { "USERLIST",			BOOL_TYPE_VAR,  offsetof(CSetList, set_userlist) ,NULL, 0 },
97 { NULL,				0,		0, NULL, 0 }
98 };
99 
100 static WSetArray wset_array[] = {
101 { "STATUS_AWAY",		STR_TYPE_VAR,	offsetof(WSet, status_away),		offsetof(WSet, away_format), BX_build_status },
102 { "STATUS_CDCCCOUNT",		STR_TYPE_VAR,	offsetof(WSet, status_cdcccount),	offsetof(WSet, cdcc_format), BX_build_status },
103 { "STATUS_CHANNEL",		STR_TYPE_VAR,	offsetof(WSet, status_channel),		offsetof(WSet, channel_format), BX_build_status },
104 { "STATUS_CHANOP",		STR_TYPE_VAR,	offsetof(WSet, status_chanop),		-1, BX_build_status },
105 { "STATUS_CLOCK",		STR_TYPE_VAR,	offsetof(WSet, status_clock),		offsetof(WSet, clock_format), BX_build_status },
106 { "STATUS_CPU_SAVER",		STR_TYPE_VAR,	offsetof(WSet, status_cpu_saver), 	offsetof(WSet, cpu_saver_format), BX_build_status },
107 { "STATUS_DCCCOUNT",		STR_TYPE_VAR,	offsetof(WSet, status_dcccount),	offsetof(WSet, dcccount_format), BX_build_status },
108 { "STATUS_FLAG",		STR_TYPE_VAR,   offsetof(WSet, status_flag),		offsetof(WSet, flag_format), BX_build_status },
109 { "STATUS_FORMAT",              STR_TYPE_VAR,   offsetof(WSet, format_status),		-1, BX_build_status },
110 { "STATUS_FORMAT1",             STR_TYPE_VAR,   offsetof(WSet, format_status[1]),	-1, BX_build_status },
111 { "STATUS_FORMAT2",             STR_TYPE_VAR,   offsetof(WSet, format_status[2]),	-1, BX_build_status },
112 { "STATUS_FORMAT3",             STR_TYPE_VAR,   offsetof(WSet, format_status[3]),	-1, BX_build_status },
113 { "STATUS_HALFOP",		STR_TYPE_VAR,	offsetof(WSet, status_halfop),		-1, BX_build_status },
114 { "STATUS_HOLD",		STR_TYPE_VAR,	offsetof(WSet, status_hold),		-1, BX_build_status },
115 { "STATUS_HOLD_LINES",		STR_TYPE_VAR,	offsetof(WSet, status_hold_lines),	offsetof(WSet, hold_lines_format), BX_build_status },
116 { "STATUS_LAG",			STR_TYPE_VAR,	offsetof(WSet, status_lag),		offsetof(WSet, lag_format), BX_build_status },
117 { "STATUS_MAIL",		STR_TYPE_VAR,	offsetof(WSet, status_mail),		offsetof(WSet, mail_format), BX_build_status },
118 { "STATUS_MODE",		STR_TYPE_VAR,	offsetof(WSet, status_mode),		offsetof(WSet, mode_format), BX_build_status },
119 { "STATUS_MSGCOUNT",		STR_TYPE_VAR,	offsetof(WSet, status_msgcount),	offsetof(WSet, msgcount_format), BX_build_status },
120 { "STATUS_NICK",		STR_TYPE_VAR,	offsetof(WSet, status_nick),		offsetof(WSet, nick_format), BX_build_status },
121 { "STATUS_NOTIFY",		STR_TYPE_VAR,	offsetof(WSet, status_notify),		offsetof(WSet, notify_format), BX_build_status },
122 { "STATUS_OPER_KILLS",		STR_TYPE_VAR,	offsetof(WSet, status_oper_kills),	offsetof(WSet, kills_format), BX_build_status },
123 { "STATUS_QUERY",		STR_TYPE_VAR,	offsetof(WSet, status_query),		offsetof(WSet, query_format), BX_build_status },
124 { "STATUS_SCROLLBACK",		STR_TYPE_VAR,	offsetof(WSet, status_scrollback),	-1, BX_build_status },
125 { "STATUS_SERVER",		STR_TYPE_VAR,	offsetof(WSet, status_server),		offsetof(WSet, server_format), BX_build_status },
126 { "STATUS_TOPIC",		STR_TYPE_VAR,	offsetof(WSet, status_topic),		offsetof(WSet, topic_format), BX_build_status },
127 { "STATUS_UMODE",		STR_TYPE_VAR,	offsetof(WSet, status_umode),		offsetof(WSet, umode_format), BX_build_status },
128 { "STATUS_USER0",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats0),	-1, BX_build_status },
129 { "STATUS_USER1",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats1),	-1, BX_build_status },
130 { "STATUS_USER10",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats10),	-1, BX_build_status },
131 { "STATUS_USER11",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats11),	-1, BX_build_status },
132 { "STATUS_USER12",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats12),	-1, BX_build_status },
133 { "STATUS_USER13",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats13),	-1, BX_build_status },
134 { "STATUS_USER14",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats14),	-1, BX_build_status },
135 { "STATUS_USER15",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats15),	-1, BX_build_status },
136 { "STATUS_USER16",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats16),	-1, BX_build_status },
137 { "STATUS_USER17",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats17),	-1, BX_build_status },
138 { "STATUS_USER18",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats18),	-1, BX_build_status },
139 { "STATUS_USER19",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats19),	-1, BX_build_status },
140 { "STATUS_USER2",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats2),	-1, BX_build_status },
141 { "STATUS_USER20",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats20),	-1, BX_build_status },
142 { "STATUS_USER21",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats21),	-1, BX_build_status },
143 { "STATUS_USER22",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats22),	-1, BX_build_status },
144 { "STATUS_USER23",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats23),	-1, BX_build_status },
145 { "STATUS_USER24",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats24),	-1, BX_build_status },
146 { "STATUS_USER25",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats25),	-1, BX_build_status },
147 { "STATUS_USER26",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats26),	-1, BX_build_status },
148 { "STATUS_USER27",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats27),	-1, BX_build_status },
149 { "STATUS_USER28",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats28),	-1, BX_build_status },
150 { "STATUS_USER29",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats29),	-1, BX_build_status },
151 { "STATUS_USER3",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats3),	-1, BX_build_status },
152 { "STATUS_USER30",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats30),	-1, BX_build_status },
153 { "STATUS_USER31",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats31),	-1, BX_build_status },
154 { "STATUS_USER32",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats32),	-1, BX_build_status },
155 { "STATUS_USER33",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats33),	-1, BX_build_status },
156 { "STATUS_USER34",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats34),	-1, BX_build_status },
157 { "STATUS_USER35",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats35),	-1, BX_build_status },
158 { "STATUS_USER36",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats36),	-1, BX_build_status },
159 { "STATUS_USER37",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats37),	-1, BX_build_status },
160 { "STATUS_USER38",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats38),	-1, BX_build_status },
161 { "STATUS_USER39",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats39),	-1, BX_build_status },
162 { "STATUS_USER4",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats4),	-1, BX_build_status },
163 { "STATUS_USER5",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats5),	-1, BX_build_status },
164 { "STATUS_USER6",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats6),	-1, BX_build_status },
165 { "STATUS_USER7",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats7),	-1, BX_build_status },
166 { "STATUS_USER8",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats8),	-1, BX_build_status },
167 { "STATUS_USER9",		STR_TYPE_VAR,	offsetof(WSet, status_user_formats9),	-1, BX_build_status },
168 { "STATUS_USERS",		STR_TYPE_VAR,	offsetof(WSet, status_users),		offsetof(WSet, status_users_format), BX_build_status },
169 { "STATUS_VOICE",		STR_TYPE_VAR,	offsetof(WSet, status_voice),		-1, BX_build_status },
170 { "STATUS_WINDOW",		STR_TYPE_VAR,	offsetof(WSet, status_window),		-1, BX_build_status },
171 { NULL,				0,		0, -1, NULL }
172 };
173 
174 CSetList *cset_queue = NULL;
175 
176 /*
177  * Returns the address of the requested field within the given CSetList.
178  */
get_cset_var_address(CSetList * tmp,int var)179 static void *get_cset_var_address(CSetList *tmp, int var)
180 {
181 	void *ptr = ((char *)tmp + cset_array[var].offset);
182 	return ptr;
183 }
184 
185 /*
186  * returns the requested int from the cset struct
187  * Will work fine with either BOOL or INT type of csets.
188  */
BX_get_cset_int_var(CSetList * tmp,int var)189 int BX_get_cset_int_var(CSetList *tmp, int var)
190 {
191 	int *ptr = get_cset_var_address(tmp, var);
192 	return *ptr;
193 }
194 
BX_get_cset_str_var(CSetList * tmp,int var)195 char *BX_get_cset_str_var(CSetList *tmp, int var)
196 {
197 	char **ptr = get_cset_var_address(tmp, var);
198 	return *ptr;
199 }
200 
201 /*
202  * sets the requested int from the cset struct
203  * Will work fine with either BOOL or INT type of csets.
204  */
BX_set_cset_int_var(CSetList * tmp,int var,int value)205 void BX_set_cset_int_var(CSetList *tmp, int var, int value)
206 {
207 	int *ptr = get_cset_var_address(tmp, var);
208 	*ptr = value;
209 }
210 
BX_set_cset_str_var(CSetList * tmp,int var,const char * value)211 void BX_set_cset_str_var(CSetList *tmp, int var, const char *value)
212 {
213 	char **ptr = get_cset_var_address(tmp, var);
214 	if (value)
215 		malloc_strcpy(ptr, value);
216 	else
217 		new_free(ptr);
218 }
219 
220 /*
221  * Next few functions ripped from vars.c, as we are really doing the same
222  * thing as those functions did, with a couple changes... The nice
223  * thing about this is that we will get the same "feel" now with
224  * SET's and CSET's
225  */
find_cset_variable(CSetArray * array,char * org_name,int * cnt)226 static int find_cset_variable(CSetArray *array, char *org_name, int *cnt)
227 {
228 	CSetArray *v, *first;
229 	int     len, var_index;
230 	char    *name = NULL;
231 
232 	len = strlen(org_name);
233 	name = LOCAL_COPY(org_name);
234 
235 	upper(name);
236 	var_index = 0;
237 	for (first = array; first->name; first++, var_index++)
238 	{
239 		if (strncmp(name, first->name, len) == 0)
240 		{
241 			*cnt = 1;
242 			break;
243 		}
244 	}
245 	if (first->name)
246 	{
247 		if (strlen(first->name) != len)
248 		{
249 			v = first;
250 			for (v++; v->name; v++, (*cnt)++)
251 			{
252 				if (strncmp(name, v->name, len) != 0)
253 					break;
254 			}
255 		}
256 		return (var_index);
257 	}
258 	else
259 	{
260 		*cnt = 0;
261 		return (-1);
262 	}
263 }
264 
265 
set_cset_var_value(CSetList * tmp,int var_index,char * value)266 static void set_cset_var_value(CSetList *tmp, int var_index, char *value)
267 {
268 	char    *rest;
269 	CSetArray *var;
270 
271 	var = &(cset_array[var_index]);
272 
273 	switch (var->type)
274 	{
275 	case BOOL_TYPE_VAR:
276         	if (value && *value && (value = next_arg(value, &rest))) {
277 			if (do_boolean(value, (int *)get_cset_var_address(tmp, var_index)))
278 			{
279 				say("Value must be either ON, OFF, or TOGGLE");
280 				break;
281 			}
282 			if (var->func)
283 				var->func(var, tmp);
284 			put_it("%s", convert_output_format(fget_string_var(FORMAT_CSET_FSET), "%s %s %s", var->name, tmp->channel, get_cset_int_var(tmp, var_index)?var_settings[ON] : var_settings[OFF]));
285 		}
286 		else
287 			put_it("%s", convert_output_format(fget_string_var(FORMAT_CSET_FSET), "%s %s %s", var->name, tmp->channel, get_cset_int_var(tmp, var_index)?var_settings[ON] : var_settings[OFF]));
288 		break;
289 
290 	case INT_TYPE_VAR:
291 		if (value && *value && (value = next_arg(value, &rest)))
292 		{
293 			int     val;
294 
295 			if (!is_number(value))
296 			{
297 				say("Value of %s must be numeric!", var->name);
298 				break;
299 			}
300 			if ((val = atoi(value)) < 0)
301 			{
302 				say("Value of %s must be greater than 0", var->name);
303 				break;
304 			}
305 			set_cset_int_var(tmp, var_index, val);
306 			if (var->func)
307 				var->func(var, tmp);
308 			put_it("%s", convert_output_format(fget_string_var(FORMAT_CSET_FSET), "%s %s %d", var->name, tmp->channel, get_cset_int_var(tmp, var_index)));
309 		}
310 		else
311 			put_it("%s", convert_output_format(fget_string_var(FORMAT_CSET_FSET), "%s %s %d", var->name, tmp->channel, get_cset_int_var(tmp, var_index)));
312 		break;
313 	case STR_TYPE_VAR:
314 		if (value && *value)
315 		{
316 			set_cset_str_var(tmp, var_index, value);
317 			if (var->func)
318 				var->func(var, tmp);
319 			put_it("%s", convert_output_format(fget_string_var(FORMAT_CSET_FSET), "%s %s %s", var->name, tmp->channel, get_cset_str_var(tmp, var_index) ));
320 		}
321 		else
322 			put_it("%s", convert_output_format(fget_string_var(FORMAT_CSET_FSET), "%s %s %s", var->name, tmp->channel, (char *)get_cset_str_var(tmp, var_index)));
323 	}
324 }
325 
check_cset_queue(char * channel,int add)326 CSetList *check_cset_queue(char *channel, int add)
327 {
328 	CSetList *c = NULL;
329 	int found = 0;
330 	if (!strchr(channel, '*') && !(c = (CSetList *)find_in_list((List **)&cset_queue, channel, 0)))
331 	{
332 		if (!add)
333 		{
334 			for (c = cset_queue; c; c = c->next)
335 				if (!my_stricmp(c->channel, channel) || wild_match(c->channel, channel))
336 					return c;
337 			return NULL;
338 		}
339 		c = create_csets_for_channel(channel);
340 		add_to_list((List **)&cset_queue, (List *)c);
341 		found++;
342 	}
343 	if (c)
344 		return c;
345 	if (add && !found)
346 	{
347 		for (c = cset_queue; c; c = c->next)
348 			if (!my_stricmp(c->channel, channel))
349 				return c;
350 		c = create_csets_for_channel(channel);
351 		c->next = cset_queue;
352 		cset_queue = c;
353 		return c;
354 	}
355 	return NULL;
356 }
357 
cset_variable_case1(char * channel,int var_index,char * args)358 static inline void cset_variable_case1(char *channel, int var_index, char *args)
359 {
360 	ChannelList *chan = NULL;
361 	int tmp = 0;
362 	int count = 0;
363 	/*
364 	 * implement a queue for channels that don't exist... later...
365 	 * go home if user doesn't have any channels.
366 	 */
367 	if (current_window->server != -1)
368 	{
369 		for (chan = get_server_channels(current_window->server); chan; chan = chan->next)
370 		{
371 			tmp = var_index;
372 			if (wild_match(channel, chan->channel))
373 			{
374 				set_cset_var_value(chan->csets, tmp, args);
375 				count++;
376 			}
377 		}
378 	}
379 	/* no channel match. lets check the queue */
380 /*	if (!count)*/
381 	{
382 		CSetList *c = NULL;
383 		if (!count)
384 			check_cset_queue(channel, 1);
385 		for (c = cset_queue; c; c = c->next)
386 		{
387 			tmp = var_index;
388 			if (!my_stricmp(channel, c->channel) || wild_match(channel, c->channel))
389 			{
390 				set_cset_var_value(c, tmp, args);
391 				count++;
392 			}
393 		}
394 		if (!count)
395 			say("CSET_VARIABLE: No match in cset queue for %s", channel);
396 	}
397 }
398 
cset_variable_casedef(char * channel,int cnt,int var_index,char * args)399 static inline void cset_variable_casedef(char *channel, int cnt, int var_index, char *args)
400 {
401 	ChannelList *chan = NULL;
402 	int tmp, tmp2;
403 	int count = 0;
404 
405 	if (current_window->server != -1)
406 	{
407 		for (chan = get_server_channels(current_window->server); chan; chan = chan->next)
408 		{
409 			tmp = var_index;
410 			tmp2 = cnt;
411 			if (wild_match(channel, chan->channel))
412 			{
413 				for (tmp2 += tmp; tmp < tmp2; tmp++)
414 					set_cset_var_value(chan->csets, tmp, empty_string);
415 				count++;
416 			}
417 		}
418 	}
419 /*	if (!count) */
420 	{
421 		CSetList *c = NULL;
422 		if (!count)
423 			check_cset_queue(channel, 1);
424 		for (c = cset_queue; c; c = c->next)
425 		{
426 			tmp = var_index;
427 			tmp2 = cnt;
428 			if (!my_stricmp(channel, c->channel) || wild_match(channel, c->channel))
429 			{
430 				for (tmp2 +=tmp; tmp < tmp2; tmp++)
431 					set_cset_var_value(c, tmp, empty_string);
432 				count++;
433 			}
434 		}
435 		if (!count)
436 			say("CSET_VARIABLE: No match in cset queue for %s", channel);
437 		return;
438 	}
439 
440 }
441 
cset_variable_noargs(char * channel)442 static inline void cset_variable_noargs(char *channel)
443 {
444 	int var_index = 0;
445 	ChannelList *chan = NULL;
446 	int count = 0;
447 
448 	if (current_window->server != -1)
449 	{
450 		for (chan = get_server_channels(current_window->server); chan; chan = chan->next)
451 		{
452 			if (wild_match(channel, chan->channel))
453 			{
454 				for (var_index = 0; var_index < NUMBER_OF_CSETS; var_index++)
455 					set_cset_var_value(chan->csets, var_index, empty_string);
456 				count++;
457 			}
458 		}
459 	}
460 /*	if (!count) */
461 	{
462 		CSetList *c = NULL;
463 		if (!count)
464 			check_cset_queue(channel, 1);
465 		for (c = cset_queue; c; c = c->next)
466 		{
467 			if (!wild_match(channel, c->channel))
468 				continue;
469 			for (var_index = 0; var_index < NUMBER_OF_CSETS; var_index++)
470 				set_cset_var_value(c, var_index, empty_string);
471 			count++;
472 		}
473 		if (!count)
474 			say("CSET_VARIABLE: No match in cset queue for %s", channel ? channel : empty_string);
475 		return;
476 	}
477 
478 }
479 
set_cset(char * var,ChannelList * chan,char * value)480 char *set_cset(char *var, ChannelList *chan, char *value)
481 {
482 int var_index, cnt = 0;
483 	var_index = find_cset_variable(cset_array, var, &cnt);
484 	if (cnt == 1)
485 	{
486 		CSetArray *var;
487 		var = &(cset_array[var_index]);
488 		switch(var->type)
489 		{
490 			case BOOL_TYPE_VAR:
491 			{
492 				int i = my_atol(value);
493 				set_cset_int_var(chan->csets, var_index, i? 1 : 0);
494 				break;
495 			}
496 			case INT_TYPE_VAR:
497 			{
498 				int i = my_atol(value);
499 				set_cset_int_var(chan->csets, var_index, i);
500 				break;
501 			}
502 			case STR_TYPE_VAR:
503 			{
504 				set_cset_str_var(chan->csets, var_index, value);
505 				break;
506 			}
507 			default:
508 				return NULL;
509 		}
510 		return value;
511 	}
512 	return NULL;
513 }
514 
get_cset(char * var,ChannelList * chan,char * value)515 char *get_cset(char *var, ChannelList *chan, char *value)
516 {
517 int var_index, cnt = 0;
518 	var_index = find_cset_variable(cset_array, var, &cnt);
519 	if (cnt == 1)
520 	{
521 		char s[81];
522 		CSetArray *var;
523 		var = &(cset_array[var_index]);
524 		*s = 0;
525 		switch (var->type)
526 		{
527 			case BOOL_TYPE_VAR:
528 			{
529 				strcpy(s, get_cset_int_var(chan->csets, var_index)?var_settings[ON] : var_settings[OFF]);
530 				if (value)
531 				{
532 					int val = -1;
533 					if (!my_stricmp(value, on))
534 						val = 1;
535 					else if (!my_stricmp(value, off))
536 						val = 0;
537 					else
538 					{
539 						if (isdigit((unsigned char)*value))
540 							val = (int)(*value - '0');
541 					}
542 					if (val != -1)
543 						set_cset_int_var(chan->csets, var_index, val);
544 				}
545 				break;
546 			}
547 			case INT_TYPE_VAR:
548 			{
549 				strncpy(s, ltoa(get_cset_int_var(chan->csets, var_index)), 30);
550 				if (value && isdigit((unsigned char)*value))
551 					set_cset_int_var(chan->csets, var_index, my_atol(value));
552 				break;
553 			}
554 			case STR_TYPE_VAR:
555 			{
556 				char *t;
557 				t = m_strdup(get_cset_str_var(chan->csets, var_index));
558 				if (value)
559 					set_cset_str_var(chan->csets, var_index, value);
560 				return t;
561 			}
562 		}
563 		return m_strdup(*s ? s : empty_string);
564 	}
565 	return m_strdup(empty_string);
566 }
567 
BUILT_IN_COMMAND(cset_variable)568 BUILT_IN_COMMAND(cset_variable)
569 {
570 	char    *var, *channel = NULL;
571 	int     no_args = 1, cnt, var_index, hook = 1;
572 
573 	if (from_server != -1 && current_window->server != -1)
574 	{
575 		if (args && *args && (is_channel(args) || *args == '*'))
576 			channel = next_arg(args, &args);
577 		else
578 			channel = get_current_channel_by_refnum(0);
579 	}
580 	else if (args && *args && (is_channel(args) || *args == '*'))
581 		channel = next_arg(args, &args);
582 
583 	if (!channel)
584 		return;
585 
586 	if ((var = next_arg(args, &args)) != NULL)
587 	{
588 		if (*var == '-')
589 		{
590 			var++;
591 			args = NULL;
592 		}
593 		var_index = find_cset_variable(cset_array, var, &cnt);
594 
595 		if (hook)
596 		{
597 			switch (cnt)
598 			{
599 				case 0:
600 					say("No such variable \"%s\"", var);
601 					return;
602 				case 1:
603 					cset_variable_case1(channel, var_index, args);
604 					return;
605 				default:
606 					say("%s is ambiguous", var);
607 					cset_variable_casedef(channel, cnt, var_index, args);
608 					return;
609 			}
610 		}
611 	}
612 	if (no_args)
613 		cset_variable_noargs(channel);
614 }
615 
create_csets_for_channel(char * channel)616 CSetList *create_csets_for_channel(char *channel)
617 {
618 	CSetList *tmp;
619 #ifdef VAR_DEBUG
620  	int i;
621 
622 	for (i = 1; i < NUMBER_OF_CSETS - 1; i++)
623 		if (strcmp(cset_array[i-1].name, cset_array[i].name) >= 0)
624 			ircpanic("Variable [%d] (%s) is out of order.", i, cset_array[i].name);
625 #endif
626 
627 	if (check_cset_queue(channel, 0))
628 	{
629 		if ((tmp = (CSetList *)find_in_list((List **)&cset_queue, channel, 0)))
630 			return tmp;
631 		for (tmp = cset_queue; tmp; tmp = tmp->next)
632 			if (!my_stricmp(tmp->channel, channel) || wild_match(tmp->channel, channel))
633 				return tmp;
634 	}
635 	tmp = (CSetList *) new_malloc(sizeof(CSetList));
636 	/* use default settings. */
637 	tmp->set_aop = get_int_var(AOP_VAR);
638 	tmp->set_annoy_kick = get_int_var(ANNOY_KICK_VAR);
639 	tmp->set_ainv = get_int_var(AINV_VAR);
640 	tmp->set_auto_join_on_invite = get_int_var(AUTO_JOIN_ON_INVITE_VAR);
641 	tmp->set_auto_rejoin = get_int_var(AUTO_REJOIN_VAR);
642 	tmp->set_bantime = get_int_var(BANTIME_VAR);
643 	tmp->compress_modes = get_int_var(COMPRESS_MODES_VAR);
644 	tmp->bitch_mode = get_int_var(BITCH_VAR);
645 	tmp->channel_log = 0;
646 
647 	tmp->log_level = m_strdup("ALL");
648 	set_msglog_channel_level(cset_array, tmp);
649 #if defined(WINNT) || defined(__EMX__)
650 	tmp->channel_log_file = m_sprintf("~/bx-conf/%s.log", channel+1);
651 #else
652 	tmp->channel_log_file = m_sprintf("~/.BitchX/%s.log", channel+1);
653 #endif
654 	tmp->set_joinflood = get_int_var(JOINFLOOD_VAR);
655 	tmp->set_joinflood_time = get_int_var(JOINFLOOD_TIME_VAR);
656 	tmp->set_ctcp_flood_ban = get_int_var(CTCP_FLOOD_BAN_VAR);
657 	tmp->set_deop_on_deopflood = get_int_var(DEOP_ON_DEOPFLOOD_VAR);
658 	tmp->set_deop_on_kickflood = get_int_var(DEOP_ON_KICKFLOOD_VAR);
659 	tmp->set_deopflood = get_int_var(DEOPFLOOD_VAR);
660 	tmp->set_deopflood_time = get_int_var(DEOPFLOOD_TIME_VAR);
661 
662 	tmp->set_hacking = get_int_var(HACKING_VAR);
663 
664 	tmp->set_kick_on_deopflood = get_int_var(KICK_ON_DEOPFLOOD_VAR);
665 	tmp->set_kick_on_joinflood = get_int_var(KICK_ON_JOINFLOOD_VAR);
666 	tmp->set_kick_on_kickflood = get_int_var(KICK_ON_KICKFLOOD_VAR);
667 	tmp->set_kick_on_nickflood = get_int_var(KICK_ON_NICKFLOOD_VAR);
668 	tmp->set_kick_on_pubflood = get_int_var(KICK_ON_PUBFLOOD_VAR);
669 
670 	tmp->set_kickflood = get_int_var(KICKFLOOD_VAR);
671 	tmp->set_kickflood_time = get_int_var(KICKFLOOD_TIME_VAR);
672 	tmp->set_kick_ops = get_int_var(KICK_OPS_VAR);
673 	tmp->set_nickflood = get_int_var(NICKFLOOD_VAR);
674 	tmp->set_nickflood_time = get_int_var(NICKFLOOD_TIME_VAR);
675 
676 	tmp->set_pubflood = get_int_var(PUBFLOOD_VAR);
677 	tmp->set_pubflood_time = get_int_var(PUBFLOOD_TIME_VAR);
678 	tmp->set_pubflood_ignore = 60;
679 	tmp->set_userlist = get_int_var(USERLIST_VAR);
680 	tmp->set_shitlist = get_int_var(SHITLIST_VAR);
681 	tmp->set_lamelist = get_int_var(LAMELIST_VAR);
682 	tmp->set_lame_ident = get_int_var(LAMEIDENT_VAR);
683 	tmp->set_kick_if_banned = get_int_var(KICK_IF_BANNED_VAR);
684 	tmp->set_auto_limit = get_int_var(AUTO_LIMIT_VAR);
685 
686 
687 	malloc_strcpy(&tmp->chanmode, get_string_var(CHANMODE_VAR));
688 	malloc_strcpy(&tmp->channel, channel);
689 
690 	return tmp;
691 }
692 
remove_csets_for_channel(CSetList * tmp)693 void remove_csets_for_channel(CSetList *tmp)
694 {
695 	new_free(&tmp->channel);
696 	new_free(&tmp->channel_log_file);
697 	new_free(&tmp->chanmode);
698 	new_free(&tmp);
699 }
700 
701 
702 
find_wset_variable(WSetArray * array,char * org_name,int * cnt)703 static int find_wset_variable(WSetArray *array, char *org_name, int *cnt)
704 {
705 	WSetArray *v, *first;
706 	int     len, var_index;
707 	char    *name = NULL;
708 
709 	len = strlen(org_name);
710 	name = LOCAL_COPY(org_name);
711 
712 	upper(name);
713 	var_index = 0;
714 	for (first = array; first->name; first++, var_index++)
715 	{
716 		if (strncmp(name, first->name, len) == 0)
717 		{
718 			*cnt = 1;
719 			break;
720 		}
721 	}
722 	if (first->name)
723 	{
724 		if (strlen(first->name) != len)
725 		{
726 			v = first;
727 			for (v++; v->name; v++, (*cnt)++)
728 			{
729 				if (strncmp(name, v->name, len) != 0)
730 					break;
731 			}
732 		}
733 		return (var_index);
734 	}
735 	else
736 	{
737 		*cnt = 0;
738 		return (-1);
739 	}
740 }
741 
742 
743 
744 
745 /*
746  * returns the requested int from the cset struct
747  * Will work fine with either BOOL or INT type of csets.
748  */
BX_get_wset_string_var(WSet * tmp,int var)749 char *BX_get_wset_string_var(WSet *tmp, int var)
750 {
751 	char **ptr = (char **)((unsigned long)tmp + wset_array[var].offset);
752 	return *ptr;
753 }
754 
755 /*
756  * returns the requested int ADDRESS from the wset struct
757  * Will work fine with STR_TYPE_VAR type of csets.
758  */
get_wset_str_var_address(WSet * tmp,int var)759 static char ** get_wset_str_var_address(WSet *tmp, int var)
760 {
761 	char **ptr = (char **)((unsigned long)tmp + wset_array[var].offset);
762 	return ptr;
763 }
764 
765 /*
766  * returns the requested int ADDRESS from the wset struct
767  * Will work fine with STR_TYPE_VAR type of csets.
768  */
get_wset_format_var_address(WSet * tmp,int var)769 char ** get_wset_format_var_address(WSet *tmp, int var)
770 {
771 	char **ptr = NULL;
772 	if (wset_array[var].format_offset != -1)
773 		ptr = (char **)((unsigned long)tmp + wset_array[var].format_offset);
774 	return ptr;
775 }
776 
777 /*
778  * sets the requested string from the wset struct
779  */
780 
BX_set_wset_string_var(WSet * tmp,int var,char * value)781 void BX_set_wset_string_var(WSet *tmp, int var, char *value)
782 {
783 	char **ptr = (char **)((unsigned long)tmp + wset_array[var].offset);
784 	if (value && *value)
785 		malloc_strcpy(ptr, value);
786 	else
787 		new_free(ptr);
788 }
789 
790 
791 
792 
793 
set_wset_var_value(Window * win,int var_index,char * value)794 static void set_wset_var_value(Window *win, int var_index, char *value)
795 {
796 	WSetArray *var;
797 
798 	var = &(wset_array[var_index]);
799 
800 	switch (var->type)
801 	{
802 	case STR_TYPE_VAR:
803 		{
804 			char **val = NULL;
805 			if ((val = get_wset_str_var_address(win->wset, var_index)))
806 			{
807 				if (value)
808 				{
809 					if (*value)
810 						malloc_strcpy(val, value);
811 					else
812 					{
813 						put_it("%s", convert_output_format(fget_string_var(FORMAT_SET_FSET), "%s %s", var->name, *val?*val:empty_string));
814 						return;
815 					}
816 				} else
817 					new_free(val);
818 				if (var->func)
819 					(var->func) (win, *val, 0);
820 				say("Value of %s set to %s", var->name, *val ?
821 					*val : "<EMPTY>");
822 			}
823 		}
824 		break;
825 	default:
826 		say("WSET_type not supported");
827 	}
828 }
829 
wset_variable_case1(Window * win,char * name,int var_index,char * args)830 static inline void wset_variable_case1(Window *win, char *name, int var_index, char *args)
831 {
832 Window *tmp = NULL;
833 int count = 0;
834 int i;
835 	if (!name)
836 	{
837 		set_wset_var_value(win, var_index, args);
838 		return;
839 	}
840 	while ((traverse_all_windows(&tmp)))
841 	{
842 		i = var_index;
843 		if (*name == '*')
844 		{
845 			set_wset_var_value(tmp, i, args);
846 			count++;
847 		}
848 		else if ((tmp->name && wild_match(name, tmp->name)) || (tmp->refnum == my_atol(name)))
849 		{
850 			set_wset_var_value(tmp, i, args);
851 			count++;
852 		}
853 	}
854 	if (!count)
855 		say("No such window name [%s]", name);
856 }
857 
wset_variable_casedef(Window * win,char * name,int cnt,int var_index,char * args)858 static inline void wset_variable_casedef(Window *win, char *name, int cnt, int var_index, char *args)
859 {
860 Window *tmp = NULL;
861 int count = 0;
862 int c, i;
863 	if (!name)
864 	{
865 		for (cnt +=var_index; var_index < cnt; var_index++)
866 			set_wset_var_value(win, var_index, args);
867 		return;
868 	}
869 	while ((traverse_all_windows(&tmp)))
870 	{
871 		c = cnt;
872 		i = var_index;
873 		if (*name == '*')
874 		{
875 			for (c += i; i < c; i++)
876 				set_wset_var_value(tmp, i, empty_string);
877 			count++;
878 		}
879 		else if ((tmp->name && wild_match(name, tmp->name)) || (tmp->refnum == my_atol(name)) )
880 		{
881 			for (c += i; i < c; i++)
882 				set_wset_var_value(tmp, i, empty_string);
883 			count++;
884 		}
885 	}
886 	if (!count)
887 		say("No such window name [%s]", name);
888 }
889 
wset_variable_noargs(Window * win,char * name)890 static inline void wset_variable_noargs(Window *win, char *name)
891 {
892 Window *tmp = NULL;
893 int var_index = 0;
894 	if (!name)
895 	{
896 		for (var_index = 0; var_index < NUMBER_OF_WSETS; var_index++)
897 			set_wset_var_value(win, var_index, empty_string);
898 	}
899 	else
900 	{
901 		int count = 0;
902 		while ((traverse_all_windows(&tmp)))
903 		{
904 			if (*name == '*')
905 			{
906 				for (var_index = 0; var_index < NUMBER_OF_WSETS; var_index++)
907 					set_wset_var_value(tmp, var_index, empty_string);
908 				count++;
909 			}
910 			else if ((tmp->name && wild_match(name, tmp->name)) || (tmp->refnum == my_atol(name)))
911 			{
912 				for (var_index = 0; var_index < NUMBER_OF_WSETS; var_index++)
913 					set_wset_var_value(tmp, var_index, empty_string);
914 				count++;
915 			}
916 		}
917 		if (!count)
918 			say("No such window name [%s]", name);
919 	}
920 }
921 
922 
BUILT_IN_COMMAND(wset_variable)923 BUILT_IN_COMMAND(wset_variable)
924 {
925 	char    *var;
926 	char	*possible;
927 	char 	*name = NULL;
928 	int     no_args = 1, cnt, var_index;
929 	Window *win = screen_list->window_list;
930 
931 	if (args)
932 	{
933 		if (*args == '*')
934 			name = next_arg(args, &args);
935 		else if (args && *args)
936 		{
937 			possible = LOCAL_COPY(args);
938 			name = next_arg(possible, &possible);
939 			if (!(win = get_window_by_name(name)))
940 			{
941 				win = get_window_by_refnum(my_atol(name));
942 				if (!win)
943 				{
944 					if (isdigit((unsigned char)*name))
945 					{
946 						say("No such window refnum %d", my_atol(name));
947 						return;
948 					}
949 				}
950 				else if (isdigit((unsigned char)*name))
951 					var = next_arg(args, &args);
952 				name = NULL;
953 			}
954 			else
955 				var = next_arg(args, &args);
956 		}
957 	}
958 	else
959 		win = current_window;
960 
961 
962 	if ((var = next_arg(args, &args)) != NULL)
963 	{
964 		if (*var == '-')
965 		{
966 			var++;
967 			args = NULL;
968 		}
969 		var_index = find_wset_variable(wset_array, var, &cnt);
970 		switch (cnt)
971 		{
972 			case 0:
973 				say("No such variable \"%s\"", var);
974 				return;
975 			case 1:
976 				wset_variable_case1(win, name, var_index, args);
977 				update_all_status(win, NULL, 0);
978 				update_all_windows();
979 				return;
980 			default:
981 				say("%s is ambiguous", var);
982 				wset_variable_casedef(win, name, cnt, var_index, args);
983 				return;
984 		}
985 	}
986 	if (no_args)
987 		wset_variable_noargs(win, name);
988 }
989 
990 
create_wsets_for_window(Window * win)991 WSet *create_wsets_for_window(Window *win)
992 {
993 	WSet *tmp;
994 #ifdef VAR_DEBUG
995  	int i;
996 
997 	for (i = 1; i < NUMBER_OF_CSETS - 1; i++)
998 		if (strcmp(wset_array[i-1].name, wset_array[i].name) >= 0)
999 			ircpanic("Variable [%d] (%s) is out of order.", i, wset_array[i].name);
1000 #endif
1001 
1002 	tmp = (WSet *) new_malloc(sizeof(WSet));
1003 
1004 	malloc_strcpy(&tmp->status_channel, get_string_var(STATUS_CHANNEL_VAR));
1005 	malloc_strcpy(&tmp->status_chanop, get_string_var(STATUS_CHANOP_VAR));
1006 	malloc_strcpy(&tmp->status_halfop, get_string_var(STATUS_HALFOP_VAR));
1007 	malloc_strcpy(&tmp->status_clock, get_string_var(STATUS_CLOCK_VAR));
1008 	malloc_strcpy(&tmp->status_hold_lines, get_string_var(STATUS_HOLD_LINES_VAR));
1009 	malloc_strcpy(&tmp->status_hold, get_string_var(STATUS_HOLD_VAR));
1010 	malloc_strcpy(&tmp->status_voice, get_string_var(STATUS_VOICE_VAR));
1011 	malloc_strcpy(&tmp->status_dcccount, get_string_var(STATUS_DCCCOUNT_VAR));
1012 	malloc_strcpy(&tmp->status_cdcccount, get_string_var(STATUS_CDCCCOUNT_VAR));
1013 	malloc_strcpy(&tmp->status_cpu_saver, get_string_var(STATUS_CPU_SAVER_VAR));
1014 	malloc_strcpy(&tmp->status_lag, get_string_var(STATUS_LAG_VAR));
1015 	malloc_strcpy(&tmp->status_away, get_string_var(STATUS_AWAY_VAR));
1016 	malloc_strcpy(&tmp->status_mail, get_string_var(STATUS_MAIL_VAR));
1017 	malloc_strcpy(&tmp->status_mode, get_string_var(STATUS_MODE_VAR));
1018 	malloc_strcpy(&tmp->status_notify, get_string_var(STATUS_NOTIFY_VAR));
1019 	malloc_strcpy(&tmp->status_oper_kills, get_string_var(STATUS_OPER_KILLS_VAR));
1020 	malloc_strcpy(&tmp->status_query, get_string_var(STATUS_QUERY_VAR));
1021 	malloc_strcpy(&tmp->status_server, get_string_var(STATUS_SERVER_VAR));
1022 	malloc_strcpy(&tmp->status_topic, get_string_var(STATUS_TOPIC_VAR));
1023 	malloc_strcpy(&tmp->status_umode, get_string_var(STATUS_UMODE_VAR));
1024 	malloc_strcpy(&tmp->status_users, get_string_var(STATUS_USERS_VAR));
1025 	malloc_strcpy(&tmp->status_msgcount, get_string_var(STATUS_MSGCOUNT_VAR));
1026 	malloc_strcpy(&tmp->status_nick, get_string_var(STATUS_NICK_VAR));
1027 	malloc_strcpy(&tmp->status_flag, get_string_var(STATUS_FLAG_VAR));
1028 	malloc_strcpy(&tmp->status_scrollback, get_string_var(STATUS_SCROLLBACK_VAR));
1029 
1030 	malloc_strcpy(&tmp->format_status[0], get_string_var(STATUS_FORMAT_VAR));
1031 	malloc_strcpy(&tmp->format_status[1], get_string_var(STATUS_FORMAT1_VAR));
1032 	malloc_strcpy(&tmp->format_status[2], get_string_var(STATUS_FORMAT2_VAR));
1033 	malloc_strcpy(&tmp->format_status[3], get_string_var(STATUS_FORMAT3_VAR));
1034 
1035 	malloc_strcpy(&tmp->status_user_formats0, get_string_var(STATUS_USER0_VAR));
1036 	malloc_strcpy(&tmp->status_user_formats1, get_string_var(STATUS_USER1_VAR));
1037 	malloc_strcpy(&tmp->status_user_formats10, get_string_var(STATUS_USER10_VAR));
1038 	malloc_strcpy(&tmp->status_user_formats11, get_string_var(STATUS_USER11_VAR));
1039 	malloc_strcpy(&tmp->status_user_formats12, get_string_var(STATUS_USER12_VAR));
1040 	malloc_strcpy(&tmp->status_user_formats13, get_string_var(STATUS_USER13_VAR));
1041 	malloc_strcpy(&tmp->status_user_formats14, get_string_var(STATUS_USER14_VAR));
1042 	malloc_strcpy(&tmp->status_user_formats15, get_string_var(STATUS_USER15_VAR));
1043 	malloc_strcpy(&tmp->status_user_formats16, get_string_var(STATUS_USER16_VAR));
1044 	malloc_strcpy(&tmp->status_user_formats17, get_string_var(STATUS_USER17_VAR));
1045 	malloc_strcpy(&tmp->status_user_formats18, get_string_var(STATUS_USER18_VAR));
1046 	malloc_strcpy(&tmp->status_user_formats19, get_string_var(STATUS_USER19_VAR));
1047 	malloc_strcpy(&tmp->status_user_formats2, get_string_var(STATUS_USER2_VAR));
1048 	malloc_strcpy(&tmp->status_user_formats20, get_string_var(STATUS_USER20_VAR));
1049 	malloc_strcpy(&tmp->status_user_formats21, get_string_var(STATUS_USER21_VAR));
1050 	malloc_strcpy(&tmp->status_user_formats22, get_string_var(STATUS_USER22_VAR));
1051 	malloc_strcpy(&tmp->status_user_formats23, get_string_var(STATUS_USER23_VAR));
1052 	malloc_strcpy(&tmp->status_user_formats24, get_string_var(STATUS_USER24_VAR));
1053 	malloc_strcpy(&tmp->status_user_formats25, get_string_var(STATUS_USER25_VAR));
1054 	malloc_strcpy(&tmp->status_user_formats26, get_string_var(STATUS_USER26_VAR));
1055 	malloc_strcpy(&tmp->status_user_formats27, get_string_var(STATUS_USER27_VAR));
1056 	malloc_strcpy(&tmp->status_user_formats28, get_string_var(STATUS_USER28_VAR));
1057 	malloc_strcpy(&tmp->status_user_formats29, get_string_var(STATUS_USER29_VAR));
1058 	malloc_strcpy(&tmp->status_user_formats3, get_string_var(STATUS_USER3_VAR));
1059 	malloc_strcpy(&tmp->status_user_formats30, get_string_var(STATUS_USER30_VAR));
1060 	malloc_strcpy(&tmp->status_user_formats31, get_string_var(STATUS_USER31_VAR));
1061 	malloc_strcpy(&tmp->status_user_formats32, get_string_var(STATUS_USER32_VAR));
1062 	malloc_strcpy(&tmp->status_user_formats33, get_string_var(STATUS_USER33_VAR));
1063 	malloc_strcpy(&tmp->status_user_formats34, get_string_var(STATUS_USER34_VAR));
1064 	malloc_strcpy(&tmp->status_user_formats35, get_string_var(STATUS_USER35_VAR));
1065 	malloc_strcpy(&tmp->status_user_formats36, get_string_var(STATUS_USER36_VAR));
1066 	malloc_strcpy(&tmp->status_user_formats37, get_string_var(STATUS_USER37_VAR));
1067 	malloc_strcpy(&tmp->status_user_formats38, get_string_var(STATUS_USER38_VAR));
1068 	malloc_strcpy(&tmp->status_user_formats39, get_string_var(STATUS_USER39_VAR));
1069 	malloc_strcpy(&tmp->status_user_formats4, get_string_var(STATUS_USER4_VAR));
1070 	malloc_strcpy(&tmp->status_user_formats5, get_string_var(STATUS_USER5_VAR));
1071 	malloc_strcpy(&tmp->status_user_formats6, get_string_var(STATUS_USER6_VAR));
1072 	malloc_strcpy(&tmp->status_user_formats7, get_string_var(STATUS_USER7_VAR));
1073 	malloc_strcpy(&tmp->status_user_formats8, get_string_var(STATUS_USER8_VAR));
1074 	malloc_strcpy(&tmp->status_user_formats9, get_string_var(STATUS_USER9_VAR));
1075 	malloc_strcpy(&tmp->status_window, get_string_var(STATUS_WINDOW_VAR));
1076 	win->wset = tmp;
1077 	return tmp;
1078 }
1079 
remove_wsets_for_window(Window * tmp)1080 void remove_wsets_for_window(Window *tmp)
1081 {
1082 	new_free(&tmp->wset->status_channel);
1083 	new_free(&tmp->wset->status_clock);
1084 	new_free(&tmp->wset->status_hold_lines);
1085 	new_free(&tmp->wset->status_hold);
1086 	new_free(&tmp->wset->status_voice);
1087 	new_free(&tmp->wset->status_dcccount);
1088 	new_free(&tmp->wset->status_cdcccount);
1089 	new_free(&tmp->wset->status_lag);
1090 	new_free(&tmp->wset->status_away);
1091 	new_free(&tmp->wset->status_nick);
1092 	new_free(&tmp->wset->status_flag);
1093 	new_free(&tmp->wset->status_mail);
1094 	new_free(&tmp->wset->status_msgcount);
1095 	new_free(&tmp->wset->status_cpu_saver);
1096 	new_free(&tmp->wset->status_chanop);
1097 	new_free(&tmp->wset->status_mode);
1098 
1099 	new_free(&tmp->wset->status_notify);
1100 	new_free(&tmp->wset->status_oper_kills);
1101 	new_free(&tmp->wset->status_query);
1102 	new_free(&tmp->wset->status_server);
1103 	new_free(&tmp->wset->status_topic);
1104 	new_free(&tmp->wset->status_umode);
1105 	new_free(&tmp->wset->status_users);
1106 	new_free(&tmp->wset->status_scrollback);
1107 	new_free(&tmp->wset->status_halfop);
1108 
1109 	new_free(&tmp->wset->status_user_formats1);
1110 	new_free(&tmp->wset->status_user_formats10);
1111 	new_free(&tmp->wset->status_user_formats11);
1112 	new_free(&tmp->wset->status_user_formats12);
1113 	new_free(&tmp->wset->status_user_formats13);
1114 	new_free(&tmp->wset->status_user_formats14);
1115 	new_free(&tmp->wset->status_user_formats15);
1116 	new_free(&tmp->wset->status_user_formats16);
1117 	new_free(&tmp->wset->status_user_formats17);
1118 	new_free(&tmp->wset->status_user_formats18);
1119 	new_free(&tmp->wset->status_user_formats19);
1120 	new_free(&tmp->wset->status_user_formats2);
1121 	new_free(&tmp->wset->status_user_formats20);
1122 	new_free(&tmp->wset->status_user_formats21);
1123 	new_free(&tmp->wset->status_user_formats22);
1124 	new_free(&tmp->wset->status_user_formats23);
1125 	new_free(&tmp->wset->status_user_formats24);
1126 	new_free(&tmp->wset->status_user_formats25);
1127 	new_free(&tmp->wset->status_user_formats26);
1128 	new_free(&tmp->wset->status_user_formats27);
1129 	new_free(&tmp->wset->status_user_formats28);
1130 	new_free(&tmp->wset->status_user_formats29);
1131 	new_free(&tmp->wset->status_user_formats3);
1132 	new_free(&tmp->wset->status_user_formats30);
1133 	new_free(&tmp->wset->status_user_formats31);
1134 	new_free(&tmp->wset->status_user_formats32);
1135 	new_free(&tmp->wset->status_user_formats33);
1136 	new_free(&tmp->wset->status_user_formats34);
1137 	new_free(&tmp->wset->status_user_formats35);
1138 	new_free(&tmp->wset->status_user_formats36);
1139 	new_free(&tmp->wset->status_user_formats37);
1140 	new_free(&tmp->wset->status_user_formats38);
1141 	new_free(&tmp->wset->status_user_formats39);
1142 	new_free(&tmp->wset->status_user_formats4);
1143 	new_free(&tmp->wset->status_user_formats5);
1144 	new_free(&tmp->wset->status_user_formats6);
1145 	new_free(&tmp->wset->status_user_formats7);
1146 	new_free(&tmp->wset->status_user_formats8);
1147 	new_free(&tmp->wset->status_user_formats9);
1148 	new_free(&tmp->wset->status_user_formats0);
1149 
1150 	new_free(&tmp->wset->format_status[0]);
1151 	new_free(&tmp->wset->format_status[1]);
1152 	new_free(&tmp->wset->format_status[2]);
1153 	new_free(&tmp->wset->format_status[3]);
1154 
1155 	new_free(&tmp->wset->status_format[0]);
1156 	new_free(&tmp->wset->status_format[1]);
1157 	new_free(&tmp->wset->status_format[2]);
1158 	new_free(&tmp->wset->status_format[3]);
1159 	new_free(&tmp->wset->status_line[0]);
1160 	new_free(&tmp->wset->status_line[1]);
1161 	new_free(&tmp->wset->status_line[2]);
1162 
1163 	new_free(&tmp->wset->mode_format);
1164 	new_free(&tmp->wset->umode_format);
1165 	new_free(&tmp->wset->topic_format);
1166 	new_free(&tmp->wset->query_format);
1167 	new_free(&tmp->wset->clock_format);
1168 	new_free(&tmp->wset->hold_lines_format);
1169 	new_free(&tmp->wset->channel_format);
1170 	new_free(&tmp->wset->mail_format);
1171 	new_free(&tmp->wset->server_format);
1172 	new_free(&tmp->wset->notify_format);
1173 	new_free(&tmp->wset->kills_format);
1174 	new_free(&tmp->wset->lag_format);
1175 	new_free(&tmp->wset->cpu_saver_format);
1176 	new_free(&tmp->wset->msgcount_format);
1177 	new_free(&tmp->wset->dcccount_format);
1178 	new_free(&tmp->wset->cdcc_format);
1179 	new_free(&tmp->wset->nick_format);
1180 	new_free(&tmp->wset->away_format);
1181 	new_free(&tmp->wset->flag_format);
1182 	new_free(&tmp->wset->status_users_format);
1183 	new_free(&tmp->wset->status_window);
1184 	new_free(&tmp->wset->window_special_format);
1185 	new_free(&tmp->wset);
1186 }
1187 
log_channel(CSetArray * var,CSetList * cs)1188 void log_channel(CSetArray *var, CSetList *cs)
1189 {
1190 	ChannelList *chan;
1191 	if (!cs->channel_log_file)
1192 	{
1193 		bitchsay("Try setting a channel log file first");
1194 		set_cset_int_var(cs, CHANNEL_LOG_CSET, 0);
1195 		return;
1196 	}
1197 	if ((chan = lookup_channel(cs->channel, from_server, 0)))
1198 		do_log(cs->channel_log, cs->channel_log_file, &chan->msglog_fp);
1199 }
1200 
set_msglog_channel_level(CSetArray * var,CSetList * cs)1201 void set_msglog_channel_level(CSetArray *var, CSetList *cs)
1202 {
1203 	cs->channel_log_level = parse_lastlog_level(cs->log_level, 1);
1204 	set_cset_str_var(cs, CHANNEL_LOG_LEVEL_CSET, bits_to_lastlog_level(cs->channel_log_level));
1205 }
1206 
do_logchannel(unsigned long level,ChannelList * chan,char * format,...)1207 void do_logchannel(unsigned long level, ChannelList *chan, char *format, ...)
1208 {
1209 	if (!chan || !get_cset_int_var(chan->csets, CHANNEL_LOG_CSET))
1210 		return;
1211 	if ((chan->csets->channel_log_level & level) && format)
1212 	{
1213 		char s[BIG_BUFFER_SIZE+1];
1214 		va_list args;
1215 		va_start(args, format);
1216 		vsnprintf(s, BIG_BUFFER_SIZE, format, args);
1217 		va_end(args);
1218 		add_to_log(chan->msglog_fp, now, s, logfile_line_mangler);
1219 	}
1220 }
1221 
set_channel_limit(ChannelList * channel,int currentlimit,int add,int numusers)1222 void set_channel_limit(ChannelList *channel, int currentlimit, int add, int numusers)
1223 {
1224 	if ((now - channel->limit_time) < 30)
1225 		return;
1226 	if (add && numusers)
1227 	{
1228 		if ((currentlimit - numusers) < (add / 2) && ((numusers + add) != currentlimit))
1229 			my_send_to_server(channel->server, "MODE %s +l %d", channel->channel, numusers + add);
1230 		else if ((currentlimit - numusers) > (currentlimit + (add / 2)) && ((numusers + add) != currentlimit))
1231 			my_send_to_server(channel->server, "MODE %s +l %d", channel->channel, numusers + add);
1232 	}
1233 	else
1234 		my_send_to_server(channel->server, "MODE %s -l", channel->channel);
1235 	channel->limit_time = now;
1236 }
1237 
check_channel_limit(ChannelList * chan)1238 void check_channel_limit(ChannelList *chan)
1239 {
1240 	if (chan && chan->csets && chan->csets->set_auto_limit && chan->have_op)
1241 	{
1242 		int count = 0;
1243 		NickList *nick;
1244 		for (nick = next_nicklist(chan, NULL); nick; nick = next_nicklist(chan, nick))
1245 			count++;
1246 		set_channel_limit(chan, chan->limit, chan->csets->set_auto_limit, count);
1247 	}
1248 }
1249 
limit_channel(CSetArray * var,CSetList * cs)1250 void limit_channel(CSetArray *var, CSetList *cs)
1251 {
1252 ChannelList *chan;
1253 	if ((chan = lookup_channel(cs->channel, from_server, 0)))
1254 	{
1255 		if (cs->set_auto_limit)
1256 		{
1257 			int count = 0;
1258 			NickList *nick;
1259 			for (nick = next_nicklist(chan, NULL); nick; nick = next_nicklist(chan, nick))
1260 				count++;
1261 			set_channel_limit(chan, chan->limit, cs->set_auto_limit, count);
1262 		} else
1263 			set_channel_limit(chan, chan->limit, 0, 0);
1264 	}
1265 }
1266 
1267 #ifdef GUI
return_cset_var(int nummer)1268 CSetArray *return_cset_var(int nummer)
1269 {
1270    return &cset_array[nummer];
1271 }
1272 
return_wset_var(int nummer)1273 WSetArray *return_wset_var(int nummer)
1274 {
1275    return &wset_array[nummer];
1276 }
1277 #endif
1278 
1279