1 /*
2  * vars.c: All the dealing of the irc variables are handled here.
3  *
4  * Written By Michael Sandrof
5  *
6  * Copyright (c) 1990 Michael Sandrof.
7  * Copyright (c) 1991, 1992 Troy Rollo.
8  * Copyright (c) 1992-2017 Matthew R. Green.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include "irc.h"
36 IRCII_RCSID("@(#)$eterna: vars.c,v 1.108 2019/01/16 06:27:37 mrg Exp $");
37 
38 #include "status.h"
39 #include "window.h"
40 #include "lastlog.h"
41 #include "log.h"
42 #include "irccrypt.h"
43 #include "history.h"
44 #include "notify.h"
45 #include "vars.h"
46 #include "input.h"
47 #include "ircaux.h"
48 #include "whois.h"
49 #include "ircterm.h"
50 #include "translat.h"
51 #include "output.h"
52 #include "server.h"
53 #include "dcc.h"
54 #include "ssl.h"
55 
56 #define	VF_NODAEMON	0x0001
57 #define VF_EXPAND_PATH	0x0002
58 
59 #define VIF_CHANGED	0x01
60 #define VIF_GLOBAL	0x02
61 
62 /* the types of IrcVariables */
63 #define BOOL_TYPE_VAR 0
64 #define CHAR_TYPE_VAR 1
65 #define INT_TYPE_VAR 2
66 #define STR_TYPE_VAR 3
67 
68 static	void	check_variable_order(void);
69 static	int	find_variable(u_char *, int *);
70 static	void	exec_warning(int);
71 static	void	input_warning(int);
72 static	void	eight_bit_characters(int);
73 static	void	v_update_all_status(int);
74 
75 /* IrcVariable: structure for each variable in the variable table */
76 typedef struct
77 {
78 	char	*name;			/* what the user types */
79 	int	type;			/* variable types, see below */
80 	int	integer;		/* int value of variable */
81 	u_char	*string;		/* string value of variable */
82 					/* function to call every time variable is set */
83 	void	(*ifunc)(int);
84 	void	(*sfunc)(u_char *);
85 	unsigned short	int_flags;	/* internal flags to the variable */
86 	unsigned short	flags;		/* flags for this variable */
87 }	IrcVariable;
88 
89 /*
90  * irc_variable: all the irc variables used.  Note that the integer and
91  * boolean defaults are set here, which the string default value are set in
92  * the init_variables() procedure.
93  *
94  * this structure needs to be in alphabetical order, and the
95  * check_variable_order() procedure will assert that it is from
96  * init_variables()
97  */
98 static	IrcVariable irc_variable[] =
99 {
100 	{ "ALWAYS_SPLIT_BIGGEST",	BOOL_TYPE_VAR,	DEFAULT_ALWAYS_SPLIT_BIGGEST,		NULL, 0, NULL,				0, 0 },
101 	{ "AUTO_UNMARK_AWAY",		BOOL_TYPE_VAR,	DEFAULT_AUTO_UNMARK_AWAY,		NULL, 0, NULL,				0, 0 },
102 	{ "AUTO_WHOWAS",		BOOL_TYPE_VAR,	DEFAULT_AUTO_WHOWAS,			NULL, 0, NULL,				0, 0 },
103 	{ "BACKGROUND_COLOUR",		INT_TYPE_VAR,	DEFAULT_BACKGROUND_COLOUR,		NULL, 0, NULL,				0, 0 },
104 	{ "BEEP",			BOOL_TYPE_VAR,	DEFAULT_BEEP,				NULL, 0, NULL,				0, 0 },
105 	{ "BEEP_MAX",			INT_TYPE_VAR,	DEFAULT_BEEP_MAX,			NULL, 0, NULL,				0, 0 },
106 	{ "BEEP_ON_MSG",		STR_TYPE_VAR,	0,					NULL, 0, set_beep_on_msg,		0, 0 },
107 	{ "BEEP_WHEN_AWAY",		INT_TYPE_VAR,	DEFAULT_BEEP_WHEN_AWAY,			NULL, 0, NULL,				0, 0 },
108 	{ "BIND_LOCAL_DCCHOST",		BOOL_TYPE_VAR,	DEFAULT_BIND_LOCAL_DCCHOST,		NULL, 0, NULL,				0, 0 },
109 	{ "BOLD_VIDEO",			BOOL_TYPE_VAR,	DEFAULT_BOLD_VIDEO,			NULL, 0, NULL,				0, 0 },
110 	{ "CHANNEL_NAME_WIDTH",		INT_TYPE_VAR,	DEFAULT_CHANNEL_NAME_WIDTH,		NULL, v_update_all_status, 0,		0, 0 },
111 	{ "CLIENT_INFORMATION",		STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, 0 },
112 	{ "CLOCK",			BOOL_TYPE_VAR,	DEFAULT_CLOCK,				NULL, v_update_all_status, 0,		0, 0 },
113 	{ "CLOCK_24HOUR",		BOOL_TYPE_VAR,	DEFAULT_CLOCK_24HOUR,			NULL, reset_clock, 0,			0, 0 },
114 	{ "CLOCK_ALARM",		STR_TYPE_VAR,	0,					NULL, 0, set_alarm,			0, 0 },
115 	{ "CMDCHARS",			STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, 0 },
116 	{ "COLOUR",			BOOL_TYPE_VAR,	DEFAULT_COLOUR,				NULL, 0, NULL,				0, 0 },
117 	{ "COMMAND_MODE",		BOOL_TYPE_VAR,	DEFAULT_COMMAND_MODE,			NULL, 0, NULL,				0, 0 },
118 	{ "CONTINUED_LINE",		STR_TYPE_VAR,	0,					NULL, 0, set_continued_line,		0, 0 },
119 	{ "CTCP_REPLY_BACKLOG_SECONDS",	INT_TYPE_VAR,	DEFAULT_CTCP_REPLY_BACKLOG_SECONDS,	NULL, ctcp_reply_backlog_change, 0,	0, 0 },
120 	{ "CTCP_REPLY_FLOOD_SIZE",	INT_TYPE_VAR,	DEFAULT_CTCP_REPLY_FLOOD_SIZE_VAR,	NULL, 0, NULL,				0, 0 },
121 	{ "CTCP_REPLY_IGNORE_SECONDS",	INT_TYPE_VAR,	DEFAULT_CTCP_REPLY_IGNORE_SECONDS,	NULL, 0, NULL,				0, 0 },
122 	{ "DCCHOST",			STR_TYPE_VAR,	0,					NULL, 0, set_dcchost,			0, 0 },
123 	{ "DCCPORT",			INT_TYPE_VAR,	DEFAULT_DCCPORT,			NULL, 0, NULL,				0, 0 },
124 	{ "DCC_BLOCK_SIZE",		INT_TYPE_VAR,	DEFAULT_DCC_BLOCK_SIZE,			NULL, 0, NULL,				0, 0 },
125 	{ "DEBUG",			INT_TYPE_VAR,	0,					NULL, 0, NULL,				0, 0 },
126 	{ "DECRYPT_PROGRAM",		STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, VF_NODAEMON },
127 	{ "DISPLAY",			BOOL_TYPE_VAR,	DEFAULT_DISPLAY,			NULL, 0, NULL,				0, 0 },
128 	{ "DISPLAY_ENCODING",		STR_TYPE_VAR,	0,					NULL, 0, set_display_encoding,			0, 0 },
129 	{ "EIGHT_BIT_CHARACTERS",	BOOL_TYPE_VAR,	DEFAULT_EIGHT_BIT_CHARACTERS,		NULL, eight_bit_characters, 0,		0, 0 },
130 	{ "ENCRYPT_PROGRAM",		STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, VF_NODAEMON },
131 	{ "EXEC_PROTECTION",		BOOL_TYPE_VAR,	DEFAULT_EXEC_PROTECTION,		NULL, exec_warning, 0,			0, VF_NODAEMON },
132 	{ "FLOOD_AFTER",		INT_TYPE_VAR,	DEFAULT_FLOOD_AFTER,			NULL, 0, NULL,				0, 0 },
133 	{ "FLOOD_RATE",			INT_TYPE_VAR,	DEFAULT_FLOOD_RATE,			NULL, 0, NULL,				0, 0 },
134 	{ "FLOOD_USERS",		INT_TYPE_VAR,	DEFAULT_FLOOD_USERS,			NULL, 0, NULL,				0, 0 },
135 	{ "FLOOD_WARNING",		BOOL_TYPE_VAR,	DEFAULT_FLOOD_WARNING,			NULL, 0, NULL,				0, 0 },
136 	{ "FOREGROUND_COLOUR",		INT_TYPE_VAR,	DEFAULT_FOREGROUND_COLOUR,		NULL, 0, NULL,				0, 0 },
137 	{ "FULL_STATUS_LINE",		BOOL_TYPE_VAR,	DEFAULT_FULL_STATUS_LINE,		NULL, v_update_all_status, 0,		0, 0 },
138 	{ "HELP_PAGER",			BOOL_TYPE_VAR,	DEFAULT_HELP_PAGER,			NULL, 0, NULL,				0, 0 },
139 	{ "HELP_PATH",			STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, VF_EXPAND_PATH|VF_NODAEMON },
140 	{ "HELP_PROMPT",		BOOL_TYPE_VAR,	DEFAULT_HELP_PROMPT,			NULL, 0, NULL,				0, 0 },
141 	{ "HELP_WINDOW",		BOOL_TYPE_VAR,	DEFAULT_HELP_WINDOW,			NULL, 0, NULL,				0, 0 },
142 	{ "HIDE_CHANNEL_KEYS",		BOOL_TYPE_VAR,	DEFAULT_HIDE_CHANNEL_KEYS,		NULL, v_update_all_status, 0,		0, 0 },
143 	{ "HIDE_PRIVATE_CHANNELS",	BOOL_TYPE_VAR,	DEFAULT_HIDE_PRIVATE_CHANNELS,		NULL, v_update_all_status, 0,		0, 0 },
144 	{ "HIGHLIGHT_CHAR",		STR_TYPE_VAR,	0,					NULL, 0, set_highlight_char,		0, 0 },
145 	{ "HISTORY",			INT_TYPE_VAR,	DEFAULT_HISTORY,			NULL, set_history_size, 0,		0, VF_NODAEMON },
146 	{ "HISTORY_FILE",		STR_TYPE_VAR,	0,					NULL, 0, set_history_file,		0, 0 },
147 	{ "HOLD_MODE",			BOOL_TYPE_VAR,	DEFAULT_HOLD_MODE,			NULL, reset_line_cnt, 0,		0, 0 },
148 	{ "HOLD_MODE_MAX",		INT_TYPE_VAR,	DEFAULT_HOLD_MODE_MAX,			NULL, 0, NULL,				0, 0 },
149 	{ "INDENT",			BOOL_TYPE_VAR,	DEFAULT_INDENT,				NULL, 0, NULL,				0, 0 },
150 	{ "INPUT_ALIASES",		BOOL_TYPE_VAR,	DEFAULT_INPUT_ALIASES,			NULL, 0, NULL,				0, 0 },
151 	{ "INPUT_ENCODING",		STR_TYPE_VAR,	0,					NULL, 0, set_input_encoding,			0, 0 },
152 	{ "INPUT_PROMPT",		STR_TYPE_VAR,	0,					NULL, 0, set_input_prompt,		0, 0 },
153 	{ "INPUT_PROTECTION",		BOOL_TYPE_VAR,	DEFAULT_INPUT_PROTECTION,		NULL, input_warning, 0,			0, 0 },
154 	{ "INSERT_MODE",		BOOL_TYPE_VAR,	DEFAULT_INSERT_MODE,			NULL, v_update_all_status, 0,		0, 0 },
155 	{ "INVERSE_VIDEO",		BOOL_TYPE_VAR,	DEFAULT_INVERSE_VIDEO,			NULL, 0, NULL,				0, 0 },
156 	{ "IRCHOST",			STR_TYPE_VAR,	0,					NULL, 0, set_irchost,			0, 0 },
157 	{ "IRC_ENCODING",		STR_TYPE_VAR,	0,					NULL, 0, set_irc_encoding,			0, 0 },
158 	{ "LASTLOG",			INT_TYPE_VAR,	DEFAULT_LASTLOG,			NULL, set_lastlog_size, 0,		0, 0 },
159 	{ "LASTLOG_LEVEL",		STR_TYPE_VAR,	0,					NULL, 0, set_lastlog_level,		0, 0 },
160 	{ "LOAD_PATH",			STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, VF_NODAEMON },
161 	{ "LOG",			BOOL_TYPE_VAR,	DEFAULT_LOG,				NULL, logger, 0,			0, 0 },
162 	{ "LOGFILE",			STR_TYPE_VAR,	0,					NULL, 0, set_log_file,			0, VF_NODAEMON },
163 	{ "MAIL",			INT_TYPE_VAR,	DEFAULT_MAIL,				NULL, v_update_all_status, 0,		0, VF_NODAEMON },
164 	{ "MAKE_NOTICE_MSG",		BOOL_TYPE_VAR,	DEFAULT_MAKE_NOTICE_MSG,		NULL, 0, NULL,				0, 0},
165 	{ "MAX_RECURSIONS",		INT_TYPE_VAR,	DEFAULT_MAX_RECURSIONS,			NULL, 0, NULL,				0, 0 },
166 	{ "MENU",			STR_TYPE_VAR,	0,					NULL, 0, set_menu,			0, 0 },
167 	{ "MINIMUM_SERVERS",		INT_TYPE_VAR,	DEFAULT_MINIMUM_SERVERS,		NULL, 0, NULL,				0, VF_NODAEMON },
168 	{ "MINIMUM_USERS",		INT_TYPE_VAR,	DEFAULT_MINIMUM_USERS,			NULL, 0, NULL,				0, VF_NODAEMON },
169 	{ "NOTIFY_HANDLER",		STR_TYPE_VAR, 	0,					NULL, 0, set_notify_handler,		0, 0 },
170 	{ "NOTIFY_LEVEL",		STR_TYPE_VAR,	0,					NULL, 0, set_notify_level,		0, 0 },
171 	{ "NOTIFY_ON_TERMINATION",	BOOL_TYPE_VAR,	DEFAULT_NOTIFY_ON_TERMINATION,		NULL, 0, NULL,				0, VF_NODAEMON },
172 	{ "NOVICE",			BOOL_TYPE_VAR,	DEFAULT_NOVICE,				NULL, 0, NULL,				0, 0 },
173 	{ "NO_ASK_NICKNAME",		BOOL_TYPE_VAR,	DEFAULT_NO_ASK_NICKNAME,		NULL, 0, NULL,				0, 0 },
174 	{ "NO_CTCP_FLOOD",		BOOL_TYPE_VAR,	DEFAULT_NO_CTCP_FLOOD,			NULL, 0, NULL,				0, 0 },
175 	{ "OLD_ENCRYPT_PROGRAM",	BOOL_TYPE_VAR,	0,					NULL, 0, NULL,				0, VF_NODAEMON },
176 	{ "REALNAME",			STR_TYPE_VAR,	0,					NULL, 0, set_realname,			0, VF_NODAEMON },
177 	{ "SAME_WINDOW_ONLY",		BOOL_TYPE_VAR,	DEFAULT_SAME_WINDOW_ONLY,		NULL, 0, NULL,				0, 0 },
178 	{ "SCREEN_OPTIONS", 		STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, VF_NODAEMON },
179 	{ "SCROLL",			BOOL_TYPE_VAR,	DEFAULT_SCROLL,				NULL, set_scroll, 0,			0, 0 },
180 	{ "SCROLL_LINES",		INT_TYPE_VAR,	DEFAULT_SCROLL_LINES,			NULL, set_scroll_lines, 0,		0, 0 },
181 	{ "SEND_IGNORE_MSG",		BOOL_TYPE_VAR,	DEFAULT_SEND_IGNORE_MSG,		NULL, 0, NULL,				0, 0 },
182 	{ "SHELL",			STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, VF_NODAEMON },
183 	{ "SHELL_FLAGS",		STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, VF_NODAEMON },
184 	{ "SHELL_LIMIT",		INT_TYPE_VAR,	DEFAULT_SHELL_LIMIT,			NULL, 0, NULL,				0, VF_NODAEMON },
185 	{ "SHOW_AWAY_ONCE",		BOOL_TYPE_VAR,	DEFAULT_SHOW_AWAY_ONCE,			NULL, 0, NULL,				0, 0 },
186 	{ "SHOW_CHANNEL_NAMES",		BOOL_TYPE_VAR,	DEFAULT_SHOW_CHANNEL_NAMES,		NULL, 0, NULL,				0, 0 },
187 	{ "SHOW_END_OF_MSGS",		BOOL_TYPE_VAR,	DEFAULT_SHOW_END_OF_MSGS,		NULL, 0, NULL,				0, 0 },
188 	{ "SHOW_NUMERICS",		BOOL_TYPE_VAR,	DEFAULT_SHOW_NUMERICS,			NULL, 0, NULL,				0, 0 },
189 	{ "SHOW_STARS",			BOOL_TYPE_VAR,	1,					NULL, 0, NULL,				0, 0 },
190 	{ "SHOW_STATUS_ALL",		BOOL_TYPE_VAR,	DEFAULT_SHOW_STATUS_ALL,		NULL, v_update_all_status, 0,		0, 0 },
191 	{ "SHOW_WHO_HOPCOUNT", 		BOOL_TYPE_VAR,	DEFAULT_SHOW_WHO_HOPCOUNT,		NULL, 0, NULL,				0, 0 },
192 	{ "SSL_CA_CHAIN_FILE", 		STR_TYPE_VAR,	0,					NULL, 0, ssl_setup_certs,		0, VF_NODAEMON },
193 	{ "SSL_CA_FILE", 		STR_TYPE_VAR,	0,					NULL, 0, ssl_setup_certs,		0, VF_NODAEMON },
194 	{ "SSL_CA_PATH", 		STR_TYPE_VAR,	0,					NULL, 0, ssl_setup_certs,		0, VF_NODAEMON },
195 	{ "SSL_CA_PRIVATE_KEY_FILE", 	STR_TYPE_VAR,	0,					NULL, 0, ssl_setup_certs,		0, VF_NODAEMON },
196 	{ "STAR_PREFIX",		STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, 0 },
197 	{ "STATUS_AWAY",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
198 	{ "STATUS_CHANNEL",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
199 	{ "STATUS_CHANOP",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
200 	{ "STATUS_CLOCK",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
201 	{ "STATUS_FORMAT",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
202 	{ "STATUS_FORMAT1",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
203 	{ "STATUS_FORMAT2",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
204 	{ "STATUS_GROUP",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
205 	{ "STATUS_HOLD",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
206 	{ "STATUS_HOLD_LINES",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
207 	{ "STATUS_INSERT",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
208 	{ "STATUS_MAIL",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, VF_NODAEMON },
209 	{ "STATUS_MODE",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
210 	{ "STATUS_NOTIFY",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
211 	{ "STATUS_OPER",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
212 	{ "STATUS_OVERWRITE",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
213 	{ "STATUS_QUERY",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
214 	{ "STATUS_SCROLLED",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
215 	{ "STATUS_SCROLLED_LINES",	STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
216 	{ "STATUS_SERVER",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
217 	{ "STATUS_UMODE",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
218 	{ "STATUS_USER",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
219 	{ "STATUS_USER1",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
220 	{ "STATUS_USER2",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
221 	{ "STATUS_USER3",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
222 	{ "STATUS_VOICE",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
223 	{ "STATUS_WINDOW",		STR_TYPE_VAR,	0,					NULL, 0, build_status,			0, 0 },
224 	{ "SUPPRESS_SERVER_MOTD",	BOOL_TYPE_VAR,	DEFAULT_SUPPRESS_SERVER_MOTD,		NULL, 0, NULL,				0, VF_NODAEMON },
225 	{ "SWITCH_TO_QUIET_CHANNELS",	BOOL_TYPE_VAR,	DEFAULT_SWITCH_TO_QUIET_CHANNELS,	NULL, 0, NULL,				0, VF_NODAEMON },
226 	{ "TAB",			BOOL_TYPE_VAR,	DEFAULT_TAB,				NULL, 0, NULL,				0, 0 },
227 	{ "TAB_MAX",			INT_TYPE_VAR,	DEFAULT_TAB_MAX,			NULL, 0, NULL,				0, 0 },
228 	{ "UNDERLINE_VIDEO",		BOOL_TYPE_VAR,	DEFAULT_UNDERLINE_VIDEO,		NULL, 0, NULL,				0, 0 },
229 	{ "USER_INFORMATION", 		STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, 0 },
230 	{ "USER_WALLOPS",		BOOL_TYPE_VAR,	DEFAULT_USER_WALLOPS,			NULL, 0, NULL,				0, 0 },
231 	{ "VERBOSE_CTCP",		BOOL_TYPE_VAR,	DEFAULT_VERBOSE_CTCP,			NULL, 0, NULL,				0, 0 },
232 	{ "WARN_OF_IGNORES",		BOOL_TYPE_VAR,	DEFAULT_WARN_OF_IGNORES,		NULL, 0, NULL,				0, 0 },
233 	{ "WSERV_PATH",			STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, 0 },
234 	{ "XTERM_GEOMOPTSTR", 		STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, VF_NODAEMON },
235 	{ "XTERM_OPTIONS", 		STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, VF_NODAEMON },
236 	{ "XTERM_PATH", 		STR_TYPE_VAR,	0,					NULL, 0, NULL,				0, VF_NODAEMON },
237 	{ NULL,				0,		0,					NULL, 0, NULL,				0, 0 }
238 };
239 
240 /*
241  * init_variables: initializes the string variables that can't really be
242  * initialized properly above
243  */
244 void
init_variables(void)245 init_variables(void)
246 {
247 	check_variable_order();
248 
249 	set_string_var(CMDCHARS_VAR, UP(DEFAULT_CMDCHARS));
250 	set_string_var(LOGFILE_VAR, UP(DEFAULT_LOGFILE));
251 	set_string_var(SHELL_VAR, UP(DEFAULT_SHELL));
252 	set_string_var(SHELL_FLAGS_VAR, UP(DEFAULT_SHELL_FLAGS));
253 	set_string_var(DECRYPT_PROGRAM_VAR, UP(DEFAULT_DECRYPT_PROGRAM));
254 	set_string_var(DISPLAY_ENCODING_VAR, UP(DEFAULT_DISPLAY_ENCODING));
255 	set_string_var(ENCRYPT_PROGRAM_VAR, UP(DEFAULT_ENCRYPT_PROGRAM));
256 	set_string_var(CONTINUED_LINE_VAR, UP(DEFAULT_CONTINUED_LINE));
257 	set_string_var(INPUT_ENCODING_VAR, UP(DEFAULT_INPUT_ENCODING));
258 	set_string_var(INPUT_PROMPT_VAR, UP(DEFAULT_INPUT_PROMPT));
259 	set_string_var(IRC_ENCODING_VAR, UP(DEFAULT_IRC_ENCODING));
260 	set_string_var(HIGHLIGHT_CHAR_VAR, UP(DEFAULT_HIGHLIGHT_CHAR));
261 	set_string_var(HISTORY_FILE_VAR, UP(DEFAULT_HISTORY_FILE));
262 	set_string_var(LASTLOG_LEVEL_VAR, UP(DEFAULT_LASTLOG_LEVEL));
263 	set_string_var(NOTIFY_HANDLER_VAR, UP(DEFAULT_NOTIFY_HANDLER));
264 	set_string_var(NOTIFY_LEVEL_VAR, UP(DEFAULT_NOTIFY_LEVEL));
265 	set_string_var(REALNAME_VAR, my_realname());
266 	set_string_var(SSL_CA_CHAIN_FILE_VAR, UP(DEFAULT_SSL_CA_CHAIN_FILE));
267 	set_string_var(SSL_CA_FILE_VAR, UP(DEFAULT_SSL_CA_FILE));
268 	set_string_var(SSL_CA_PATH_VAR, UP(DEFAULT_SSL_CA_PATH));
269 	set_string_var(SSL_CA_PRIVATE_KEY_FILE_VAR, UP(DEFAULT_SSL_CA_PRIVATE_KEY_FILE));
270 	set_string_var(STAR_PREFIX_VAR, UP(DEFAULT_STAR_PREFIX));
271 	set_string_var(STATUS_FORMAT_VAR, UP(DEFAULT_STATUS_FORMAT));
272 	set_string_var(STATUS_FORMAT1_VAR, UP(DEFAULT_STATUS_FORMAT1));
273 	set_string_var(STATUS_FORMAT2_VAR, UP(DEFAULT_STATUS_FORMAT2));
274 	set_string_var(STATUS_AWAY_VAR, UP(DEFAULT_STATUS_AWAY));
275 	set_string_var(STATUS_CHANNEL_VAR, UP(DEFAULT_STATUS_CHANNEL));
276 	set_string_var(STATUS_CHANOP_VAR, UP(DEFAULT_STATUS_CHANOP));
277 	set_string_var(STATUS_CLOCK_VAR, UP(DEFAULT_STATUS_CLOCK));
278 	set_string_var(STATUS_GROUP_VAR, UP(DEFAULT_STATUS_GROUP));
279 	set_string_var(STATUS_HOLD_VAR, UP(DEFAULT_STATUS_HOLD));
280 	set_string_var(STATUS_HOLD_LINES_VAR, UP(DEFAULT_STATUS_HOLD_LINES));
281 	set_string_var(STATUS_INSERT_VAR, UP(DEFAULT_STATUS_INSERT));
282 	set_string_var(STATUS_MAIL_VAR, UP(DEFAULT_STATUS_MAIL));
283 	set_string_var(STATUS_MODE_VAR, UP(DEFAULT_STATUS_MODE));
284 	set_string_var(STATUS_OPER_VAR, UP(DEFAULT_STATUS_OPER));
285 	set_string_var(STATUS_OVERWRITE_VAR, UP(DEFAULT_STATUS_OVERWRITE));
286 	set_string_var(STATUS_QUERY_VAR, UP(DEFAULT_STATUS_QUERY));
287 	set_string_var(STATUS_SCROLLED_VAR, UP(DEFAULT_STATUS_SCROLLED));
288 	set_string_var(STATUS_SCROLLED_LINES_VAR, UP(DEFAULT_STATUS_SCROLLED_LINES));
289 	set_string_var(STATUS_SERVER_VAR, UP(DEFAULT_STATUS_SERVER));
290 	set_string_var(STATUS_UMODE_VAR, UP(DEFAULT_STATUS_UMODE));
291 	set_string_var(STATUS_USER_VAR, UP(DEFAULT_STATUS_USER));
292 	set_string_var(STATUS_USER1_VAR, UP(DEFAULT_STATUS_USER1));
293 	set_string_var(STATUS_USER2_VAR, UP(DEFAULT_STATUS_USER2));
294 	set_string_var(STATUS_USER3_VAR, UP(DEFAULT_STATUS_USER3));
295 	set_string_var(STATUS_WINDOW_VAR, UP(DEFAULT_STATUS_WINDOW));
296 	set_string_var(USER_INFO_VAR, UP(DEFAULT_USERINFO));
297 #ifdef WSERV_PATH
298 	set_string_var(WSERV_PATH_VAR, UP(WSERV_PATH));
299 #else
300 	set_string_var(WSERV_PATH_VAR, UP(DEFAULT_WSERV_PATH));
301 #endif
302 	set_string_var(XTERM_GEOMOPTSTR_VAR, UP(DEFAULT_XTERM_GEOMOPTSTR));
303 	set_string_var(XTERM_OPTIONS_VAR, UP(DEFAULT_XTERM_OPTIONS));
304 	set_string_var(XTERM_PATH_VAR, UP(DEFAULT_XTERM_PATH));
305 	set_alarm(DEFAULT_CLOCK_ALARM);
306 	set_beep_on_msg(UP(DEFAULT_BEEP_ON_MSG));
307 	set_string_var(STATUS_NOTIFY_VAR, UP(DEFAULT_STATUS_NOTIFY));
308 	set_string_var(CLIENTINFO_VAR, UP(IRCII_COMMENT));
309 	set_string_var(IRCHOST_VAR, get_irchost());
310 	set_string_var(DCCHOST_VAR, get_dcchost());
311 #ifdef HAVE_ICONV_OPEN
312 	set_irc_encoding(UP(irc_variable[IRC_ENCODING_VAR].string));
313 	set_input_encoding(UP(irc_variable[INPUT_ENCODING_VAR].string));
314 	set_display_encoding(UP(irc_variable[DISPLAY_ENCODING_VAR].string));
315 #endif /* HAVE_ICONV_OPEN */
316 	set_string_var(HELP_PATH_VAR, UP(DEFAULT_HELP_PATH));
317 	set_lastlog_size(irc_variable[LASTLOG_VAR].integer);
318 	set_history_size(irc_variable[HISTORY_VAR].integer);
319 	set_history_file(UP(irc_variable[HISTORY_FILE_VAR].string));
320 	set_highlight_char(UP(irc_variable[HIGHLIGHT_CHAR_VAR].string));
321 	set_lastlog_level(UP(irc_variable[LASTLOG_LEVEL_VAR].string));
322 	set_notify_level(UP(irc_variable[NOTIFY_LEVEL_VAR].string));
323 	if (get_int_var(LOG_VAR))
324 		set_int_var(LOG_VAR, 1);
325 }
326 
327 /*
328  * check_variable_order: make sure irc_variable[] is properly ordered.
329  */
330 static	void
check_variable_order(void)331 check_variable_order(void)
332 {
333 	IrcVariable *curr, *prev = NULL;
334 	size_t	len;
335 
336 	for (curr = irc_variable; curr->name; prev = curr++)
337 		if (prev && (len = my_strlen(prev->name)) && my_strncmp(prev->name, curr->name, len) > 0)
338 		{
339 			yell("irc_variables[] order is wrong at elements \"%s\" and \"%s\"!", prev->name, curr->name);
340 			abort();
341 		}
342 
343 }
344 
345 /*
346  * find_variable: looks up variable name in the variable table and returns
347  * the index into the variable array of the match.  If there is no match, cnt
348  * is set to 0 and -1 is returned.  If more than one match the string, cnt is
349  * set to that number, and it returns the first match.  Index will contain
350  * the index into the array of the first found entry
351  */
352 static	int
find_variable(u_char * org_name,int * cnt)353 find_variable(u_char *org_name, int *cnt)
354 {
355 	IrcVariable *v,
356 		    *first;
357 	size_t	len;
358 	int	var_index;
359 	u_char	*name = NULL;
360 
361 	malloc_strcpy(&name, org_name);
362 	upper(name);
363 	len = my_strlen(name);
364 	var_index = 0;
365 	for (first = irc_variable; first->name; first++, var_index++)
366 
367 	{
368 		if (my_strncmp(name, first->name, len) == 0)
369 		{
370 			*cnt = 1;
371 			break;
372 		}
373 	}
374 	if (first->name)
375 
376 	{
377 		if (my_strlen(first->name) != len)
378 		{
379 			v = first;
380 			for (v++; v->name; v++, (*cnt)++)
381 
382 			{
383 				if (my_strncmp(name, v->name, len) != 0)
384 					break;
385 			}
386 		}
387 		new_free(&name);
388 		return (var_index);
389 	}
390 	else
391 	{
392 		*cnt = 0;
393 		new_free(&name);
394 		return (-1);
395 	}
396 }
397 
398 /*
399  * do_boolean: just a handy thing.  Returns 1 if the str is not ON, OFF, or
400  * TOGGLE
401  */
402 int
do_boolean(u_char * str,int * value)403 do_boolean(u_char *str, int *value)
404 {
405 	upper(str);
406 	if (my_strcmp(str, var_settings(ON)) == 0)
407 		*value = 1;
408 	else if (my_strcmp(str, var_settings(OFF)) == 0)
409 		*value = 0;
410 	else if (my_strcmp(str, var_settings(TOGGLE)) == 0)
411 	{
412 		if (*value)
413 			*value = 0;
414 		else
415 			*value = 1;
416 	}
417 	else
418 		return (1);
419 	return (0);
420 }
421 
422 /*
423  * set_var_value: Given the variable structure and the string representation
424  * of the value, this sets the value in the most verbose and error checking
425  * of manors.  It displays the results of the set and executes the function
426  * defined in the var structure
427  */
428 void
set_var_value(int var_index,u_char * value)429 set_var_value(int var_index, u_char *value)
430 {
431 	u_char	*rest;
432 	IrcVariable *var;
433 	int	old;
434 
435 
436 	var = &(irc_variable[var_index]);
437 #ifdef DAEMON_UID
438 	if (getuid() == DAEMON_UID && var->flags&VF_NODAEMON && value && *value)
439 	{
440 		say("You are not permitted to set that variable");
441 		return;
442 	}
443 #endif /* DAEMON_UID */
444 	switch (var->type)
445 	{
446 	case BOOL_TYPE_VAR:
447 		if (value && *value && (value = next_arg(value, &rest)))
448 		{
449 			old = var->integer;
450 			if (do_boolean(value, &(var->integer)))
451 
452 			{
453 				say("Value must be either ON, OFF, or TOGGLE");
454 				break;
455 			}
456 			if (!(var->int_flags & VIF_CHANGED))
457 			{
458 				if (old != var->integer)
459 					var->int_flags |= VIF_CHANGED;
460 			}
461 			if (loading_global())
462 				var->int_flags |= VIF_GLOBAL;
463 			if (var->ifunc)
464 				(*var->ifunc)(var->integer);
465 			say("Value of %s set to %s", var->name,
466 				var->integer ? var_settings(ON)
467 					     : var_settings(OFF));
468 		}
469 		else
470 			say("Current value of %s is %s", var->name,
471 				(var->integer) ?
472 				var_settings(ON) : var_settings(OFF));
473 		break;
474 	case CHAR_TYPE_VAR:
475 		if (value && *value && (value = next_arg(value, &rest)))
476 		{
477 			if ((int) my_strlen(value) > 1)
478 				say("Value of %s must be a single character",
479 					var->name);
480 			else
481 			{
482 				if (!(var->int_flags & VIF_CHANGED))
483 				{
484 					if (var->integer != *value)
485 						var->int_flags |= VIF_CHANGED;
486 				}
487 				if (loading_global())
488 					var->int_flags |= VIF_GLOBAL;
489 				var->integer = *value;
490 				if (var->ifunc)
491 					(*var->ifunc)(var->integer);
492 				say("Value of %s set to '%c'", var->name,
493 					var->integer);
494 			}
495 		}
496 		else
497 			say("Current value of %s is '%c'", var->name,
498 				var->integer);
499 		break;
500 	case INT_TYPE_VAR:
501 		if (value && *value && (value = next_arg(value, &rest)))
502 		{
503 			int	val;
504 
505 			if (!is_number(value))
506 			{
507 				say("Value of %s must be numeric!", var->name);
508 				break;
509 			}
510 			if ((val = my_atoi(value)) < 0)
511 			{
512 				say("Value of %s must be greater than 0",
513 					var->name);
514 				break;
515 			}
516 			if (!(var->int_flags & VIF_CHANGED))
517 			{
518 				if (var->integer != val)
519 					var->int_flags |= VIF_CHANGED;
520 			}
521 			if (loading_global())
522 				var->int_flags |= VIF_GLOBAL;
523 			var->integer = val;
524 			if (var->ifunc)
525 				(*var->ifunc)(var->integer);
526 			say("Value of %s set to %d", var->name, var->integer);
527 		}
528 		else
529 			say("Current value of %s is %d", var->name,
530 				var->integer);
531 		break;
532 	case STR_TYPE_VAR:
533 		if (value)
534 		{
535 			if (*value)
536 			{
537 				u_char	*temp = NULL;
538 
539 				if (var->flags & VF_EXPAND_PATH)
540 				{
541 					temp = expand_twiddle(value);
542 					value = temp;
543 				}
544 				if (!(var->int_flags & VIF_CHANGED))
545 				{
546 					if ((var->string && ! value) ||
547 					    (! var->string && value) ||
548 					    my_stricmp(var->string, value))
549 						var->int_flags |= VIF_CHANGED;
550 				}
551 				if (loading_global())
552 					var->int_flags |= VIF_GLOBAL;
553 				malloc_strcpy(&var->string, value);
554 				if (temp)
555 					new_free(&temp);
556 			}
557 			else
558 			{
559 				if (var->string)
560 					say("Current value of %s is %s",
561 						var->name, var->string);
562 				else
563 					say("No value for %s has been set",
564 						var->name);
565 				return;
566 			}
567 		}
568 		else
569 			new_free(&var->string);
570 		if (var->sfunc)
571 			(*var->sfunc)(var->string);
572 		say("Value of %s set to %s", var->name, var->string ?
573 			var->string : UP("<EMPTY>"));
574 		break;
575 	}
576 }
577 
578 /*
579  * set_variable: The SET command sets one of the irc variables.  The args
580  * should consist of "variable-name setting", where variable name can be
581  * partial, but non-ambbiguous, and setting depends on the variable being set
582  */
583 void
set_variable(u_char * command,u_char * args,u_char * subargs)584 set_variable(u_char *command, u_char *args, u_char *subargs)
585 {
586 	u_char	*var;
587 	int	cnt,
588 		var_index,
589 		lastlog_level;
590 
591 	if ((var = next_arg(args, &args)) != NULL)
592 	{
593 		if (*var == '-')
594 		{
595 			var++;
596 			args = NULL;
597 		}
598 		var_index = find_variable(var, &cnt);
599 		switch (cnt)
600 		{
601 		case 0:
602 			say("No such variable \"%s\"", var);
603 			return;
604 		case 1:
605 			set_var_value(var_index, args);
606 			return;
607 		default:
608 			say("%s is ambiguous", var);
609 			for (cnt += var_index; var_index < cnt; var_index++)
610 				set_var_value(var_index, empty_string());
611 			return;
612 		}
613 	}
614 	lastlog_level = message_from_level(LOG_CRAP);
615 	for (var_index = 0; var_index < NUMBER_OF_VARIABLES; var_index++)
616 		set_var_value(var_index, empty_string());
617 	(void) message_from_level(lastlog_level);
618 }
619 
620 /*
621  * get_string_var: returns the value of the string variable given as an index
622  * into the variable table.  Does no checking of variable types, etc
623  */
624 u_char	*
get_string_var(int var)625 get_string_var(int var)
626 {
627 	return irc_variable[var].string;
628 }
629 
630 /*
631  * get_int_var: returns the value of the integer string given as an index
632  * into the variable table.  Does no checking of variable types, etc
633  */
634 int
get_int_var(int var)635 get_int_var(int var)
636 {
637 	return (irc_variable[var].integer);
638 }
639 
640 /*
641  * set_string_var: sets the string variable given as an index into the
642  * variable table to the given string.  If string is null, the current value
643  * of the string variable is freed and set to null
644  */
645 void
set_string_var(int var,u_char * string)646 set_string_var(int var, u_char *string)
647 {
648 	if (string)
649 		malloc_strcpy(&irc_variable[var].string, string);
650 	else
651 		new_free(&irc_variable[var].string);
652 }
653 
654 /*
655  * set_int_var: sets the integer value of the variable given as an index into
656  * the variable table to the given value
657  */
658 void
set_int_var(int var,unsigned value)659 set_int_var(int var, unsigned value)
660 {
661 	if (var == NOVICE_VAR && !get_load_depth() && !value)
662 	{
663 say("WARNING: Setting NOVICE to OFF enables commands in your client which");
664 say("         could be used by others on IRC to control your IRC session");
665 say("         or compromise security on your machine. If somebody has");
666 say("         asked you to do this, and you do not know EXACTLY why, or if");
667 say("         you are not ABSOLUTELY sure what you are doing, you should");
668 say("         immediately /SET NOVICE ON and find out more information.");
669 	}
670 	irc_variable[var].integer = value;
671 }
672 
673 /*
674  * save_variables: this writes all of the IRCII variables to the given FILE
675  * pointer in such a way that they can be loaded in using LOAD or the -l switch
676  */
677 void
save_variables(FILE * fp,int do_all)678 save_variables(FILE *fp, int do_all)
679 {
680 	IrcVariable *var;
681 
682 	for (var = irc_variable; var->name; var++)
683 	{
684 		if (!(var->int_flags & VIF_CHANGED))
685 			continue;
686 		if (do_all || !(var->int_flags & VIF_GLOBAL))
687 		{
688 			if (my_strcmp(var->name, "DISPLAY") == 0 || my_strcmp(var->name, "CLIENT_INFORMATION") == 0)
689 				continue;
690 			fprintf(fp, "SET ");
691 			switch (var->type)
692 			{
693 			case BOOL_TYPE_VAR:
694 				fprintf(fp, "%s %s\n", var->name, var->integer ?
695 					var_settings(ON) : var_settings(OFF));
696 				break;
697 			case CHAR_TYPE_VAR:
698 				fprintf(fp, "%s %c\n", var->name, var->integer);
699 				break;
700 			case INT_TYPE_VAR:
701 				fprintf(fp, "%s %u\n", var->name, var->integer);
702 				break;
703 			case STR_TYPE_VAR:
704 				if (var->string)
705 					fprintf(fp, "%s %s\n", var->name,
706 						var->string);
707 				else
708 					fprintf(fp, "-%s\n", var->name);
709 				break;
710 			}
711 		}
712 	}
713 }
714 
715 u_char	*
make_string_var(u_char * var_name)716 make_string_var(u_char *var_name)
717 {
718 	int	cnt,
719 		var_index;
720 	u_char	*ret = NULL,
721 		*cmd = NULL;
722 
723 	malloc_strcpy(&cmd, var_name);
724 	upper(cmd);
725 	if (((var_index = find_variable(cmd, &cnt)) == -1) ||
726 	    (cnt > 1) ||
727 	    my_strcmp(cmd, irc_variable[var_index].name))
728 		goto out;
729 	switch (irc_variable[var_index].type)
730 	{
731 	case STR_TYPE_VAR:
732 		malloc_strcpy(&ret, irc_variable[var_index].string);
733 		break;
734 	case INT_TYPE_VAR:
735 		malloc_snprintf(&ret, "%u", irc_variable[var_index].integer);
736 		break;
737 	case BOOL_TYPE_VAR:
738 		malloc_strcpy(&ret, UP(var_settings(irc_variable[var_index].integer)));
739 		break;
740 	case CHAR_TYPE_VAR:
741 		malloc_snprintf(&ret, "%c", irc_variable[var_index].integer);
742 		break;
743 	}
744 out:
745 	new_free(&cmd);
746 	return (ret);
747 
748 }
749 
750 /* exec_warning: a warning message displayed whenever EXEC_PROTECTION is turned off.  */
751 static	void
exec_warning(int value)752 exec_warning(int value)
753 {
754 	if (value == OFF)
755 	{
756 		say("Warning!  You have turned EXEC_PROTECTION off");
757 		say("Please read the /HELP SET EXEC_PROTECTION documentation");
758 	}
759 }
760 
761 static	void
input_warning(int value)762 input_warning(int value)
763 {
764 	if (value == OFF)
765 	{
766 		say("Warning!  You have turned INPUT_PROTECTION off");
767 		say("Please read the /HELP ON INPUT, and /HELP SET INPUT_PROTECTION documentation");
768 	}
769 }
770 
771 /* returns the size of the character set */
772 int
charset_size(void)773 charset_size(void)
774 {
775 	return get_int_var(EIGHT_BIT_CHARACTERS_VAR) ? 256 : 128;
776 }
777 
778 static	void
eight_bit_characters(int value)779 eight_bit_characters(int value)
780 {
781 	if (value == ON && !term_eight_bit())
782 		say("Warning!  Your terminal says it does not support eight bit characters");
783 	set_term_eight_bit(value);
784 }
785 
786 static	void
v_update_all_status(int dummy)787 v_update_all_status(int dummy)
788 {
789 	update_all_status();
790 }
791 
792 char *
var_settings(int idx)793 var_settings(int idx)
794 {
795 	if (idx == OFF)
796 		return "OFF";
797 	else if (idx == ON)
798 		return "ON";
799 	else if (idx == TOGGLE)
800 		return "TOGGLE";
801 	return "<internal error>";
802 };
803