1 /* $EPIC: vars.c,v 1.51 2014/03/31 13:57:22 jnelson Exp $ */
2 /*
3  * vars.c: All the dealing of the irc variables are handled here.
4  *
5  * Copyright (c) 1990 Michael Sandroff.
6  * Copyright (c) 1991, 1992 Troy Rollo.
7  * Copyright (c) 1992-1996 Matthew Green.
8  * Copyright � 1993, 2003 EPIC Software Labs.
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  *    notices, the above paragraph (the one permitting redistribution),
18  *    this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. The names of the author(s) may not be used to endorse or promote
21  *    products derived from this software without specific prior written
22  *    permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #include "irc.h"
38 #include "alist.h"
39 #include "status.h"
40 #include "window.h"
41 #include "lastlog.h"
42 #include "log.h"
43 #include "hook.h"
44 #include "sedcrypt.h"
45 #include "history.h"
46 #include "notify.h"
47 #include "vars.h"
48 #include "input.h"
49 #include "ircaux.h"
50 #include "termx.h"
51 #include "output.h"
52 #include "stack.h"
53 #include "dcc.h"
54 #include "keys.h"
55 #include "translat.h"
56 #include "timer.h"
57 #include "clock.h"
58 #include "mail.h"
59 
60 /* IrcVariable: structure for each variable in the variable table */
61 typedef struct
62 {
63 	const char *	name;		/* what the user types */
64 	int		type;		/* variable types, see below */
65 	int		integer;	/* int value of variable */
66 	double		number;		/* decimal value of variable */
67 	char *		string;		/* string value of variable */
68 	void		(*func) (const void *); /* func called when var is set */
69 	char		int_flags;	/* internal flags to the variable */
70 	unsigned short	flags;		/* flags for this variable */
71 }	IrcVariable;
72 
73 /*
74  * The VIF_* macros stand for "(V)ariable.(i)nt_(f)lags", and have been
75  * used for the various possible values of the int_flags data member.
76  * The first two are, the third one is not.  The third one is used in
77  * the 'flags' data member, but its based on the same idea.
78  */
79 #define VIF_CHANGED	0x01	/* /set has been changed by user */
80 #define VIF_GLOBAL	0x02	/* /set was changed only by global */
81 #define VIF_PENDING	0x04	/* A /set is pending for this variable */
82 
83 /* the types of IrcVariables */
84 #define BOOL_TYPE_VAR 0
85 #define CHAR_TYPE_VAR 1
86 #define INT_TYPE_VAR 2
87 #define STR_TYPE_VAR 3
88 #define FLOAT_TYPE_VAR 4
89 
90 const char	*var_settings[] =
91 {
92 	"OFF", "ON", "TOGGLE"
93 };
94 
95 static	void	eight_bit_characters 	(const void *);
96 static	void	set_realname 		(const void *);
97 static 	void 	set_display_pc_characters (const void *);
98 static 	void	set_dcc_timeout 	(const void *);
99 static	void	set_mangle_inbound 	(const void *);
100 static	void	set_mangle_outbound 	(const void *);
101 static	void	set_mangle_logfiles 	(const void *);
102 static	void	set_scroll 		(const void *);
103 static	void	update_all_status_wrapper (const void *);
104 static	void	set_highlight_char	(const void *);
105 static	void	set_wserv_type		(const void *);
106 
107 /*
108  * irc_variable: all the irc variables used.  Note that the integer and
109  * boolean defaults are set here, which the string default value are set in
110  * the init_variables() procedure
111  */
112 static	IrcVariable irc_variable[] =
113 {
114 	{ "ALLOW_C1_CHARS",		BOOL_TYPE_VAR,	DEFAULT_ALLOW_C1_CHARS, 0, NULL, NULL, 0, 0 },
115 	{ "ALT_CHARSET",		BOOL_TYPE_VAR,	DEFAULT_ALT_CHARSET, 0, NULL, NULL, 0, 0 },
116 	{ "ALWAYS_SPLIT_BIGGEST",	BOOL_TYPE_VAR,	DEFAULT_ALWAYS_SPLIT_BIGGEST, 0, NULL, NULL, 0, 0 },
117 	{ "AUTO_NEW_NICK",		BOOL_TYPE_VAR,	DEFAULT_AUTO_NEW_NICK, 0, NULL, NULL, 0, 0 },
118         { "AUTO_RECONNECT",             BOOL_TYPE_VAR,  DEFAULT_AUTO_RECONNECT, 0, NULL, NULL, 0, 0 },
119 	{ "AUTO_RECONNECT_DELAY",	INT_TYPE_VAR,	DEFAULT_AUTO_RECONNECT_DELAY, 0, NULL, NULL, 0, 0 },
120         { "AUTO_REJOIN",                BOOL_TYPE_VAR,  DEFAULT_AUTO_REJOIN, 0, NULL, NULL, 0, 0 },
121 	{ "AUTO_REJOIN_CONNECT",	BOOL_TYPE_VAR,	DEFAULT_AUTO_REJOIN_CONNECT, 0, NULL, NULL, 0, 0 },
122 	{ "AUTO_REJOIN_DELAY",		INT_TYPE_VAR,	DEFAULT_AUTO_REJOIN_DELAY, 0, NULL, NULL, 0, 0 },
123 	{ "AUTO_UNMARK_AWAY",		BOOL_TYPE_VAR,	DEFAULT_AUTO_UNMARK_AWAY, 0, NULL, NULL, 0, 0 },
124 	{ "AUTO_WHOWAS",		BOOL_TYPE_VAR,	DEFAULT_AUTO_WHOWAS, 0, NULL, NULL, 0, 0 },
125 	{ "BAD_STYLE",			BOOL_TYPE_VAR,	DEFAULT_BAD_STYLE, 0, NULL, NULL, 0, 0 },
126 	{ "BANNER",			STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
127 	{ "BANNER_EXPAND",		BOOL_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
128 	{ "BEEP",			BOOL_TYPE_VAR,	DEFAULT_BEEP, 0, NULL, NULL, 0, 0 },
129 	{ "BEEP_MAX",			INT_TYPE_VAR,	DEFAULT_BEEP_MAX, 0, NULL, NULL, 0, 0 },
130 	{ "BEEP_ON_MSG",		STR_TYPE_VAR,	0, 0, NULL, set_beep_on_msg, 0, 0 },
131 	{ "BEEP_WHEN_AWAY",		INT_TYPE_VAR,	DEFAULT_BEEP_WHEN_AWAY, 0, NULL, NULL, 0, 0 },
132 	{ "BLINK_VIDEO",		BOOL_TYPE_VAR,	DEFAULT_BLINK_VIDEO, 0, NULL, NULL, 0, 0 },
133 	{ "BOLD_VIDEO",			BOOL_TYPE_VAR,	DEFAULT_BOLD_VIDEO, 0, NULL, NULL, 0, 0 },
134 	{ "CHANNEL_NAME_WIDTH",		INT_TYPE_VAR,	DEFAULT_CHANNEL_NAME_WIDTH, 0, NULL, update_all_status_wrapper, 0, 0 },
135 	{ "CLIENT_INFORMATION",		STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
136 	{ "CLOCK",			BOOL_TYPE_VAR,	DEFAULT_CLOCK, 0, NULL, set_clock, 0, 0 },
137 	{ "CLOCK_24HOUR",		BOOL_TYPE_VAR,	DEFAULT_CLOCK_24HOUR, 0, NULL, reset_clock, 0, 0 },
138 	{ "CLOCK_FORMAT",		STR_TYPE_VAR,	0, 0, NULL, set_clock_format, 0, 0 },
139 	{ "CLOCK_INTERVAL",		INT_TYPE_VAR,	DEFAULT_CLOCK_INTERVAL, 0, NULL, set_clock_interval, 0, 0 },
140 	{ "CMDCHARS",			STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
141 	{ "COLOR",			BOOL_TYPE_VAR,	DEFAULT_COLOR, 0, NULL, NULL, 0, 0 },
142 	{ "COMMAND_MODE",		BOOL_TYPE_VAR,	DEFAULT_COMMAND_MODE, 0, NULL, NULL, 0, 0 },
143 	{ "COMMENT_HACK",		BOOL_TYPE_VAR,	DEFAULT_COMMENT_HACK, 0, NULL, NULL, 0, 0 },
144 	{ "CONNECT_TIMEOUT",		INT_TYPE_VAR,	DEFAULT_CONNECT_TIMEOUT, 0, NULL, NULL, 0, 0 },
145 	{ "CONTINUED_LINE",		STR_TYPE_VAR,	0, 0, NULL, set_continued_line, 0, 0 },
146 	{ "CPU_SAVER_AFTER",		INT_TYPE_VAR,	DEFAULT_CPU_SAVER_AFTER, 0, NULL, set_cpu_saver_after, 0, 0 },
147 	{ "CPU_SAVER_EVERY",		INT_TYPE_VAR,	DEFAULT_CPU_SAVER_EVERY, 0, NULL, set_cpu_saver_every, 0, 0 },
148 	{ "CURRENT_WINDOW_LEVEL",	STR_TYPE_VAR,	0, 0, NULL, set_current_window_level, 0, 0 },
149 	{ "DCC_AUTO_SEND_REJECTS",	BOOL_TYPE_VAR,	DEFAULT_DCC_AUTO_SEND_REJECTS, 0, NULL, NULL, 0, 0 },
150 	{ "DCC_DEQUOTE_FILENAMES",	BOOL_TYPE_VAR,	DEFAULT_DCC_DEQUOTE_FILENAMES, 0, NULL, NULL, 0, 0 },
151 	{ "DCC_LONG_PATHNAMES",		BOOL_TYPE_VAR,	DEFAULT_DCC_LONG_PATHNAMES, 0, NULL, NULL, 0, 0 },
152 	{ "DCC_SLIDING_WINDOW",		INT_TYPE_VAR,	DEFAULT_DCC_SLIDING_WINDOW, 0, NULL, NULL, 0, 0 },
153 	{ "DCC_STORE_PATH",		STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
154 	{ "DCC_TIMEOUT",		INT_TYPE_VAR,	DEFAULT_DCC_TIMEOUT, 0, NULL, set_dcc_timeout, 0, 0 },
155 	{ "DCC_USE_GATEWAY_ADDR",	BOOL_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
156 	{ "DEBUG",			INT_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
157 	{ "DISPATCH_UNKNOWN_COMMANDS",	BOOL_TYPE_VAR,	DEFAULT_DISPATCH_UNKNOWN_COMMANDS, 0, NULL, NULL, 0, 0 },
158 	{ "DISPLAY",			BOOL_TYPE_VAR,	DEFAULT_DISPLAY, 0, NULL, NULL, 0, 0 },
159 	{ "DISPLAY_ANSI",		BOOL_TYPE_VAR,	DEFAULT_DISPLAY_ANSI, 0, NULL, NULL, 0, 0 },
160 	{ "DISPLAY_PC_CHARACTERS",	INT_TYPE_VAR,	DEFAULT_DISPLAY_PC_CHARACTERS, 0, NULL, set_display_pc_characters, 0, 0 },
161 	{ "DO_NOTIFY_IMMEDIATELY",	BOOL_TYPE_VAR,	DEFAULT_DO_NOTIFY_IMMEDIATELY, 0, NULL, NULL, 0, 0 },
162 	{ "EIGHT_BIT_CHARACTERS",	BOOL_TYPE_VAR,	DEFAULT_EIGHT_BIT_CHARACTERS, 0, NULL, eight_bit_characters, 0, 0 },
163 	{ "FLOATING_POINT_MATH",	BOOL_TYPE_VAR,	DEFAULT_FLOATING_POINT_MATH, 0, NULL, NULL, 0, 0 },
164 	{ "FLOATING_POINT_PRECISION",	INT_TYPE_VAR,	DEFAULT_FLOATING_POINT_PRECISION, 0, NULL, NULL, 0, 0 },
165 	{ "FLOOD_AFTER",		INT_TYPE_VAR,	DEFAULT_FLOOD_AFTER, 0, NULL, NULL, 0, 0 },
166 	{ "FLOOD_IGNORE",		BOOL_TYPE_VAR,	DEFAULT_FLOOD_IGNORE, 0, NULL, NULL, 0, 0 },
167 	{ "FLOOD_MASKUSER",		INT_TYPE_VAR,	DEFAULT_FLOOD_MASKUSER, 0, NULL, NULL, 0, 0 },
168 	{ "FLOOD_RATE",			INT_TYPE_VAR,	DEFAULT_FLOOD_RATE, 0, NULL, NULL, 0, 0 },
169 	{ "FLOOD_RATE_PER",		INT_TYPE_VAR,	DEFAULT_FLOOD_RATE_PER, 0, NULL, NULL, 0, 0 },
170 	{ "FLOOD_USERS",		INT_TYPE_VAR,	DEFAULT_FLOOD_USERS, 0, NULL, NULL, 0, 0 },
171 	{ "FLOOD_WARNING",		BOOL_TYPE_VAR,	DEFAULT_FLOOD_WARNING, 0, NULL, NULL, 0, 0 },
172 	{ "FULL_STATUS_LINE",		BOOL_TYPE_VAR,	DEFAULT_FULL_STATUS_LINE, 0, NULL, update_all_status_wrapper, 0, 0 },
173 	{ "HELP_PAGER",			BOOL_TYPE_VAR,	DEFAULT_HELP_PAGER, 0, NULL, NULL, 0, 0 },
174 	{ "HELP_PATH",			STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
175 	{ "HELP_PROMPT",		BOOL_TYPE_VAR,	DEFAULT_HELP_PROMPT, 0, NULL, NULL, 0, 0 },
176 	{ "HELP_WINDOW",		BOOL_TYPE_VAR,	DEFAULT_HELP_WINDOW, 0, NULL, NULL, 0, 0 },
177 	{ "HIDE_PRIVATE_CHANNELS",	BOOL_TYPE_VAR,	DEFAULT_HIDE_PRIVATE_CHANNELS, 0, NULL, update_all_status_wrapper, 0, 0 },
178 	{ "HIGHLIGHT_CHAR",		STR_TYPE_VAR,	0, 0, NULL, set_highlight_char, 0, 0 },
179 	{ "HIGH_BIT_ESCAPE",		INT_TYPE_VAR,	DEFAULT_HIGH_BIT_ESCAPE, 0, NULL, set_meta_8bit, 0, 0 },
180 	{ "HISTORY",			INT_TYPE_VAR,	DEFAULT_HISTORY, 0, NULL, set_history_size, 0, 0 },
181 	{ "HISTORY_CIRCLEQ",		BOOL_TYPE_VAR,	DEFAULT_HISTORY_CIRCLEQ, 0, NULL, NULL, 0, 0 },
182 	{ "HOLD_SLIDER",		INT_TYPE_VAR,	DEFAULT_HOLD_SLIDER, 0, NULL, NULL, 0, 0 },
183 	{ "INDENT",			BOOL_TYPE_VAR,	DEFAULT_INDENT, 0, NULL, NULL, 0, 0 },
184 	{ "INPUT_ALIASES",		BOOL_TYPE_VAR,	DEFAULT_INPUT_ALIASES, 0, NULL, NULL, 0, 0 },
185 	{ "INPUT_PROMPT",		STR_TYPE_VAR,	0, 0, NULL, set_input_prompt, 0, 0 },
186 	{ "INSERT_MODE",		BOOL_TYPE_VAR,	DEFAULT_INSERT_MODE, 0, NULL, update_all_status_wrapper, 0, 0 },
187 	{ "INVERSE_VIDEO",		BOOL_TYPE_VAR,	DEFAULT_INVERSE_VIDEO, 0, NULL, NULL, 0, 0 },
188 	{ "KEY_INTERVAL",		INT_TYPE_VAR,	DEFAULT_KEY_INTERVAL, 0, NULL, set_key_interval, 0, 0 },
189 	{ "LASTLOG",			INT_TYPE_VAR,	DEFAULT_LASTLOG, 0, NULL, set_lastlog_size, 0, 0 },
190 	{ "LASTLOG_LEVEL",		STR_TYPE_VAR,	0, 0, NULL, set_lastlog_level, 0, 0 },
191 	{ "LOAD_PATH",			STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
192 	{ "LOG",			BOOL_TYPE_VAR,	DEFAULT_LOG, 0, NULL, logger, 0, 0 },
193 	{ "LOGFILE",			STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
194 	{ "LOG_REWRITE",		STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
195 	{ "MAIL",			INT_TYPE_VAR,	DEFAULT_MAIL, 0, NULL, set_mail, 0, 0 },
196 	{ "MAIL_INTERVAL",		INT_TYPE_VAR,	DEFAULT_MAIL_INTERVAL, 0, NULL, set_mail_interval, 0, 0 },
197 	{ "MAIL_TYPE",			STR_TYPE_VAR,	0, 0, NULL, set_mail_type, 0, 0 },
198 	{ "MANGLE_INBOUND",		STR_TYPE_VAR,	0, 0, NULL, set_mangle_inbound, 0, 0 },
199 	{ "MANGLE_LOGFILES",		STR_TYPE_VAR,	0, 0, NULL, set_mangle_logfiles, 0, 0 },
200 	{ "MANGLE_OUTBOUND",		STR_TYPE_VAR,	0, 0, NULL, set_mangle_outbound, 0, 0 },
201 	{ "MAX_RECONNECTS",		INT_TYPE_VAR,	DEFAULT_MAX_RECONNECTS, 0, NULL, NULL, 0, 0 },
202 	{ "METRIC_TIME",		BOOL_TYPE_VAR,	DEFAULT_METRIC_TIME, 0, NULL, reset_clock, 0, 0 },
203 	{ "MIRC_BROKEN_DCC_RESUME",	BOOL_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
204         { "MODE_STRIPPER",              BOOL_TYPE_VAR,  DEFAULT_MODE_STRIPPER, 0, NULL, NULL, 0, 0 },
205 	{ "ND_SPACE_MAX",		INT_TYPE_VAR,	DEFAULT_ND_SPACE_MAX, 0, NULL, NULL, 0, 0 },
206 	{ "NEW_SERVER_LASTLOG_LEVEL",	STR_TYPE_VAR,	0, 0, NULL, set_new_server_lastlog_level, 0, 0 },
207 	{ "NOTIFY",			BOOL_TYPE_VAR,	DEFAULT_NOTIFY, 0, NULL, set_notify, 0, 0 },
208 	{ "NOTIFY_INTERVAL",		INT_TYPE_VAR,	DEFAULT_NOTIFY_INTERVAL, 0, NULL, set_notify_interval, 0, 0 },
209 	{ "NOTIFY_LEVEL",		STR_TYPE_VAR,	0, 0, NULL, set_notify_level, 0, 0 },
210 	{ "NOTIFY_ON_TERMINATION",	BOOL_TYPE_VAR,	DEFAULT_NOTIFY_ON_TERMINATION, 0, NULL, NULL, 0, 0 },
211 	{ "NOTIFY_USERHOST_AUTOMATIC",	BOOL_TYPE_VAR,	DEFAULT_NOTIFY_USERHOST_AUTOMATIC, 0, NULL, NULL, 0, 0 },
212 	{ "NO_CONTROL_LOG",		BOOL_TYPE_VAR,	DEFAULT_NO_CONTROL_LOG, 0, NULL, NULL, 0, 0 },
213 	{ "NO_CTCP_FLOOD",		BOOL_TYPE_VAR,	DEFAULT_NO_CTCP_FLOOD, 0, NULL, NULL, 0, 0 },
214 	{ "NO_FAIL_DISCONNECT",		BOOL_TYPE_VAR,	DEFAULT_NO_FAIL_DISCONNECT, 0, NULL, NULL, 0, 0 },
215 	{ "NUM_OF_WHOWAS",		INT_TYPE_VAR,	DEFAULT_NUM_OF_WHOWAS, 0, NULL, NULL, 0, 0 },
216 	{ "OUTPUT_REWRITE",		STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
217 	{ "PAD_CHAR",			CHAR_TYPE_VAR,	DEFAULT_PAD_CHAR, 0, NULL, NULL, 0, 0 },
218 	{ "QUIT_MESSAGE",		STR_TYPE_VAR,   0, 0, NULL, NULL, 0, 0 },
219 	{ "RANDOM_SOURCE",		INT_TYPE_VAR,	DEFAULT_RANDOM_SOURCE, 0, NULL, NULL, 0, 0 },
220 	{ "REALNAME",			STR_TYPE_VAR,	0, 0, NULL, set_realname, 0, 0 },
221 	{ "REVERSE_STATUS_LINE",	BOOL_TYPE_VAR,	DEFAULT_REVERSE_STATUS_LINE, 0, NULL, update_all_status_wrapper, 0, 0 },
222 	{ "SCREEN_OPTIONS",             STR_TYPE_VAR,   0, 0, NULL, NULL, 0, 0 },
223 	{ "SCROLL",			BOOL_TYPE_VAR,	1, 0, NULL, set_scroll, 0, 0 },
224 	{ "SCROLLBACK",			INT_TYPE_VAR,	DEFAULT_SCROLLBACK, 0, NULL, set_scrollback_size, 0, 0 },
225 	{ "SCROLLBACK_RATIO",		INT_TYPE_VAR,	DEFAULT_SCROLLBACK_RATIO, 0, NULL, NULL, 0, 0 },
226 	{ "SCROLL_LINES",		INT_TYPE_VAR,	DEFAULT_SCROLL_LINES, 0, NULL, set_scroll_lines, 0, 0 },
227 	{ "SECURITY",			INT_TYPE_VAR,	DEFAULT_SECURITY, 0, NULL, NULL, 0, 0 },
228 	{ "SHELL",			STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
229 	{ "SHELL_FLAGS",		STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
230 	{ "SHELL_LIMIT",		INT_TYPE_VAR,	DEFAULT_SHELL_LIMIT, 0, NULL, NULL, 0, 0 },
231 	{ "SHOW_CHANNEL_NAMES",		BOOL_TYPE_VAR,	DEFAULT_SHOW_CHANNEL_NAMES, 0, NULL, NULL, 0, 0 },
232 	{ "SHOW_END_OF_MSGS",		BOOL_TYPE_VAR,	DEFAULT_SHOW_END_OF_MSGS, 0, NULL, NULL, 0, 0 },
233 	{ "SHOW_NUMERICS",		BOOL_TYPE_VAR,	DEFAULT_SHOW_NUMERICS, 0, NULL, NULL, 0, 0 },
234 	{ "SHOW_STATUS_ALL",		BOOL_TYPE_VAR,	DEFAULT_SHOW_STATUS_ALL, 0, NULL, update_all_status_wrapper, 0, 0 },
235 	{ "SHOW_WHO_HOPCOUNT", 		BOOL_TYPE_VAR,	DEFAULT_SHOW_WHO_HOPCOUNT, 0, NULL, NULL, 0, 0 },
236 	{ "SSL_CERTFILE",		STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
237 	{ "SSL_KEYFILE",		STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
238 	{ "SSL_PATH",			STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
239 	{ "STATUS_AWAY",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
240 	{ "STATUS_CHANNEL",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
241 	{ "STATUS_CHANOP",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
242 	{ "STATUS_CLOCK",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
243 	{ "STATUS_CPU_SAVER",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
244 	{ "STATUS_DOES_EXPANDOS",	BOOL_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
245 	{ "STATUS_FORMAT",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
246 	{ "STATUS_FORMAT1",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
247 	{ "STATUS_FORMAT2",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
248 	{ "STATUS_HALFOP",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
249 	{ "STATUS_HOLD",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
250 	{ "STATUS_HOLD_LINES",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
251 	{ "STATUS_INSERT",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
252 	{ "STATUS_MAIL",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
253 	{ "STATUS_MODE",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
254 	{ "STATUS_NICKNAME",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
255 	{ "STATUS_NOSWAP",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
256 	{ "STATUS_NOTIFY",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
257         { "STATUS_NO_REPEAT",           BOOL_TYPE_VAR,  DEFAULT_STATUS_NO_REPEAT, 0, NULL, build_status, 0, 0 },
258 	{ "STATUS_OPER",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
259 	{ "STATUS_OVERWRITE",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
260 	{ "STATUS_QUERY",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
261 	{ "STATUS_SCROLLBACK",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
262 	{ "STATUS_SERVER",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
263 	{ "STATUS_SSL_OFF",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
264 	{ "STATUS_SSL_ON",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
265 	{ "STATUS_TRUNCATE_RHS",	BOOL_TYPE_VAR,	DEFAULT_STATUS_TRUNCATE_RHS, 0, NULL, build_status, 0, 0 },
266 	{ "STATUS_UMODE",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
267 	{ "STATUS_USER",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
268 	{ "STATUS_USER1",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
269 	{ "STATUS_USER10",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
270 	{ "STATUS_USER11",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
271 	{ "STATUS_USER12",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
272 	{ "STATUS_USER13",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
273 	{ "STATUS_USER14",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
274 	{ "STATUS_USER15",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
275 	{ "STATUS_USER16",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
276 	{ "STATUS_USER17",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
277 	{ "STATUS_USER18",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
278 	{ "STATUS_USER19",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
279 	{ "STATUS_USER2",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
280 	{ "STATUS_USER20",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
281 	{ "STATUS_USER21",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
282 	{ "STATUS_USER22",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
283 	{ "STATUS_USER23",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
284 	{ "STATUS_USER24",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
285 	{ "STATUS_USER25",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
286 	{ "STATUS_USER26",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
287 	{ "STATUS_USER27",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
288 	{ "STATUS_USER28",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
289 	{ "STATUS_USER29",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
290 	{ "STATUS_USER3",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
291 	{ "STATUS_USER30",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
292 	{ "STATUS_USER31",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
293 	{ "STATUS_USER32",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
294 	{ "STATUS_USER33",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
295 	{ "STATUS_USER34",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
296 	{ "STATUS_USER35",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
297 	{ "STATUS_USER36",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
298 	{ "STATUS_USER37",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
299 	{ "STATUS_USER38",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
300 	{ "STATUS_USER39",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
301 	{ "STATUS_USER4",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
302 	{ "STATUS_USER5",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
303 	{ "STATUS_USER6",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
304 	{ "STATUS_USER7",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
305 	{ "STATUS_USER8",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
306 	{ "STATUS_USER9",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
307 	{ "STATUS_VOICE",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
308 	{ "STATUS_WINDOW",		STR_TYPE_VAR,	0, 0, NULL, build_status, 0, 0 },
309         { "SUPPRESS_FROM_REMOTE_SERVER",BOOL_TYPE_VAR,  DEFAULT_SUPPRESS_FROM_REMOTE_SERVER, 0, NULL, NULL, 0, 0},
310 	{ "SWITCH_CHANNELS_BETWEEN_WINDOWS",	BOOL_TYPE_VAR,	DEFAULT_SWITCH_CHANNELS_BETWEEN_WINDOWS, 0, NULL, NULL, 0, 0 },
311 	{ "SWITCH_CHANNEL_ON_PART",	BOOL_TYPE_VAR,	DEFAULT_SWITCH_CHANNEL_ON_PART, 0, NULL, NULL, 0, 0 },
312 	{ "TAB",			BOOL_TYPE_VAR,	DEFAULT_TAB, 0, NULL, NULL, 0, 0 },
313 	{ "TAB_MAX",			INT_TYPE_VAR,	DEFAULT_TAB_MAX, 0, NULL, NULL, 0, 0 },
314 	{ "TERM_DOES_BRIGHT_BLINK",	BOOL_TYPE_VAR,	DEFAULT_TERM_DOES_BRIGHT_BLINK, 0, NULL, NULL, 0, 0 },
315 	{ "TRANSLATION",		STR_TYPE_VAR,	0, 0, NULL, set_translation, 0, 0 },
316 	{ "TRANSLATION_PATH",		STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
317 	{ "UNDERLINE_VIDEO",		BOOL_TYPE_VAR,	DEFAULT_UNDERLINE_VIDEO, 0, NULL, NULL, 0, 0 },
318 	{ "USER_INFORMATION", 		STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
319 	{ "VERBOSE_CTCP",		BOOL_TYPE_VAR,	DEFAULT_VERBOSE_CTCP, 0, NULL, NULL, 0, 0 },
320 	{ "WORD_BREAK",			STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
321 	{ "WSERV_PATH",			STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
322 	{ "WSERV_TYPE",			STR_TYPE_VAR,	0, 0, NULL, set_wserv_type, 0, 0 },
323 	{ "XTERM",			STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
324 	{ "XTERM_OPTIONS", 		STR_TYPE_VAR,	0, 0, NULL, NULL, 0, 0 },
325 	{ (char *) 0, 0, 0, 0, 0, 0, 0, 0 }
326 };
327 
328 /*
329  * init_variables: initializes the string variables that can't really be
330  * initialized properly above
331  */
init_variables(void)332 void 	init_variables (void)
333 {
334 	char 	*s;
335 	int 	i;
336 
337 	for (i = 1; i < NUMBER_OF_VARIABLES - 1; i++)
338 		if (strcmp(irc_variable[i-1].name, irc_variable[i].name) >= 0)
339 			panic("Variable [%d] (%s) is out of order.", i, irc_variable[i].name);
340 
341 	set_string_var(BANNER_VAR, DEFAULT_BANNER);
342 	set_string_var(BEEP_ON_MSG_VAR, DEFAULT_BEEP_ON_MSG);
343 	set_string_var(CMDCHARS_VAR, DEFAULT_CMDCHARS);
344 	set_string_var(CURRENT_WINDOW_LEVEL_VAR, DEFAULT_CURRENT_WINDOW_LEVEL);
345 	set_string_var(LOGFILE_VAR, DEFAULT_LOGFILE);
346 	set_string_var(SHELL_VAR, DEFAULT_SHELL);
347 	set_string_var(SHELL_FLAGS_VAR, DEFAULT_SHELL_FLAGS);
348 	set_string_var(CONTINUED_LINE_VAR, DEFAULT_CONTINUED_LINE);
349 	set_string_var(INPUT_PROMPT_VAR, DEFAULT_INPUT_PROMPT);
350 	set_string_var(HIGHLIGHT_CHAR_VAR, DEFAULT_HIGHLIGHT_CHAR);
351 	set_string_var(LASTLOG_LEVEL_VAR, DEFAULT_LASTLOG_LEVEL);
352 	set_string_var(LOG_REWRITE_VAR, NULL);
353 	set_string_var(MAIL_TYPE_VAR, DEFAULT_MAIL_TYPE);
354 	set_string_var(MANGLE_INBOUND_VAR, NULL);
355 	set_string_var(MANGLE_LOGFILES_VAR, NULL);
356 	set_string_var(MANGLE_OUTBOUND_VAR, NULL);
357 	set_string_var(NEW_SERVER_LASTLOG_LEVEL_VAR,
358 			DEFAULT_NEW_SERVER_LASTLOG_LEVEL);
359 	set_string_var(NOTIFY_LEVEL_VAR, DEFAULT_NOTIFY_LEVEL);
360 	set_string_var(OUTPUT_REWRITE_VAR, NULL);
361 	set_string_var(QUIT_MESSAGE_VAR, DEFAULT_QUIT_MESSAGE);
362 	set_string_var(REALNAME_VAR, realname);
363 	set_string_var(SSL_CERTFILE_VAR, NULL);
364 	set_string_var(SSL_KEYFILE_VAR, NULL);
365 	set_string_var(SSL_PATH_VAR, NULL);
366 	set_string_var(STATUS_FORMAT_VAR, DEFAULT_STATUS_FORMAT);
367 	set_string_var(STATUS_FORMAT1_VAR, DEFAULT_STATUS_FORMAT1);
368 	set_string_var(STATUS_FORMAT2_VAR, DEFAULT_STATUS_FORMAT2);
369 	set_string_var(STATUS_AWAY_VAR, DEFAULT_STATUS_AWAY);
370 	set_string_var(STATUS_CHANNEL_VAR, DEFAULT_STATUS_CHANNEL);
371 	set_string_var(STATUS_CHANOP_VAR, DEFAULT_STATUS_CHANOP);
372 	set_string_var(STATUS_HALFOP_VAR, DEFAULT_STATUS_HALFOP);
373 	set_string_var(STATUS_SSL_ON_VAR, DEFAULT_STATUS_SSL_ON);
374 	set_string_var(STATUS_SSL_OFF_VAR, DEFAULT_STATUS_SSL_OFF);
375 	set_string_var(STATUS_CLOCK_VAR, DEFAULT_STATUS_CLOCK);
376 	set_string_var(STATUS_CPU_SAVER_VAR, DEFAULT_STATUS_CPU_SAVER);
377 	set_string_var(STATUS_HOLD_VAR, DEFAULT_STATUS_HOLD);
378 	set_string_var(STATUS_HOLD_LINES_VAR, DEFAULT_STATUS_HOLD_LINES);
379 	set_string_var(STATUS_INSERT_VAR, DEFAULT_STATUS_INSERT);
380 	set_string_var(STATUS_MAIL_VAR, DEFAULT_STATUS_MAIL);
381 	set_string_var(STATUS_MODE_VAR, DEFAULT_STATUS_MODE);
382 	set_string_var(STATUS_NICK_VAR, DEFAULT_STATUS_NICK);
383 	set_string_var(STATUS_NOSWAP_VAR, DEFAULT_STATUS_NOSWAP);
384 	set_string_var(STATUS_OPER_VAR, DEFAULT_STATUS_OPER);
385 	set_string_var(STATUS_OVERWRITE_VAR, DEFAULT_STATUS_OVERWRITE);
386 	set_string_var(STATUS_QUERY_VAR, DEFAULT_STATUS_QUERY);
387 	set_string_var(STATUS_SCROLLBACK_VAR, DEFAULT_STATUS_SCROLLBACK);
388 	set_string_var(STATUS_SERVER_VAR, DEFAULT_STATUS_SERVER);
389 	set_string_var(STATUS_UMODE_VAR, DEFAULT_STATUS_UMODE);
390 	set_string_var(STATUS_USER0_VAR, DEFAULT_STATUS_USER);
391 	set_string_var(STATUS_USER1_VAR, DEFAULT_STATUS_USER1);
392 	set_string_var(STATUS_USER2_VAR, DEFAULT_STATUS_USER2);
393 	set_string_var(STATUS_USER3_VAR, DEFAULT_STATUS_USER3);
394 	set_string_var(STATUS_USER4_VAR, DEFAULT_STATUS_USER4);
395 	set_string_var(STATUS_USER5_VAR, DEFAULT_STATUS_USER5);
396 	set_string_var(STATUS_USER6_VAR, DEFAULT_STATUS_USER6);
397 	set_string_var(STATUS_USER7_VAR, DEFAULT_STATUS_USER7);
398 	set_string_var(STATUS_USER8_VAR, DEFAULT_STATUS_USER8);
399 	set_string_var(STATUS_USER9_VAR, DEFAULT_STATUS_USER9);
400 	set_string_var(STATUS_USER10_VAR, DEFAULT_STATUS_USER10);
401 	set_string_var(STATUS_USER11_VAR, DEFAULT_STATUS_USER11);
402 	set_string_var(STATUS_USER12_VAR, DEFAULT_STATUS_USER12);
403 	set_string_var(STATUS_USER13_VAR, DEFAULT_STATUS_USER13);
404 	set_string_var(STATUS_USER14_VAR, DEFAULT_STATUS_USER14);
405 	set_string_var(STATUS_USER15_VAR, DEFAULT_STATUS_USER15);
406 	set_string_var(STATUS_USER16_VAR, DEFAULT_STATUS_USER16);
407 	set_string_var(STATUS_USER17_VAR, DEFAULT_STATUS_USER17);
408 	set_string_var(STATUS_USER18_VAR, DEFAULT_STATUS_USER18);
409 	set_string_var(STATUS_USER19_VAR, DEFAULT_STATUS_USER19);
410 	set_string_var(STATUS_USER20_VAR, DEFAULT_STATUS_USER20);
411 	set_string_var(STATUS_USER21_VAR, DEFAULT_STATUS_USER21);
412 	set_string_var(STATUS_USER22_VAR, DEFAULT_STATUS_USER22);
413 	set_string_var(STATUS_USER23_VAR, DEFAULT_STATUS_USER23);
414 	set_string_var(STATUS_USER24_VAR, DEFAULT_STATUS_USER24);
415 	set_string_var(STATUS_USER25_VAR, DEFAULT_STATUS_USER25);
416 	set_string_var(STATUS_USER26_VAR, DEFAULT_STATUS_USER26);
417 	set_string_var(STATUS_USER27_VAR, DEFAULT_STATUS_USER27);
418 	set_string_var(STATUS_USER28_VAR, DEFAULT_STATUS_USER28);
419 	set_string_var(STATUS_USER29_VAR, DEFAULT_STATUS_USER29);
420 	set_string_var(STATUS_USER30_VAR, DEFAULT_STATUS_USER30);
421 	set_string_var(STATUS_USER31_VAR, DEFAULT_STATUS_USER31);
422 	set_string_var(STATUS_USER32_VAR, DEFAULT_STATUS_USER32);
423 	set_string_var(STATUS_USER33_VAR, DEFAULT_STATUS_USER33);
424 	set_string_var(STATUS_USER34_VAR, DEFAULT_STATUS_USER34);
425 	set_string_var(STATUS_USER35_VAR, DEFAULT_STATUS_USER35);
426 	set_string_var(STATUS_USER36_VAR, DEFAULT_STATUS_USER36);
427 	set_string_var(STATUS_USER37_VAR, DEFAULT_STATUS_USER37);
428 	set_string_var(STATUS_USER38_VAR, DEFAULT_STATUS_USER38);
429 	set_string_var(STATUS_USER39_VAR, DEFAULT_STATUS_USER39);
430 	set_string_var(STATUS_VOICE_VAR, DEFAULT_STATUS_VOICE);
431 	set_string_var(STATUS_WINDOW_VAR, DEFAULT_STATUS_WINDOW);
432 	set_string_var(TRANSLATION_VAR, NULL);
433 	set_string_var(USERINFO_VAR, DEFAULT_USERINFO);
434 	set_string_var(XTERM_VAR, DEFAULT_XTERM);
435 	set_string_var(XTERM_OPTIONS_VAR, DEFAULT_XTERM_OPTIONS);
436 	set_string_var(STATUS_NOTIFY_VAR, DEFAULT_STATUS_NOTIFY);
437 	set_string_var(CLIENTINFO_VAR, IRCII_COMMENT);
438 	set_string_var(WORD_BREAK_VAR, DEFAULT_WORD_BREAK);
439 	set_string_var(WSERV_PATH_VAR, WSERV_PATH);
440 	set_string_var(WSERV_TYPE_VAR, DEFAULT_WSERV_TYPE);
441 
442 	/*
443 	 * Construct the default help path
444 	 */
445 	s = malloc_strdup(irc_lib);
446 	malloc_strcat(&s, "/help");
447 	set_string_var(HELP_PATH_VAR, s);
448 	new_free(&s);
449 
450 	/*
451 	 * Forcibly init all the variables
452 	 */
453 	for (i = 0; i < NUMBER_OF_VARIABLES; i++)
454 	{
455 		IrcVariable *var = &irc_variable[i];
456 
457 		if (var->func)
458 		{
459 			if (var->func == build_status)
460 				continue;
461 			if (var->func == update_all_status_wrapper)
462 				continue;
463 
464 			var->flags |= VIF_PENDING;
465 			switch (var->type)
466 			{
467 				case (BOOL_TYPE_VAR):
468 				case (INT_TYPE_VAR):
469 				case (CHAR_TYPE_VAR):
470 					var->func(&var->integer);
471 					break;
472 				case (FLOAT_TYPE_VAR):
473 					var->func(&var->number);
474 					break;
475 				case (STR_TYPE_VAR):
476 					var->func(var->string);
477 					break;
478 			}
479 			var->flags &= ~VIF_PENDING;
480 		}
481 	}
482 }
483 
484 /*
485  * do_boolean: just a handy thing.  Returns 1 if the str is not ON, OFF, or
486  * TOGGLE
487  */
do_boolean(char * str,int * value)488 int 	do_boolean (char *str, int *value)
489 {
490 	upper(str);
491 	if (strcmp(str, var_settings[ON]) == 0)
492 		*value = 1;
493 	else if (strcmp(str, var_settings[OFF]) == 0)
494 		*value = 0;
495 	else if (strcmp(str, "TOGGLE") == 0)
496 	{
497 		if (*value)
498 			*value = 0;
499 		else
500 			*value = 1;
501 	}
502 	else
503 		return (1);
504 	return (0);
505 }
506 
507 /*
508  * get_variable_index: converts a string into an offset into the set table.
509  * Returns NUMBER_OF_VARIABLES if varname doesn't exist.
510  */
get_variable_index(const char * varname)511 static enum VAR_TYPES get_variable_index (const char *varname)
512 {
513 	enum VAR_TYPES	retval;
514 	int	cnt;
515 
516 	find_fixed_array_item(irc_variable, sizeof(IrcVariable),
517 				NUMBER_OF_VARIABLES, varname, &cnt,
518 				(int *)&retval);
519 
520 	if (cnt < 0)
521 		return retval;
522 
523 	return NUMBER_OF_VARIABLES;
524 }
525 
526 /*
527  * set_var_value: Given the variable structure and the string representation
528  * of the value, this sets the value in the most verbose and error checking
529  * of manors.  It displays the results of the set and executes the function
530  * defined in the var structure
531  */
set_var_value(int svv_index,char * value)532 void 	set_var_value (int svv_index, char *value)
533 {
534 	char	*rest;
535 	IrcVariable *var;
536 	int	old;
537 
538 	var = &(irc_variable[svv_index]);
539 	switch (var->type)
540 	{
541 	case BOOL_TYPE_VAR:
542 	{
543 		if (value && *value && (value = next_arg(value, &rest)))
544 		{
545 			old = var->integer;
546 			if (do_boolean(value, &(var->integer)))
547 			{
548 				say("Value must be either ON, OFF, or TOGGLE");
549 				break;
550 			}
551 			if (!(var->int_flags & VIF_CHANGED))
552 			{
553 				if (old != var->integer)
554 					var->int_flags |= VIF_CHANGED;
555 			}
556 			if (loading_global)
557 				var->int_flags |= VIF_GLOBAL;
558 			if (var->func)
559 				(var->func) (&var->integer);
560 			say("Value of %s set to %s", var->name,
561 				var->integer ? var_settings[ON]
562 					     : var_settings[OFF]);
563 		}
564 		else
565 			say("Current value of %s is %s", var->name,
566 				(var->integer) ?
567 				var_settings[ON] : var_settings[OFF]);
568 		break;
569 	}
570 	case CHAR_TYPE_VAR:
571 	{
572 		if (!value)
573 		{
574 			if (!(var->int_flags & VIF_CHANGED))
575 			{
576 				if (var->integer)
577 					var->int_flags |= VIF_CHANGED;
578 			}
579 			if (loading_global)
580 				var->int_flags |= VIF_GLOBAL;
581 			var->integer = ' ';
582 			if (var->func)
583 				(var->func) (&var->integer);
584 			say("Value of %s set to '%c'", var->name, var->integer);
585 		}
586 
587 
588 		else if (value && *value && (value = next_arg(value, &rest)))
589 		{
590 			if (strlen(value) > 1)
591 				say("Value of %s must be a single character",
592 					var->name);
593 			else
594 			{
595 				if (!(var->int_flags & VIF_CHANGED))
596 				{
597 					if (var->integer != *value)
598 						var->int_flags |= VIF_CHANGED;
599 				}
600 				if (loading_global)
601 					var->int_flags |= VIF_GLOBAL;
602 				var->integer = *value;
603 				if (var->func)
604 					(var->func) (&var->integer);
605 				say("Value of %s set to '%c'", var->name,
606 					var->integer);
607 			}
608 		}
609 		else
610 			say("Current value of %s is '%c'", var->name,
611 				var->integer);
612 		break;
613 	}
614 	case INT_TYPE_VAR:
615 	{
616 		if (value && *value && (value = next_arg(value, &rest)))
617 		{
618 			int	val;
619 
620 			if (!is_number(value))
621 			{
622 				say("Value of %s must be numeric!", var->name);
623 				break;
624 			}
625 			if ((val = my_atol(value)) < 0)
626 			{
627 				say("Value of %s must be a non-negative number", var->name);
628 				break;
629 			}
630 			if (!(var->int_flags & VIF_CHANGED))
631 			{
632 				if (var->integer != val)
633 					var->int_flags |= VIF_CHANGED;
634 			}
635 			if (loading_global)
636 				var->int_flags |= VIF_GLOBAL;
637 			var->integer = val;
638 			if (var->func)
639 				(var->func) (&var->integer);
640 			say("Value of %s set to %d", var->name, var->integer);
641 		}
642 		else
643 			say("Current value of %s is %d", var->name, var->integer);
644 		break;
645 	}
646 	case FLOAT_TYPE_VAR:
647 	{
648 		if (value && *value && (value = next_arg(value, &rest)))
649 		{
650 			int	val;
651 
652 			if (!is_real_number(value))
653 			{
654 				say("Value of %s must be numeric!", var->name);
655 				break;
656 			}
657 			val = atof(value);
658 			if (!(var->int_flags & VIF_CHANGED))
659 			{
660 				if (var->number != val)
661 					var->int_flags |= VIF_CHANGED;
662 			}
663 			if (loading_global)
664 				var->int_flags |= VIF_GLOBAL;
665 			var->number = val;
666 			if (var->func)
667 				(var->func) (&var->number);
668 			say("Value of %s set to %f", var->name, var->number);
669 		}
670 		else
671 			say("Current value of %s is %f", var->name, var->number);
672 		break;
673 	}
674 	case STR_TYPE_VAR:
675 	{
676 		if (value)
677 		{
678 			if (*value)
679 			{
680 				if ((!var->int_flags & VIF_CHANGED))
681 				{
682 					if ((var->string && !value) ||
683 					    (!var->string && value) ||
684 					    my_stricmp(var->string, value))
685 						var->int_flags |= VIF_CHANGED;
686 				}
687 				if (loading_global)
688 					var->int_flags |= VIF_GLOBAL;
689 				malloc_strcpy(&(var->string), value);
690 			}
691 			else
692 			{
693 				if (var->string)
694 					say("Current value of %s is %s",
695 						var->name, var->string);
696 				else
697 					say("No value for %s has been set",
698 						var->name);
699 				return;
700 			}
701 		}
702 		else
703 			new_free(&(var->string));
704 
705 		if (var->func && !(var->int_flags & VIF_PENDING))
706 		{
707 			var->int_flags |= VIF_PENDING;
708 			(var->func) (var->string);
709 			var->int_flags &= ~VIF_PENDING;
710 		}
711 
712 		say("Value of %s set to %s", var->name, var->string ?
713 			var->string : "<EMPTY>");
714 		break;
715 	}
716 	}
717 }
718 
719 /*
720  * set_variable: The SET command sets one of the irc variables.  The args
721  * should consist of "variable-name setting", where variable name can be
722  * partial, but non-ambbiguous, and setting depends on the variable being set
723  */
BUILT_IN_COMMAND(setcmd)724 BUILT_IN_COMMAND(setcmd)
725 {
726 	char	*var = NULL;
727 	int	cnt;
728 enum VAR_TYPES	sv_index;
729 	int	hook = 0;
730 
731 	/*
732 	 * XXX Ugh.  This is a hideous offense of good taste which is
733 	 * necessary to support set's abominable syntax, particularly
734 	 * acute with /set continued_line<space><space>
735 	 */
736 	while (args && *args && isspace(*args))
737 		args++;
738 	var = args;
739 	while (args && *args && !isspace(*args))
740 		args++;
741 	if (args && *args)
742 		*args++ = 0;
743 
744 	if (var && *var)
745 	{
746 		if (*var == '-')
747 		{
748 			var++;
749 			args = (char *) 0;
750 		}
751 
752 		/* Exact match? */
753 		upper(var);
754 		find_fixed_array_item (irc_variable, sizeof(IrcVariable), NUMBER_OF_VARIABLES, var, &cnt, (int *)&sv_index);
755 
756 		if (cnt == 1)
757 			cnt = -1;
758 
759 		if ((cnt >= 0) || !(irc_variable[sv_index].int_flags & VIF_PENDING))
760 			hook = 1;
761 
762 		if (cnt < 0)
763 			irc_variable[sv_index].int_flags |= VIF_PENDING;
764 
765 		if (hook)
766 		{
767 			hook = do_hook(SET_LIST, "%s %s",
768 				var, args ? args : "<unset>");
769 
770 			if (hook && (cnt < 0))
771 			{
772 				hook = do_hook(SET_LIST, "%s %s",
773 					irc_variable[sv_index].name,
774 					args ? args : "<unset>");
775 			}
776 		}
777 
778 		if (cnt < 0)
779 			irc_variable[sv_index].int_flags &= ~VIF_PENDING;
780 
781 		if (hook)
782 		{
783 			if (cnt < 0)
784 				set_var_value(sv_index, args);
785 			else if (cnt == 0)
786 			{
787 				if (do_hook(SET_LIST, "set-error No such variable \"%s\"", var))
788 					say("No such variable \"%s\"", var);
789 			}
790 			else
791 			{
792 				if (do_hook(SET_LIST, "set-error %s is ambiguous", var))
793 				{
794 					say("%s is ambiguous", var);
795 					for (cnt += sv_index; (int)sv_index < cnt; sv_index = (enum VAR_TYPES)(sv_index + 1))
796 						set_var_value(sv_index, empty_string);
797 				}
798 			}
799 		}
800 	}
801 	else
802         {
803 		int var_index;
804 		for (var_index = 0; var_index < NUMBER_OF_VARIABLES; var_index++)
805 			set_var_value(var_index, empty_string);
806         }
807 }
808 
809 /*
810  * get_string_var: returns the value of the string variable given as an index
811  * into the variable table.  Does no checking of variable types, etc
812  */
get_string_var(enum VAR_TYPES var)813 char *	get_string_var (enum VAR_TYPES var)
814 {
815 	return (irc_variable[var].string);
816 }
817 
818 /*
819  * get_int_var: returns the value of the integer string given as an index
820  * into the variable table.  Does no checking of variable types, etc
821  */
get_int_var(enum VAR_TYPES var)822 int 	get_int_var (enum VAR_TYPES var)
823 {
824 	return (irc_variable[var].integer);
825 }
826 
827 /*
828  * get_int_var: returns the value of the integer string given as an index
829  * into the variable table.  Does no checking of variable types, etc
830  */
get_float_var(enum VAR_TYPES var)831 double 	get_float_var (enum VAR_TYPES var)
832 {
833 	return (irc_variable[var].number);
834 }
835 
836 /*
837  * set_string_var: sets the string variable given as an index into the
838  * variable table to the given string.  If string is null, the current value
839  * of the string variable is freed and set to null
840  */
set_string_var(enum VAR_TYPES var,const char * string)841 void 	set_string_var (enum VAR_TYPES var, const char *string)
842 {
843 	if (string)
844 		malloc_strcpy(&(irc_variable[var].string), string);
845 	else
846 		new_free(&(irc_variable[var].string));
847 }
848 
849 /* Same story, second verse. */
set_int_var(enum VAR_TYPES var,int value)850 void 	set_int_var (enum VAR_TYPES var, int value)
851 {
852 	irc_variable[var].integer = value;
853 }
854 
855 /* Same story, second verse. */
set_float_var(enum VAR_TYPES var,double value)856 void 	set_float_var (enum VAR_TYPES var, double value)
857 {
858 	irc_variable[var].number = value;
859 }
860 
861 /*
862  * save_variables: this writes all of the IRCII variables to the given FILE
863  * pointer in such a way that they can be loaded in using LOAD or the -l switch
864  */
save_variables(FILE * fp,int do_all)865 void 	save_variables (FILE *fp, int do_all)
866 {
867 	IrcVariable *var;
868 
869 	for (var = irc_variable; var->name; var++)
870 	{
871 		if (!(var->int_flags & VIF_CHANGED))
872 			continue;
873 		if (do_all || !(var->int_flags & VIF_GLOBAL))
874 		{
875 			if (strcmp(var->name, "DISPLAY") == 0 || strcmp(var->name, "CLIENT_INFORMATION") == 0)
876 				continue;
877 			fprintf(fp, "SET ");
878 			switch (var->type)
879 			{
880 			case BOOL_TYPE_VAR:
881 				fprintf(fp, "%s %s\n", var->name, var->integer ?
882 					var_settings[ON] : var_settings[OFF]);
883 				break;
884 			case CHAR_TYPE_VAR:
885 				fprintf(fp, "%s %c\n", var->name, var->integer);
886 				break;
887 			case INT_TYPE_VAR:
888 				fprintf(fp, "%s %u\n", var->name, var->integer);
889 				break;
890 			case FLOAT_TYPE_VAR:
891 				fprintf(fp, "%s %f\n", var->name, var->number);
892 				break;
893 			case STR_TYPE_VAR:
894 				if (var->string)
895 					fprintf(fp, "%s %s\n", var->name,
896 						var->string);
897 				else
898 					fprintf(fp, "-%s\n", var->name);
899 				break;
900 			}
901 		}
902 	}
903 }
904 
make_string_var(const char * var_name)905 char 	*make_string_var (const char *var_name)
906 {
907 	enum VAR_TYPES	msv_index;
908 	char	*ret = (char *) 0;
909 	char	*copy;
910 
911 	copy = LOCAL_COPY(var_name);
912 	upper(copy);
913 
914 	msv_index = get_variable_index(copy);
915 	if (msv_index == NUMBER_OF_VARIABLES)
916 		return NULL;
917 
918 	switch (irc_variable[msv_index].type)
919 	{
920 		case STR_TYPE_VAR:
921 		        if (irc_variable[msv_index].string)
922 			    ret = malloc_strdup(irc_variable[msv_index].string);
923 			break;
924 		case INT_TYPE_VAR:
925 			ret = malloc_strdup(ltoa(irc_variable[msv_index].integer));
926 			break;
927 		case FLOAT_TYPE_VAR:
928 			ret = malloc_strdup(ftoa(irc_variable[msv_index].number));
929 			break;
930 		case BOOL_TYPE_VAR:
931 			ret = malloc_strdup(var_settings[irc_variable[msv_index].integer]);
932 			break;
933 		case CHAR_TYPE_VAR:
934 			ret = malloc_dupchar(irc_variable[msv_index].integer);
935 			break;
936 	}
937 	return (ret);
938 
939 }
940 
GET_FIXED_ARRAY_NAMES_FUNCTION(get_set,irc_variable)941 GET_FIXED_ARRAY_NAMES_FUNCTION(get_set, irc_variable)
942 
943 /* returns the size of the character set */
944 int 	charset_size (void)
945 {
946 	return get_int_var(EIGHT_BIT_CHARACTERS_VAR) ? 256 : 128;
947 }
948 
eight_bit_characters(const void * stuff)949 static void 	eight_bit_characters (const void *stuff)
950 {
951 	int	value = *(const int *)stuff;
952 
953 	if (value == ON && !term_eight_bit())
954 		say("Warning!  Your terminal says it does not support eight bit characters");
955 	set_term_eight_bit(value);
956 }
957 
set_realname(const void * stuff)958 static void 	set_realname (const void *stuff)
959 {
960 	const char *value = (const char *)stuff;
961 
962 	if (!value)
963 	{
964 		say("Unsetting your realname will do you no good.  So there.");
965 		value = empty_string;
966 	}
967 	strlcpy(realname, value, sizeof realname);
968 }
969 
set_display_pc_characters(const void * stuff)970 static void 	set_display_pc_characters (const void *stuff)
971 {
972 	int	value = *(const int *)stuff;
973 
974 	if (value < 0 || value > 5)
975 	{
976 		say("The value of DISPLAY_PC_CHARACTERS must be between 0 and 5 inclusive");
977 		set_int_var(DISPLAY_PC_CHARACTERS_VAR, 0);
978 	}
979 }
980 
set_dcc_timeout(const void * stuff)981 static void	set_dcc_timeout (const void *stuff)
982 {
983 	int	value = *(const int *)stuff;
984 
985 	if (value == 0)
986 		dcc_timeout = (time_t) -1;
987 	else
988 		dcc_timeout = value;
989 }
990 
parse_mangle(const char * value,int nvalue,char ** rv)991 int	parse_mangle (const char *value, int nvalue, char **rv)
992 {
993 	char	*str1, *str2;
994 	char	*copy;
995 	char	*nv = NULL;
996 
997 	if (rv)
998 		*rv = NULL;
999 
1000 	if (!value)
1001 		return 0;
1002 
1003 	copy = LOCAL_COPY(value);
1004 
1005 	while ((str1 = new_next_arg(copy, &copy)))
1006 	{
1007 		while (*str1 && (str2 = next_in_comma_list(str1, &str1)))
1008 		{
1009 			     if (!my_strnicmp(str2, "ALL_OFF", 4))
1010 				nvalue |= STRIP_ALL_OFF;
1011 			else if (!my_strnicmp(str2, "-ALL_OFF", 5))
1012 				nvalue &= ~(STRIP_ALL_OFF);
1013 			else if (!my_strnicmp(str2, "ALL", 3))
1014 				nvalue = (0x7FFFFFFF ^ (MANGLE_ESCAPES) ^ (STRIP_OTHER));
1015 			else if (!my_strnicmp(str2, "-ALL", 4))
1016 				nvalue = 0;
1017 			else if (!my_strnicmp(str2, "ALT_CHAR", 3))
1018 				nvalue |= STRIP_ALT_CHAR;
1019 			else if (!my_strnicmp(str2, "-ALT_CHAR", 4))
1020 				nvalue &= ~(STRIP_ALT_CHAR);
1021 			else if (!my_strnicmp(str2, "ANSI", 2))
1022 				nvalue |= MANGLE_ANSI_CODES;
1023 			else if (!my_strnicmp(str2, "-ANSI", 3))
1024 				nvalue &= ~(MANGLE_ANSI_CODES);
1025 			else if (!my_strnicmp(str2, "BLINK", 2))
1026 				nvalue |= STRIP_BLINK;
1027 			else if (!my_strnicmp(str2, "-BLINK", 3))
1028 				nvalue &= ~(STRIP_BLINK);
1029 			else if (!my_strnicmp(str2, "BOLD", 2))
1030 				nvalue |= STRIP_BOLD;
1031 			else if (!my_strnicmp(str2, "-BOLD", 3))
1032 				nvalue &= ~(STRIP_BOLD);
1033 			else if (!my_strnicmp(str2, "COLOR", 1))
1034 				nvalue |= STRIP_COLOR;
1035 			else if (!my_strnicmp(str2, "-COLOR", 2))
1036 				nvalue &= ~(STRIP_COLOR);
1037 			else if (!my_strnicmp(str2, "ESCAPE", 1))
1038 				nvalue |= MANGLE_ESCAPES;
1039 			else if (!my_strnicmp(str2, "-ESCAPE", 2))
1040 				nvalue &= ~(MANGLE_ESCAPES);
1041 			else if (!my_strnicmp(str2, "ND_SPACE", 2))
1042 				nvalue |= STRIP_ND_SPACE;
1043 			else if (!my_strnicmp(str2, "-ND_SPACE", 3))
1044 				nvalue &= ~(STRIP_ND_SPACE);
1045 			else if (!my_strnicmp(str2, "NONE", 2))
1046 				nvalue = 0;
1047 			else if (!my_strnicmp(str2, "OTHER", 2))
1048 				nvalue |= STRIP_OTHER;
1049 			else if (!my_strnicmp(str2, "-OTHER", 3))
1050 				nvalue &= ~(STRIP_OTHER);
1051 			else if (!my_strnicmp(str2, "REVERSE", 2))
1052 				nvalue |= STRIP_REVERSE;
1053 			else if (!my_strnicmp(str2, "-REVERSE", 3))
1054 				nvalue &= ~(STRIP_REVERSE);
1055 			else if (!my_strnicmp(str2, "ROM_CHAR", 2))
1056 				nvalue |= STRIP_ROM_CHAR;
1057 			else if (!my_strnicmp(str2, "-ROM_CHAR", 3))
1058 				nvalue &= ~(STRIP_ROM_CHAR);
1059 			else if (!my_strnicmp(str2, "UNDERLINE", 1))
1060 				nvalue |= STRIP_UNDERLINE;
1061 			else if (!my_strnicmp(str2, "-UNDERLINE", 2))
1062 				nvalue &= ~(STRIP_UNDERLINE);
1063 		}
1064 	}
1065 
1066 	if (rv)
1067 	{
1068 		if (nvalue & MANGLE_ESCAPES)
1069 			malloc_strcat_wordlist(&nv, comma, "ESCAPE");
1070 		if (nvalue & MANGLE_ANSI_CODES)
1071 			malloc_strcat_wordlist(&nv, comma, "ANSI");
1072 		if (nvalue & STRIP_COLOR)
1073 			malloc_strcat_wordlist(&nv, comma, "COLOR");
1074 		if (nvalue & STRIP_REVERSE)
1075 			malloc_strcat_wordlist(&nv, comma, "REVERSE");
1076 		if (nvalue & STRIP_UNDERLINE)
1077 			malloc_strcat_wordlist(&nv, comma, "UNDERLINE");
1078 		if (nvalue & STRIP_BOLD)
1079 			malloc_strcat_wordlist(&nv, comma, "BOLD");
1080 		if (nvalue & STRIP_BLINK)
1081 			malloc_strcat_wordlist(&nv, comma, "BLINK");
1082 		if (nvalue & STRIP_ALT_CHAR)
1083 			malloc_strcat_wordlist(&nv, comma, "ALT_CHAR");
1084 		if (nvalue & STRIP_ROM_CHAR)
1085 			malloc_strcat_wordlist(&nv, comma, "ROM_CHAR");
1086 		if (nvalue & STRIP_ND_SPACE)
1087 			malloc_strcat_wordlist(&nv, comma, "ND_SPACE");
1088 		if (nvalue & STRIP_ALL_OFF)
1089 			malloc_strcat_wordlist(&nv, comma, "ALL_OFF");
1090 		if (nvalue & STRIP_OTHER)
1091 			malloc_strcat_wordlist(&nv, comma, "OTHER");
1092 
1093 		*rv = nv;
1094 	}
1095 
1096 	return nvalue;
1097 }
1098 
set_mangle_inbound(const void * stuff)1099 static	void	set_mangle_inbound (const void *stuff)
1100 {
1101 	const char *value = (const char *)stuff;
1102 	char *nv = NULL;
1103 	inbound_line_mangler = parse_mangle(value, inbound_line_mangler, &nv);
1104 	set_string_var(MANGLE_INBOUND_VAR, nv);
1105 	new_free(&nv);
1106 }
1107 
set_mangle_outbound(const void * stuff)1108 static	void	set_mangle_outbound (const void *stuff)
1109 {
1110 	const char *value = (const char *)stuff;
1111 	char *nv = NULL;
1112 	outbound_line_mangler = parse_mangle(value, outbound_line_mangler, &nv);
1113 	set_string_var(MANGLE_OUTBOUND_VAR, nv);
1114 	new_free(&nv);
1115 }
1116 
set_mangle_logfiles(const void * stuff)1117 static	void	set_mangle_logfiles (const void *stuff)
1118 {
1119 	const char *value = (const char *)stuff;
1120 	char *nv = NULL;
1121 	logfile_line_mangler = parse_mangle(value, logfile_line_mangler, &nv);
1122 	set_string_var(MANGLE_LOGFILES_VAR, nv);
1123 	new_free(&nv);
1124 }
1125 
set_scroll(const void * stuff)1126 static	void	set_scroll (const void *stuff)
1127 {
1128 	int	value = *(const int *)stuff;
1129 	char *	whatever;
1130 	int	owd = window_display;
1131 
1132 	window_display = 0;
1133 	if (value)
1134 	{
1135 		whatever = LOCAL_COPY("ONE");
1136 		window_scroll(current_window, &whatever);
1137 	}
1138 	else
1139 	{
1140 		whatever = LOCAL_COPY("ZERO");
1141 		window_scroll(current_window, &whatever);
1142 	}
1143 	window_display = owd;
1144 }
1145 
update_all_status_wrapper(const void * stuff)1146 static void	update_all_status_wrapper (const void *stuff)
1147 {
1148 	update_all_status();
1149 }
1150 
set_highlight_char(const void * stuff)1151 static void    set_highlight_char (const void *stuff)
1152 {
1153 	const char *s = (const char *)stuff;
1154         int     len;
1155 
1156         if (!s)
1157                 s = empty_string;
1158         len = strlen(s);
1159 
1160         if (!my_strnicmp(s, "BOLD", len))
1161                 malloc_strcpy(&highlight_char, BOLD_TOG_STR);
1162         else if (!my_strnicmp(s, "INVERSE", len))
1163                 malloc_strcpy(&highlight_char, REV_TOG_STR);
1164         else if (!my_strnicmp(s, "UNDERLINE", len))
1165                 malloc_strcpy(&highlight_char, UND_TOG_STR);
1166         else
1167                 malloc_strcpy(&highlight_char, s);
1168 }
1169 
set_wserv_type(const void * stuff)1170 static void    set_wserv_type (const void *stuff)
1171 {
1172 	const char *s = (const char *)stuff;
1173 
1174         if (!s)
1175 		return;		/* It's ok */
1176 	if (!my_stricmp(s, "SCREEN"))
1177 		return;		/* It's ok */
1178 	if (!my_stricmp(s, "XTERM"))
1179 		return;		/* It's ok */
1180 
1181 	say("SET WSERV_TYPE must be either SCREEN or XTERM");
1182 	set_string_var(WSERV_TYPE_VAR, NULL);
1183 }
1184 
1185 
1186 /*******/
1187 typedef struct	varstacklist
1188 {
1189 	char *	varname;
1190 	char *	value;
1191 	struct varstacklist *next;
1192 }	VarStack;
1193 
1194 VarStack *set_stack = NULL;
1195 
do_stack_set(int type,char * args)1196 void	do_stack_set (int type, char *args)
1197 {
1198 	VarStack *item;
1199 	char *varname = NULL;
1200 
1201 	if (set_stack == NULL && (type == STACK_POP || type == STACK_LIST))
1202 	{
1203 		say("Set stack is empty!");
1204 		return;
1205 	}
1206 
1207 	if (STACK_PUSH == type)
1208 	{
1209 		varname = next_arg(args, &args);
1210 		if (!varname)
1211 		{
1212 			say("Must specify a variable name to stack");
1213 			return;
1214 		}
1215 		upper(varname);
1216 
1217 		item = (VarStack *)new_malloc(sizeof(VarStack));
1218 		item->varname = malloc_strdup(varname);
1219 		item->value = make_string_var(varname);
1220 
1221 		item->next = set_stack;
1222 		set_stack = item;
1223 		return;
1224 	}
1225 
1226 	else if (STACK_POP == type)
1227 	{
1228 	    VarStack *prev = NULL;
1229 	    enum VAR_TYPES var_index;
1230 	    int	owd = window_display;
1231 
1232 	    varname = next_arg(args, &args);
1233 	    if (!varname)
1234 	    {
1235 		say("Must specify a variable name to stack");
1236 		return;
1237 	    }
1238 	    upper(varname);
1239 
1240 	    for (item = set_stack; item; prev = item, item = item->next)
1241 	    {
1242 		/* If this is not it, go to the next one */
1243 		if (my_stricmp(varname, item->varname))
1244 			continue;
1245 
1246 		/* remove it from the list */
1247 		if (prev == NULL)
1248 			set_stack = item->next;
1249 		else
1250 			prev->next = item->next;
1251 
1252 		window_display = 0;
1253 		var_index = get_variable_index(item->varname);
1254 		if (var_index == NUMBER_OF_VARIABLES)
1255 			return;		/* Do nothing */
1256 		set_var_value(var_index, item->value);
1257 		window_display = owd;
1258 
1259 		new_free(&item->varname);
1260 		new_free(&item->value);
1261 		new_free(&item);
1262 		return;
1263 	    }
1264 
1265 	    say("%s is not on the Set stack!", varname);
1266 	    return;
1267 	}
1268 
1269 	else if (STACK_LIST == type)
1270 	{
1271 	    VarStack *prev = NULL;
1272 
1273 	    for (item = set_stack; item; prev = item, item = item->next)
1274 		say("Variable [%s] = %s", item->varname, item->value ? item->value : "<EMPTY>");
1275 
1276 	    return;
1277 	}
1278 
1279 	else
1280 		say("Unknown STACK type ??");
1281 }
1282 
1283