Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/source/commands.c
1069 views
1
/*
2
* commands.c: This is really a mishmash of function and such that deal with IRCII
3
* commands (both normal and keybinding commands)
4
*
5
* Written By Michael Sandrof
6
* Portions are based on EPIC.
7
* Modified by panasync (Colten Edwards) 1995-97
8
* Copyright(c) 1990
9
* Random Ircname by Christian Deimel
10
*
11
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
12
*/
13
14
#include "irc.h"
15
static char cvsrevision[] = "$Id: commands.c 206 2012-06-13 12:34:32Z keaston $";
16
CVS_REVISION(commands_c)
17
18
/* These headers are for the local-address-finding routines. */
19
#ifdef IPV6
20
21
#include <net/if.h>
22
#include <ifaddrs.h>
23
24
#else /* IPV6 */
25
26
#include <sys/ioctl.h>
27
#include <sys/socket.h>
28
29
#ifndef SIOCGIFCONF
30
#include <sys/sockio.h>
31
#endif /* SIOCGIFCONF */
32
33
/* Some systems call it SIOCGIFCONF, some call it OSIOCGIFCONF */
34
#if defined(OSIOCGIFCONF)
35
#define SANE_SIOCGIFCONF OSIOCGIFCONF
36
#elif defined(SIOCGIFCONF)
37
#define SANE_SIOCGIFCONF SIOCGIFCONF
38
#endif
39
40
#ifdef HAVE_NET_IF_H
41
#include <net/if.h>
42
#endif /* HAVE_NET_IF_H */
43
44
#endif /* IPV6 */
45
46
#include <sys/stat.h>
47
#include "struct.h"
48
#include "commands.h"
49
#include "parse.h"
50
#include "server.h"
51
#include "chelp.h"
52
#include "encrypt.h"
53
#include "vars.h"
54
#include "ircaux.h"
55
#include "lastlog.h"
56
#include "log.h"
57
#include "window.h"
58
#include "screen.h"
59
#include "ircterm.h"
60
#include "who.h"
61
#include "hook.h"
62
#include "input.h"
63
#include "ignore.h"
64
#include "keys.h"
65
#include "names.h"
66
#include "alias.h"
67
#include "history.h"
68
#include "funny.h"
69
#include "ctcp.h"
70
#include "dcc.h"
71
#include "output.h"
72
#include "exec.h"
73
#include "notify.h"
74
#include "numbers.h"
75
#include "status.h"
76
#include "if.h"
77
#include "help.h"
78
#include "stack.h"
79
#include "queue.h"
80
#include "timer.h"
81
#include "list.h"
82
#include "userlist.h"
83
#include "misc.h"
84
#include "alist.h"
85
#include "tcl_bx.h"
86
#include "hash2.h"
87
#include "cset.h"
88
#include "notice.h"
89
90
#ifdef TRANSLATE
91
#include "translat.h"
92
#endif
93
94
#ifdef WANT_CD
95
#include "cdrom.h"
96
#endif
97
98
#define MAIN_SOURCE
99
#include "modval.h"
100
101
#ifdef WANT_TCL
102
Tcl_Interp *tcl_interp = NULL;
103
#endif
104
105
#define COMMENT_HACK
106
107
extern int doing_notice;
108
109
/* Used to handle and catch breaks and continues */
110
int will_catch_break_exceptions = 0;
111
int will_catch_continue_exceptions = 0;
112
int will_catch_return_exceptions = 0;
113
int break_exception = 0;
114
int continue_exception = 0;
115
int return_exception = 0;
116
117
118
119
static void oper_password_received (char *, char *);
120
121
int no_hook_notify = 0;
122
int load_depth = -1;
123
124
extern char cx_function[];
125
126
/* used with /save */
127
#define SFLAG_ALIAS 0x0001
128
#define SFLAG_ASSIGN 0x0002
129
#define SFLAG_BIND 0x0004
130
#define SFLAG_ON 0x0008
131
#define SFLAG_SET 0x0010
132
#define SFLAG_NOTIFY 0x0020
133
#define SFLAG_SERVER 0x0040
134
#define SFLAG_DIGRAPH 0x0080
135
#define SFLAG_WATCH 0x0100
136
#define SFLAG_ALL 0xffff
137
138
/* The maximum number of recursive LOAD levels allowed */
139
#define MAX_LOAD_DEPTH 10
140
141
int interactive = 0;
142
143
144
typedef struct WaitCmdstru
145
{
146
char *stuff;
147
struct WaitCmdstru *next;
148
} WaitCmd;
149
150
static WaitCmd *start_wait_list = NULL,
151
*end_wait_list = NULL;
152
153
char lame_wait_nick[] = "***LW***";
154
char wait_nick[] = "***W***";
155
156
#ifdef WANT_DLL
157
IrcCommandDll *find_dll_command (char *, int *);
158
IrcCommandDll *dll_commands = NULL;
159
#endif
160
161
162
AJoinList *ajoin_list = NULL;
163
164
/*
165
* irc_command: all the availble irc commands: Note that the first entry has
166
* a zero length string name and a null server command... this little trick
167
* makes "/ blah blah blah" to always be sent to a channel, bypassing queries,
168
* etc. Neato. This list MUST be sorted.
169
*/
170
171
BUILT_IN_COMMAND(debug_user);
172
BUILT_IN_COMMAND(debugmsg);
173
BUILT_IN_COMMAND(debughook);
174
BUILT_IN_COMMAND(evalserver);
175
BUILT_IN_COMMAND(purge);
176
BUILT_IN_COMMAND(debugfunc);
177
BUILT_IN_COMMAND(url_grabber);
178
BUILT_IN_COMMAND(breakcmd);
179
BUILT_IN_COMMAND(returncmd);
180
BUILT_IN_COMMAND(continuecmd);
181
BUILT_IN_COMMAND(check_clones);
182
BUILT_IN_COMMAND(usleepcmd);
183
BUILT_IN_COMMAND(pastecmd);
184
BUILT_IN_COMMAND(oper);
185
BUILT_IN_COMMAND(epichelp);
186
BUILT_IN_COMMAND(spam);
187
BUILT_IN_COMMAND(do_mtopic);
188
BUILT_IN_COMMAND(xevalcmd);
189
BUILT_IN_COMMAND(send_kline);
190
BUILT_IN_COMMAND(show_revisions);
191
192
#ifdef GUI
193
BUILT_IN_COMMAND(os2popupmenu);
194
BUILT_IN_COMMAND(os2popupmsg);
195
BUILT_IN_COMMAND(pmpaste);
196
BUILT_IN_COMMAND(pmprop);
197
BUILT_IN_COMMAND(os2menu);
198
BUILT_IN_COMMAND(os2menuitem);
199
BUILT_IN_COMMAND(os2submenu);
200
#endif
201
202
#ifdef __EMXPM__
203
BUILT_IN_COMMAND(pmcodepage);
204
#endif
205
206
#ifdef WANT_CHAN_NICK_SERV
207
BUILT_IN_COMMAND(e_server);
208
#endif
209
210
#ifdef ALLOW_DETACH
211
BUILT_IN_COMMAND(detachcmd);
212
#endif
213
214
215
char relay_help[] = "%R[%n-list|-kick|-wall|-wallop|-msg|-notice|-topic|-kboot|-ansi|-kill|-help%R]%n %Y<%n#|channel|nick%Y> <%nchannel|nick%Y>";
216
char scripting_command[] = "- Scripting command";
217
218
IrcCommand irc_command[] =
219
{
220
{ "", empty_string, do_send_text, 0, NULL },
221
{ "#", NULL, comment, 0, NULL },
222
{ "4OP", NULL, do_4op, SERVERREQ, "%Y<%Cnick%Y>%n\n- Sets mode +oooo on %Y<%Cnick%Y>%n"},
223
{ ":", NULL, comment, 0, NULL },
224
{ "ABORT", NULL, abortcmd, 0, "- Saves IRCII settings then exits IRC" },
225
{ "ABOUT", NULL, about, 0, "- Shows yet another ansi screen with greets to people who have contributed to the %PBitchX%n project"},
226
{ "ADDFORWARD", "AddForward", do_forward, 0, "%Y<%Bchannel%G|%Cnick%Y>%n\n - Forward all messages to %Y<%Bchannel%G|%Cnick%Y>%n" },
227
{ "ADDIDLE", "AddIdle", addidle, 0, "%Y<%Bchannel%Y>%n %R[%nseconds%R]%n\n- Adds %Y<%Bchannel%Y>%n as idle channel with %R[%nseconds%R]%n" },
228
{ "ADDLAMENICK","AddLameNick", add_bad_nick, 0, "%Y<%Cnick%G|%Cnick%C nick nick%Y>%n\n - Adds %Y<%Cnick%Y>%n to your lame nicklist, bans nick!*@*"},
229
{ "ADDNOFLOOD", "AddNoFlood", add_no_flood, 0, "%Y<%Cnick%Y>%n\n - Adds %Cnick%n to your no flood list" },
230
#ifdef WANT_USERLIST
231
{ "ADDSHIT", "AddShit", add_shit, 0, "%Y<%Cnick%G|%Cnick%G!%nuser%Y@%nhostname%Y>%n %Y<%Bchannel%G|%Y*>%n %R[%nshitlevel%R]%n %R[%nreason%R]%n\n- Add %Y<%Cnick%G|%Cnick%G!%nuser%Y@%nhostname%Y>%n to your shitlist on %Y<%Bchannel%G|%Y*>%n with %R[%nshitlevel%R]%n and for %R[%nreason%R]%n" },
232
{ "ADDUSER", "AddUser", add_user, 0, "%Y<%Cnick%G|%Cnick%G!%nuser%Y@%nhostname%Y>%n %Y<%Bchannel%G|%Y*>%n %R[%nuserlevel%R]%n %R[%nauto-op%R]%n %R[%nprotection%R]%n %R[%npassword%R]%n\n - Adds %Y<%Cnick%G|%Cnick%G!%nuser%Y@%nhostname%Y>%n on %Y<%Bchannel%G|%Y*>%n with %R[%nuserlevel%R]%n %R[%nauto-op%R]%n and %R[%nprotection%R]%n levels to your userlist" },
233
#endif
234
{ "ADDWORD", NULL, add_ban_word, 0, "%Y<%Bchannel%G|%Y*>%n %Y<%nword%y(%ns%y)%Y>%n\n- Adds %Y<%nword%y(%ns%y)%Y>%n to wordlist, anyone saying it in %Y<%Bchannel%G|%Y*>%n will be kicked" },
235
{ "ADMIN", "ADMIN", send_comm, SERVERREQ, "%R[%nserver%R]%n\n- Shows the iRC Administration information on current server or %R[%nserver%R]%n" },
236
{ "AJOIN", "AJoin", auto_join, 0, "%Y<%Bchannel%y(%Bs%y)%Y>%n\n- Add %Y<%Bchannel%y(%Bs%y)%Y>%n to AJoin list%P;%n it joins %Y<%Bchannel%y(%Bs%y)%Y>%n on startup or change of server" },
237
{ "AJOINLIST", "AJoinList", auto_join, 0, "- Display list of ajoin channels" },
238
{ "ALIAS", zero, aliascmd, 0, scripting_command },
239
{ "ASSIGN", one, assigncmd, 0, scripting_command },
240
{ "AWAY", "Away", away, SERVERREQ, "%R[%nreason%R]%n\n- Sets you away on server if %R[%nreason%R]%n else sets you back" },
241
{ "AWAYLOG", "AwayLog", awaylog, 0, "%R[%nALL|MSGS|NOTICES|...%R]%n\n- Displays or changes what you want logged in your lastlog. This is a comma separated list" },
242
{ "AWAYMSG", "AwayMsg", away, 0, "Sets your auto-away msg" },
243
{ "B", NULL, ban, SERVERREQ, "See %YBAN%n" },
244
{ "BACK", "Back", back, SERVERREQ, "- Sets you back from being away" },
245
{ "BAN", NULL, ban, 0, "%Y<%Cnick%G|%Cnick%G!%nuser%y@%nhostname%Y>%n\n- Ban %Y<%Cnick%G|%Cnick%G!%nuser%y@%nhostname%Y>%n from current channel" },
246
{ "BANSTAT", NULL, banstat, 0, "%R[%Bchannel%R]%n\n- Show bans on current channel or %R[%Bchannel%R]%n" },
247
{ "BANTYPE", NULL, bantype, 0, "%W/%nbantype %Y<%nNormal%G|%nBetter%G|%nHost%G|%nDomain%G|%nScrew%G|%nIP%Y>%n\n- When a ban is done on a nick, it uses %Y<%nbantype%Y>%n" },
248
{ "BANWORDS", NULL, add_ban_word, 0, "%Y<%nchannel|*%Y>%n word(s)\n- Adds word or words to the banned words list for %Y<%nchannel%Y>" },
249
{ "BEEP", NULL, beepcmd, 0, "- Creates a beep noise" },
250
#ifdef WANT_CHELP
251
{ "BHELP", "BHELP", chelp, 0, "%Y<%nhelp%W|%nindex%W|%nother%Y>%n\n - BitchX help command" },
252
#endif
253
{ "BIND", NULL, bindcmd, 0, "- Command to bind a key to a function" },
254
{ "BK", NULL, kickban, SERVERREQ, "%Y<%Cnick%Y>%n %R[%nreason%R]%n\n- Deops, bans and kicks %Y<%Cnick%Y>%n for %R[%nreason%R]%n" },
255
{ "BKI", "BKI", kickban, SERVERREQ, "%Y<%Cnick%Y>%n %R[%nreason%R]%n\n- Deops, bans, kicks and ignores %Y<%Cnick%Y>%n for %R[%nreason%R]%n" },
256
{ "BLESS", NULL, blesscmd, 0, scripting_command },
257
{ "BREAK", NULL, breakcmd, 0, NULL },
258
{ "BYE", "QUIT", e_quit, 0, "- Quit Irc"},
259
{ "C", "MODE", send_mode, 0, "%Y<%nnick|channel%Y> <%nmode%Y>%n\n- Sets a mode for a channel or nick"},
260
{ "CALL", NULL, e_call, 0, scripting_command },
261
#ifndef BITCHX_LITE
262
{ "CBOOT", "Cboot", cboot, 0, "%Y<%nnick%Y>%n %R[%nreason%R]%n\n- Kicks a %Y<%nnick%Y>%n off the TwilightZone with %R[%nreason%R]" },
263
#endif
264
{ "CD", NULL, cd, 0, "%Y<%ndir%Y>%n\n - Changes current directory to %Y<%ndir%Y>%n or prints current directory" },
265
#ifdef WANT_CDCC
266
{ "CDCC", NULL, cdcc, 0, "%Y<%ncommand%Y>%n\n- Channel, DOffer, Echo, Load, List, MinSpeed, Notice, Offer, PList, Queue, ReSend, Save, Type Describe Note" },
267
#endif
268
#ifdef WANT_CD
269
{ "CDEJECT", NULL, cd_eject, 0, NULL },
270
{ "CDHELP", NULL, cd_help, 0, NULL },
271
{ "CDLIST", NULL, cd_list, 0, NULL },
272
{ "CDPAUSE", NULL, cd_pause, 0, NULL },
273
{ "CDPLAY", NULL, cd_play, 0, NULL },
274
{ "CDSTOP", NULL, cd_stop, 0, NULL },
275
{ "CDVOL", NULL, cd_volume, 0, NULL },
276
#endif
277
{ "CHANNEL", "JOIN", e_channel, SERVERREQ, "- Shows information on the channels, modes and server you are on" },
278
#ifdef WANT_CHAN_NICK_SERV
279
{ "CHANSERV", "CHANSERV", send_comm, 0, NULL },
280
#endif
281
{ "CHANST", NULL, channel_stats, SERVERREQ, "%Y<%n-ALL%Y> %R[%Bchannel%R]%n\n- Shows statistics on current channel or %R[%Bchannel%R]%n" },
282
{ "CHAT", "Chat", chat, SERVERREQ, "%Y<%nNick%Y>%n\n- Attempts to dcc chat nick" },
283
{ "CHATOPS", "CHATOPS", e_wall, SERVERREQ, NULL },
284
#ifdef WANT_USERLIST
285
{ "CHGAOP", "ChgAop", change_user, 0, "%Y<%Cnick%Y>%n <auto-oplevel>" },
286
{ "CHGCHAN", "ChgChan", change_user, 0, "%Y<%Cnick%Y>%n %Y<%Bchannel%Y>%n" },
287
{ "CHGLEVEL", "ChgLevel", change_user, 0, "%Y<%Cnick%Y>%n %Y<%nlevel%Y>%n" },
288
{ "CHGPASS", "ChgPass", change_user, 0, "%Y<%Cnick%Y>%n %Y<%nprotection-level%Y>%n" },
289
{ "CHGPROT", "ChgProt", change_user, 0, "%Y<%Cnick%Y>%n %Y<%nprotection-level%Y>%n" },
290
{ "CHGUH", "ChgUH", change_user, 0, "%Y<%Cnick%Y>%n %Y<%nuserhost%Y>%n" },
291
#endif
292
{ "CHOPS", "Chops", users, SERVERREQ, "%R[%Bchannel%R]%n\n- Shows, in a full format, all the nicks with op status" },
293
{ "CLEAR", NULL, my_clear, 0, "- Clears the screen" },
294
{ "CLEARAUTO", "CLEARAUTO", clear_tab, 0, "- Clears all the nicks in the auto-response list" },
295
{ "CLEARLOCK", "ClearLock", mode_lock, 0, "%Y<%Cchannel%G|%Y*>%n\n- Unlocks the mode lock for %Y<%Cchannel%G|%Y*>%n" },
296
{ "CLEARTAB", NULL, clear_tab, 0, "- Clears the nicks in the tabkey list" },
297
#ifndef BITCHX_LITE
298
{ "CLINK", "Clink", clink, 0, "%Y<%Cnick%Y>%n %Y<%ntext%Y>%n" },
299
{ "CLONES", "Clones", check_clones, SERVERREQ, NULL },
300
{ "CMSG", "Cmsg", cmsg, 0, "%Y<%Cnick%Y>%n %Y<%ntext%Y>%n\n- While in the TwilightZone, a private message will be sent to %Y<%Cnick%Y>%n with %Y<%ntext%Y>%n" },
301
#else
302
{ "CLONES", "Clones", check_clones, SERVERREQ, NULL },
303
#endif
304
#ifdef __EMXPM__
305
{ "CODEPAGE", "CODEPAGE", pmcodepage, 0, "OS/2 - Changes the current VIO Codepage" },
306
#endif
307
{ "CONNECT", "CONNECT", send_comm, 0, "%Y<%nserver1%Y>%n %Y<%nport%Y>%n %R[%nserver2%R]%n\n%Y*%n Requires irc operator status" },
308
{ "CONTINUE", NULL, continuecmd, 0, NULL },
309
#ifndef BITCHX_LITE
310
{ "CSAY", "Csay", csay, 0, "%Y<%ntext%Y>%n" },
311
#endif
312
{ "CSET", "Cset", cset_variable, 0, "%R[%n*|channel|chan*%R]%n\n- changes variables that affect a channel or displays them" },
313
{ "CTCP", NULL, ctcp, SERVERREQ, "%Y<%Cnick%Y>%n %Y<%nrequest%Y>%n\n- CTCP sends %Y<%Cnick%Y>%n with %Y<%nrequest%Y>%n" },
314
#ifndef BITCHX_LITE
315
{ "CTOGGLE", NULL, toggle_xlink, 0, NULL },
316
{ "CWHO", "Cwho", cwho, 0, "- Lists the clients and bots connected to the TwilightZone" },
317
{ "CWHOM", "Cwhom", cwho, 0, "- Lists the clients and bots connected to the TwilightZone" },
318
#endif
319
{ "CYCLE", NULL, cycle, SERVERREQ, "%R[%Bchannel%R]%n\n- Leaves current channel or %R[%Bchannel%R]%n and immediately rejoins" },
320
{ "D", NULL, describe, SERVERREQ, "See %YDESCRIBE%n" },
321
{ "DATE", "TIME", send_comm, SERVERREQ, "- Shows current time and date from current server" },
322
{ "DBAN", NULL, unban, SERVERREQ, "- Clears all bans on current channel" },
323
{ "DC", NULL, init_dcc_chat, SERVERREQ, "%Y<%Cnick%Y>%n\n- Starts a DCC CHAT to %Y<%Cnick%Y>%n" },
324
{ "DCA", "Dca", dcx, 0, "- Kills all dcc connections" },
325
{ "DCC", NULL, dcc, 0, "Displays a active DCC list. For more info /dcc help" },
326
{ "DCG", "Dcg", dcx, 0, "%Y<%nnick%Y>%n\n- Kills all dcc gets to %Y<%nnick%Y>" },
327
{ "DCS", "Dcs", dcx, 0, "%Y<%nnick%Y>%n\n- Kills all dcc sends to %Y<%nnick%Y>" },
328
{ "DCX", "Dcx", dcx, 0, "%Y<%nnick%Y>%n\n- Kills all dcc chats to %Y<%nnick%Y>" },
329
{ "DEBUG", NULL, e_debug, 0, "%R[%nflags%R]%n\n- Sets various debug flags in the client" },
330
{ "DEBUGFUNC", NULL, debugfunc, 0, NULL },
331
{ "DEBUGHASH", NULL, show_hash, 0, NULL },
332
{ "DEBUGMSG", NULL, debugmsg, 0, NULL },
333
#ifdef WANT_USERLIST
334
{ "DEBUGUSER", NULL, debug_user, 0, NULL },
335
#endif
336
{ "DEHOP", "h", dodeop, SERVERREQ, "%Y<%C%nnick(s)%Y>%n\n- Removes halfops from %Y<%Cnick%y(%Cs%y)%Y>%n" },
337
{ "DEOP", "o", dodeop, SERVERREQ, "%Y<%C%nnick(s)%Y>%n\n- Deops %Y<%Cnick%y(%Cs%y)%Y>%n" },
338
{ "DEOPER", NULL, deop, SERVERREQ, "%Y*%n Requires irc operator status\n- Removes irc operator status" },
339
{ "DESCRIBE", NULL, describe, SERVERREQ, "%Y<%Cnick%G|%Bchannel%Y>%n %Y<%naction%Y>%n\n- Describes to %Y<%Cnick%G|%Bchannel%Y>%n with %Y<%naction%Y>%n" },
340
#ifdef ALLOW_DETACH
341
{ "DETACH", NULL, detachcmd, 0, NULL },
342
#endif
343
{ "DEVOICE", "v", dodeop, SERVERREQ, "%Y<%C%nnick(s)%Y>%n\n- de-voices %Y<%Cnick%y(%Cs%y)%Y>%n" },
344
#if !defined(WINNT) && !defined(__EMX__)
345
{ "DF", "df", exec_cmd, 0, "- Show disk space usage" },
346
#endif
347
{ "DIE", "DIE", send_comm, SERVERREQ, "%Y*%n Requires irc operator status\n- Kills the IRC server you are on" },
348
#ifdef TRANSLATE
349
{ "DIGRAPH", NULL, digraph, 0, NULL },
350
#endif
351
{ "DISCONNECT", NULL, disconnectcmd, 0, "- Disconnects you from the current server" },
352
{ "DLINE", "DLINE", send_kline, SERVERREQ, NULL },
353
{ "DME", "dme", me, SERVERREQ, "<action>\n- Sends an action to current dcc" },
354
{ "DNS", "NSlookup", nslookup, 0, "%YDNS<%nnick|hostname%y>%n\n- Attempts to nslookup on nick or hostname"},
355
{ "DO", NULL, docmd, 0, scripting_command },
356
{ "DOP", "o", dodeop, SERVERREQ, "- See deop" },
357
{ "DS", NULL, dcc_stat_comm, 0, "- Displays some dcc file transfer stats" },
358
{ "DUMP", "Dump", dumpcmd, 0, "%Y<%ntype%Y>%n\n- Dumps %Y<%ntype%Y>%n to screen\n%Y<%ntype%Y>%n:\n%YAlias%n %YAll%n %YBind%n %YChstats%n %YFsets%n\n%YFile%n %YOn%n %YVar%n %YTimers%n %YWsets%n %YCsets%n" },
359
{ "ECHO", NULL, echocmd, 0, "<text>\n- Echos text to the screen" },
360
#ifdef WANT_EPICHELP
361
{ "EHELP", NULL, epichelp, 0, NULL },
362
#endif
363
{ "ENCRYPT", NULL, encrypt_cmd, 0, NULL },
364
{ "EVAL", "EVAL", evalcmd, 0, scripting_command },
365
{ "EVALSERVER", NULL, evalserver, 0, "<refnum> <command> sends to <refnum> server command" },
366
#if !defined(WINNT)
367
{ "EXEC", NULL, execcmd, 0, "%Y<%ncommand%Y>%n\n- Executes %Y<%ncommand%Y>%n with the shell set from %PSHELL%n" },
368
#endif
369
{ "EXIT", "QUIT", e_quit, 0, "- Quits IRC" },
370
{ "FE", "Fe", fe, 0, scripting_command },
371
{ "FEC", "Fec", fe, 0, scripting_command },
372
#ifdef GUI
373
{ "FILEDIALOG", NULL, filedialog, 0, "GUI - File dialog" },
374
#endif
375
{ "FINGER", NULL, finger, 0, "%Y<%Cnick%Y>%n\n- Fetches finger info on %Y<%Cnick%Y>%n" },
376
{ "FK", "FK", masskick, SERVERREQ, "%Y<%Cnick%G!%nuser%Y@%nhostname%Y>%n%R[%nreason%R]%n\nFinds clienTs matching %Y<%Cnick%G!%nuser%Y@%nhostname%Y>%n and immediately kicks them from current channel for %R[%nreason%R]%n" },
377
{ "FLUSH", NULL, flush, 0, "- Flush ALL server output" },
378
#ifdef GUI
379
{ "FONTDIALOG", NULL, fontdialog, 0, "GUI - Font Dialog" },
380
#endif
381
{ "FOR", NULL, forcmd, 0, scripting_command },
382
{ "FOREACH", NULL, foreach, 0, scripting_command },
383
{ "FORWARD", "Forward", do_forward, 0, "%Y<%Cnick%Y>%n\n- Forwards all messages to %Y<%Cnick%Y>%n" },
384
{ "FPORTS", NULL, findports, 0, "%Y<%nhostname%Y>%n %R[%Y<%nlowport%Y>%n %Y<%nhighport%Y>%R]%n\n- Attempts to find ports on %Y<%nhostname%Y>%n on %R[%Y<%nlowport%Y>%n %Y<%n %Y<%nhighport%Y>%R]%n" },
385
{ "FPROT", "FProt", tog_fprot, 0, "- Toggles flood protection to be either on or off" },
386
{ "FSET", "Fset", fset_variable, 0, "- Setting various output formats" },
387
#ifdef WANT_FTP
388
{ "FTP", "Ftp", init_ftp, 0, "%Y<%nhostname%Y> %R[%nlogin%R] [%npassword%R] [%n-p port%R]%n\n- Open a ftp connection to a host" },
389
#endif
390
{ "FUCK", "Fuck", kickban, SERVERREQ, "%Y<%Cnick%Y>%n %R[%nreason%R]%n\n- Deops, bans and kicks %Y<%Cnick%Y>%n for %R[%nreason%R]%n" },
391
{ "FUCKEM", NULL, fuckem, SERVERREQ, NULL },
392
{ "GONE", "Gone", away, SERVERREQ, "%R[%nreason%R]%n\n- Sets you away on server if %R[%nreason%R]%n else sets you back. Does not announce to your channels." },
393
{ "HASH", "HASH", send_comm, SERVERREQ, "Server command"},
394
{ "HELP", NULL, help, 0, NULL },
395
#ifdef WANT_CHAN_NICK_SERV
396
{ "HELPOP", "HELPOP", send_comm, SERVERREQ, NULL },
397
{ "HELPSERV", "HELPSERV", send_comm, SERVERREQ, NULL },
398
#endif
399
{ "HISTORY", NULL, history, 0, "- Shows recently typed commands" },
400
{ "HOOK", NULL, hookcmd, 0, scripting_command },
401
{ "HOP", "h", doop, SERVERREQ, "%Y<%Cnick%Y>%n\n- Gives %Y<%Cnick%Y>%n +h" },
402
{ "HOST", "USERHOST", userhostcmd, 0, "- Shows host of yourself or %R[%Cnick%R]%n" },
403
{ "HOSTNAME", "HOSTNAME", e_hostname, 0, "%Y<%nhostname%Y>%n\n- Shows list of possible hostnames with option to change it on virtual hosts" },
404
{ "I", "INVITE", do_invite, SERVERREQ, "- See %YINVITE%n" },
405
{ "IF", "IF", ifcmd, 0, scripting_command },
406
{ "IG", "Ig", do_ig, 0, "+%G|%n-%Y<%Cnick%Y>%n\n- Ignores ALL except crap and public of nick!host matching %Y<%Cnick%Y>%n" },
407
{ "IGH", "IgH", do_ig, 0, "+%G|%n-%Y<%Cnick%Y>%n\n- Ignores ALL except crap and public of hostname matching %Y<%Cnick%Y>%n" },
408
{ "IGHT", "IgHt", do_ig, 0, "+%G|%n-%Y<%Cnick%Y>%n\n- Ignores ALL except crap and public of hostname matching %Y<%Cnick%Y>%n and expires this on a timer"},
409
{ "IGNORE", NULL, ignore, 0, NULL },
410
{ "IGT", "Igt", do_ig, 0, "+%G|%n-%Y<%Cnick%Y>%n\n- Ignores ALL except crap and public of nick!host matching %Y<%Cnick%Y>%n and expires this on a timer" },
411
{ "INFO", "INFO", info, 0, "- Shows current client info" },
412
{ "INPUT", "Input", inputcmd, 0, scripting_command },
413
{ "INPUT_CHAR", "Input_Char", inputcmd, 0, scripting_command },
414
{ "INVITE", "INVITE", do_invite, SERVERREQ, "%Y<%Cnick%Y>%n %R[%Bchannel%R]%n\n- Invites %Y<%Cnick%Y>%n to current channel or %R[%Bchannel%R]%n" },
415
#ifdef WANT_CHAN_NICK_SERV
416
{ "IRCIIHELP", "IRCIIHELP", send_comm, SERVERREQ, NULL },
417
#endif
418
{ "IRCHOST", "HOSTNAME", e_hostname, 0, "%Y<%nhostname%Y>%n\n- Shows list of possible hostnames with option to change it on virtual hosts" },
419
{ "IRCNAME", NULL, realname_cmd, 0, NULL },
420
{ "IRCUSER", NULL, set_username, 0, "<username>\n- Changes your <username>" },
421
{ "ISON", "ISON", isoncmd, SERVERREQ, NULL },
422
{ "J", "JOIN", e_channel, SERVERREQ, "%Y<%nchannel%Y> %R[%nkey%R]%n\n- Joins a %Y<%nchannel%Y>" },
423
{ "JNW", "Jnw", jnw, SERVERREQ, "%Y<%nchannel%Y> %R[%nkey%R]%n %R[%n-hide%R]%n\n- Joins a %Y<%nchannel%Y>%n in a new window"},
424
{ "JOIN", "JOIN", e_channel, SERVERREQ, NULL },
425
{ "K", NULL, dokick, SERVERREQ, "%Y<%Cnick%Y>%n %R[%nreason%R]%n\n- Kicks %Y<%Cnick%Y>%n for %R[%nreason%R]%n on current channel" },
426
{ "KB", "KB", kickban, SERVERREQ, "%Y<%Cnick%Y>%n %R[%nreason%R]%n\n- Deops, kicks and bans %Y<%Cnick%Y>%n for %R[%nreason%R]%n" },
427
{ "KBI", "KBI", kickban, SERVERREQ, "%Y<%Cnick%Y>%n %R[%nreason%R]%n\n- Deops, kicks and bans %Y<%Cnick%Y>%n for %R[%nreason%R]%n" },
428
{ "KICK", "KICK", send_kick, SERVERREQ, "%Y<%Bchannel%G|%Y*>%n %Y<%Cnick%Y>%n %R[%nreason%R]%n" },
429
{ "KICKIDLE", "KickIdle", kickidle, SERVERREQ, "%Y<%Bchannel%Y>%n\n- Kicks all idle people on %Y<%Bchannel%Y>%n" },
430
{ "KILL", "KILL", send_kill, SERVERREQ, "%Y<%Cnick%Y>%n %R[%nreason%R]%n\n%Y*%n Requires irc operator status\n- Kills %Y<%Cnick%Y>%n for %R[%nreason%R]%n" },
431
{ "KLINE", "KLINE", send_kline, SERVERREQ, "%Y<%nuser%y@%nhost%Y> <%nreason%Y>%n\n%Y*%n Requires irc operator status\n- Adds a K-line to the server configfile" },
432
{ "KNOCK", "KNOCK", send_channel_com, SERVERREQ, NULL },
433
{ "L", "PART", do_getout, SERVERREQ, "- See %YLEAVE" },
434
{ "LAMENICKLIST",NULL, add_bad_nick, 0, "- Lists nicks in your lame nick list" },
435
{ "LASTLOG", NULL, lastlog, 0, "-file filename%G|%n-clear%G|%n-max #%G|%n-liternal pat%G|%n-beep%G|%nlevel" },
436
{ "LEAVE", "PART", send_comm, SERVERREQ, "%Y<%Bchannel%Y>%n\n- Leaves current channel or %Y<%Bchannel%Y>%n" },
437
{ "LINKS", "LINKS", send_comm, SERVERREQ, "- Shows servers and links to other servers" },
438
{ "LIST", "LIST", funny_stuff, SERVERREQ, "- Lists all channels" },
439
#ifdef WANT_DLL
440
{ "LISTDLL", "LISTDLL", dll_load, 0, "- List currently loaded plugins" },
441
#endif
442
{ "LK", "LameKick", LameKick, SERVERREQ, "%R[%nreason%R]%n\n- Kicks all non +o people on current channel with %R[%nreason%R]%n" },
443
{ "LKW", "Lkw", lkw, SERVERREQ, "%R[%Bchannel%R]%n\n- Leave the current channel, killing the window in current channel or%R[%Bchannel%R]%n as well" },
444
{ "LLOOK", NULL, linklook, SERVERREQ, "%Y*%n Requires set %YLLOOK%n %RON%n\n- Lists all the servers which are current split from the IRC network" },
445
{ "LOAD", "LOAD", BX_load, 0, "filename\n- Loads filename as a irc script" },
446
#ifdef WANT_DLL
447
{ "LOADDLL", NULL, dll_load, 0, "filename.so\n- Loads filename as a dll"},
448
#endif
449
#ifdef WANT_TCL
450
{ "LOADTCL", NULL, tcl_load, 0, "filename.tcl\n- Loads a tcl file" },
451
#endif
452
453
{ "LOCAL", "2", localcmd, 0, scripting_command },
454
{ "LOCOPS", "LOCOPS", e_wall, SERVERREQ, NULL },
455
#if !defined(WINNT)
456
{ "LS", "ls", exec_cmd, 0, "- Displays list of file" },
457
#endif
458
{ "LUSERS", "LUSERS", send_comm, SERVERREQ, "- Shows stats on current server" },
459
{ "M", "PRIVMSG", e_privmsg, 0, "See %YMSG%n" },
460
{ "MAP", NULL, do_map, 0, "- Displays a map of the current servers"},
461
{ "MB", NULL, massban, SERVERREQ, "- Mass bans everybody on current channel" },
462
{ "MD", NULL, massdeop, SERVERREQ, "- Mass deops current channel" },
463
{ "MDOP", NULL, massdeop, SERVERREQ, "- Mass deops current channel" },
464
{ "MDVOICE", "MDVoice", massdeop, SERVERREQ, "- Mass de-voices current channel" },
465
{ "ME", NULL, me, SERVERREQ, "<action>\n- Sends an action to current channel" },
466
#ifdef WANT_CHAN_NICK_SERV
467
{ "MEMOSERV", "MEMOSERV", send_comm, SERVERREQ, NULL },
468
#endif
469
#ifdef GUI
470
{ "MENU", NULL, os2menu, 0, "GUI - Creates or removes a menu" },
471
{ "MENUITEM", NULL, os2menuitem, 0, "GUI - Adds a menuitem to a menu" },
472
#endif
473
{ "MESG", NULL, extern_write, 0, "<YesB|BNoB||BOnB|BOff>\n- Turns mesg <Yes|No|On|Off>" },
474
{ "MK", NULL, masskick, SERVERREQ, "- Mass kicks current channel" },
475
{ "MKB", "MKB", masskickban, SERVERREQ, "- Mass kick bans current channel" },
476
{ "MKNU", NULL, mknu, SERVERREQ, "- Mass kick bans non-userlist users on current channel" },
477
{ "MODE", "MODE", send_channel_com, SERVERREQ, "%Y<%n#channel%W|%nnick%Y>%B +-%Y<%nmode%Y>%n" },
478
{ "MODELOCK", "ModeLock", mode_lock, 0, "%Y<%Bchannel%Y>%n +%G|%n-%Y<%ninstampkl #%Y>%n\n- Locks %Y<%Bchannel%Y>%n with +%G|%n-%Y<%nmodes%Y>%n" },
479
{ "MOP", NULL, massop, SERVERREQ, "- Mass ops everybody on current channel" },
480
{ "MORE", "More", readlog, 0, "%R[%nfilename%R]%n\n- displays file in pages" },
481
{ "MOTD", "MOTD", send_comm, SERVERREQ, "%R[%nserver%R]%n\n- Shows MOTD on current server %R[%nserver%R]%n" },
482
{ "MSAY", "MSay", do_msay, 0, NULL },
483
{ "MSG", "PRIVMSG", e_privmsg, 0, "%Y<%C[=]nick%Y>%n %Y<%ntext%Y>%n\n- Send %Y<%Cnick%Y>%n a message with %Y<%ntext%Y>%n" },
484
{ "MTOPIC", "MTopic", do_mtopic, 0, NULL },
485
{ "MUB", NULL, unban, SERVERREQ, "- Mass unbans current channel" },
486
{ "MULT", NULL, multkick, SERVERREQ, "%Y<%nnick(s)%Y>%n %R[%nreason%R]%n\n- Kicks all %Y<%nnick(s)%Y>%n with %R[%nreason%R]" },
487
{ "MVOICE", "MVoice", massop, SERVERREQ, "%R[%Cnick%G|%Bchannel%G|%Cnick%Y!%Cuser%Y@%nhostname%Y]%n\n- Mass voice nicks matching %R[%Cnick%G|%Bchannel%G|%Cnick%Y!%Cuser%Y@%nhostname%Y]%n" },
488
{ "N", "NAMES", do_mynames, 0, NULL },
489
{ "NAMES", "NAMES", funny_stuff, SERVERREQ, "%R[%Bchannel%R]%n\n- Shows names on current channel or %R[%Bchannel%R]%n" },
490
{ "NEWNICK", NULL, newnick, 0, NULL },
491
{ "NEWUSER", NULL, newuser, 0, NULL },
492
{ "NICK", "NICK", e_nick, 0, "-Changes nick to specified nickname" },
493
#ifdef WANT_CHAN_NICK_SERV
494
{ "NICKSERV", "NICKSERV", send_comm, SERVERREQ, NULL },
495
#endif
496
{ "NOCHAT", "NoChat", chat, 0, "%Y<%nnick%Y>%n\n- Kills chat reqest from %Y<%nnick%Y>" },
497
{ "NOPS", "Nops", users, 0, "%R[%Bchannel%R]%n\n- Shows, in a full format, all the nicks without ops in %R[%Bchannel%R]%n or channel" },
498
{ "NOTE", "NOTE", send_comm, SERVERREQ, NULL },
499
{ "NOTICE", "NOTICE", e_privmsg, 0, "%Y<%Cnick%G|%Bchannel%Y> %Y<%ntext%Y>%n\n- Sends a notice to %Y<%Cnick%G|%Bchannel%Y> with %Y<%ntext%Y>%n" },
500
{ "NOTIFY", NULL, notify, 0, "%Y<%Cnick|+|-nick%Y>%n\n- Adds/displays/removes %Y<%Cnick%Y>%n to notify list" },
501
{ "NSLOOKUP", "NSLookup", nslookup, 0, "%Y<%nhostname%Y>%n\n- Returns the IP adress and IP number for %Y<%nhostname%Y>%n" },
502
{ "NWHOIS", NULL, nwhois, 0, "%Y<%Cnick|channel%Y>%n\n- Shows internal statistics for %Y<%Cnick%Y>%n" },
503
{ "NWHOWAS", NULL, whowas, 0, "- Displays internal whowas info for all channels. This information expires after 20 minutes for users on internal list, 10 minutes for others" },
504
{ "OFFERS", "Offers", do_offers, 0, NULL },
505
{ "ON", NULL, oncmd, 0, scripting_command },
506
{ "OOPS", NULL, do_oops, SERVERREQ, "%Y<%Cnick%Y>%n\n- Sends a oops message to last recipient of a message and sends the correct message to %Y<%Cnick%Y>%n" },
507
{ "OP", "o", doop, SERVERREQ, "%Y<%Cnick%Y>%n\n- Gives %Y<%Cnick%Y>%n +o" },
508
{ "OPER", "OPER", oper, SERVERREQ, "%Y*%n Requires irc operator status\n%Y<%Cnick%Y>%n %R[%npassword%R]%n" },
509
#ifdef WANT_CHAN_NICK_SERV
510
{ "OPERSERV", "OPERSERV", send_comm, SERVERREQ, NULL },
511
#endif
512
{ "OPERWALL", "OPERWALL", e_wall, 0, NULL },
513
{ "ORIGNICK", "OrigNick", orig_nick, 0, "%Y<%Cnick%Y>%n\n- Attempts to regain a nick that someone else has taken from you." },
514
{ "OSTAT", NULL, serv_stat, 0, "-Displays some internal statistics gathered about the server" },
515
#ifdef WANT_OPERVIEW
516
{ "OV", NULL, ov_window, 0, "%R[%non|off%R]%n %R[%-hide|+hide|hide%R]%n\n- turns on/off oper view window as well as creating hidden window" },
517
#endif
518
{ "P", "Ping", pingcmd, 0, "%Y<%nnick%Y>%n\n- Pings %Y<%nnick%Y>" },
519
{ "PARSEKEY", NULL, parsekeycmd, 0, scripting_command },
520
{ "PART", "PART", send_2comm, 0, "- Leaves %Y<%nchannel%Y>%n" },
521
{ "PARTALL", "PARTALL", do_getout, 0, "- Leaves all channels" },
522
{ "PASTE", NULL, pastecmd, 0, NULL },
523
{ "PAUSE", NULL, e_pause, 0, scripting_command },
524
{ "PING", NULL, pingcmd, 0, "%Y<%nnick%Y>%n\n- Pings %Y<%nnick%Y>" },
525
#ifdef GUI
526
{ "PMPASTE", NULL, pmpaste, 0, "GUI - Clipboard Paste Command" },
527
#endif
528
{ "POP", NULL, pop_cmd, 0, scripting_command },
529
#ifdef GUI
530
{ "POPUPMENU", NULL, os2popupmenu, 0, "GUI - Popup Menu Command" },
531
{ "POPUPMSG", NULL, os2popupmsg, 0, "GUI - Popup Message Command" },
532
#endif
533
{ "PRETEND", NULL, pretend_cmd, 0, scripting_command },
534
#ifdef GUI
535
{ "PROPERTIES", NULL, pmprop, 0, "GUI - Properies Dialog" },
536
#endif
537
{ "PS", "ps", exec_cmd, 0, "- Displays process table" },
538
{ "PURGE", NULL, purge, 0, "<variable>\n- Removes all traces of variable(s) specified"},
539
{ "PUSH", NULL, push_cmd, 0, scripting_command },
540
{ "Q", NULL, query, 0, "%Y<%n-cmd cmdname%Y> <%Cnick%Y>%n\n- Starts a query to %Y<%Cnick%Y>%n" },
541
{ "QME", "qme", me, 0, "- Sends a action to a query" },
542
{ "QUERY", NULL, query, 0, "%Y<%n-cmd cmdname%Y> <%Cnick%Y>%n\n- Starts a query to %Y<%Cnick%Y>%n" },
543
{ "QUEUE", NULL, queuecmd, 0, scripting_command },
544
{ "QUIT", "QUIT", e_quit, 0, "- Quit BitchX" },
545
{ "QUOTE", "QUOTE", quotecmd, 0, "%Y<%ntext%Y>%n\n- Sends text directly to the server" },
546
{ "RANDOMNICK", NULL, randomnick, 0, "%Y<%Cnick%Y>%n\n- Changes your nick to a random nick. If nick is specified is is used as a prefix" },
547
{ "RBIND", NULL, rbindcmd, 0, "- Removes a key binding" },
548
{ "READLOG", "ReadLog", readlog, 0, "- Displays current away log" },
549
{ "RECONNECT", NULL, reconnect_cmd, 0, "- Reconnects you to current server" },
550
{ "REDIRECT", NULL, redirect, 0, "%Y<%Cnick%G|%Bchannel%Y> <command>\n- Redirects <command> to %Y<%Cnick%G|%Bchannel%Y>" },
551
{ "REHASH", "REHASH", send_comm, 0, "%Y*%n Requires irc operator status\n- Rehashs ircd.conf for new configuration" },
552
{ "REINIT", NULL, init_vars, 0, "- Reinitializes internal variables" },
553
{ "REINITSTAT", NULL, init_window_vars, 0, "- Reinitializes window variables" },
554
555
{ "REL", "Rel", do_dirlasttype, 0, relay_help },
556
557
{ "RELC", "RelC", do_dirlasttype, 0, relay_help },
558
{ "RELCR", "RelCR", do_dirlasttype, 0, relay_help },
559
{ "RELCRT", "RelCRT", do_dirlasttype, 0, relay_help },
560
{ "RELCT", "RelCT", do_dirlasttype, 0, relay_help },
561
{ "RELD", "RelD", do_dirlasttype, 0, relay_help },
562
{ "RELDT", "RelDT", do_dirlasttype, 0, relay_help },
563
564
{ "RELI", "RelI", do_dirlasttype, 0, relay_help },
565
{ "RELIT", "RelIT", do_dirlasttype, 0, relay_help },
566
{ "RELM", "RelM", do_dirlasttype, 0, relay_help },
567
{ "RELMT", "RelMT", do_dirlasttype, 0, relay_help },
568
{ "RELN", "RelN", do_dirlasttype, 0, relay_help },
569
{ "RELNT", "RelNT", do_dirlasttype, 0, relay_help },
570
571
{ "RELOAD", NULL, reload_save, 0, "- Reloads BitchX.sav" },
572
573
{ "RELS", "RelS", do_dirlasttype, 0, relay_help },
574
{ "RELSD", "RelSd", do_dirlasttype, 0, relay_help },
575
{ "RELSDT", "RelSdT", do_dirlasttype, 0, relay_help },
576
{ "RELSM", "RelSM", do_dirlasttype, 0, relay_help },
577
{ "RELSMT", "RelSMT", do_dirlasttype, 0, relay_help },
578
579
{ "RELSN", "RelSN", do_dirlasttype, 0, relay_help },
580
{ "RELSNT", "RelSNT", do_dirlasttype, 0, relay_help },
581
{ "RELST", "RelST", do_dirlasttype, 0, relay_help },
582
{ "RELSTT", "RelSTT", do_dirlasttype, 0, relay_help },
583
584
{ "RELSW", "RelSW", do_dirlasttype, 0, relay_help },
585
{ "RELSWT", "RelSWT", do_dirlasttype, 0, relay_help },
586
587
{ "RELT", "RelT", do_dirlasttype, 0, relay_help },
588
{ "RELTT", "RelTT", do_dirlasttype, 0, relay_help },
589
{ "RELW", "RelW", do_dirlasttype, 0, relay_help },
590
{ "RELWT", "RelWT", do_dirlasttype, 0, relay_help },
591
592
593
{ "REMLOG", "RemLog", remove_log, 0, "- Removes logfile" },
594
{ "REPEAT", NULL, repeatcmd, 0, "%Y<%ntimes%Y>%n %Y<%ncommand%Y>%n\n- Repeats %Y<%ntimes%Y>%n %Y<%ncommand%Y>%n" },
595
{ "REQUEST", NULL, ctcp, 0, "%Y<%Cnick%G|%Bchannel%Y>%n %Y<%nrequest%Y>%n\n- Sends CTCP %Y<%nrequest%Y>%n to %Y<%Cnick%G|%Bchannel%Y>%n" },
596
{ "RESET", NULL, reset, 0, "- Fixes flashed terminals" },
597
{ "RESTART", "RESTART", send_comm, 0, "%Y*%n Requires irc operator status\n- Restarts server" },
598
{ "RETURN", NULL, returncmd, 0, NULL },
599
{ "REVISIONS", NULL, show_revisions, 0, "- Shows CVS revisions of source files." },
600
/* nuxx requested this command */
601
{ "RMAP", "MAP", send_2comm, 0, "- Sends out a /map command to the server%n" },
602
{ "RPING", "RPING", send_comm, 0, NULL },
603
{ "SAVE", "SaveAll", savelists, 0, "- Saves ~/.BitchX/BitchX.sav" },
604
{ "SAVEIRC", NULL, save_settings, 0, "- Saves ~/.bitchxrc" },
605
{ "SAVELIST", NULL, savelists, 0, "- Saves ~/.BitchX/BitchX.sav" },
606
{ "SAY", empty_string, do_send_text, 0, "-%Y<%ntype%Y>%n Says whatever you write" },
607
{ "SC", "NAMES", do_mynames, 0, NULL },
608
{ "SCAN", "scan", do_scan, 0, "%R[%Bchannel%R]%n\n- Scans %R[%Bchannel%R]%n or current channel for all nicks" },
609
{ "SCANF", "ScanF", do_scan, 0, "%R[%Bchannel%R]%n\n- Scans %R[%Bchannel%R]%n or current channel for friends" },
610
{ "SCANI", "ScanI", do_scan, 0, "%R[%Bchannel%R]%n\n- Scans %R[%Bchannel%R]%n or current channel for ircops" },
611
{ "SCANN", "ScanN", do_scan, 0, "%R[%Bchannel%R]%n\n- Scans %R[%Bchannel%R]%n or current channel for non-ops" },
612
{ "SCANO", "ScanO", do_scan, 0, "%R[%Bchannel%R]%n\n- Scans %R[%Bchannel%R]%n or current channel for ops" },
613
{ "SCANS", "ScanS", do_scan, 0, "%R[%Bchannel%R]%n\n- Scans %R[%Bchannel%R]%n or current channel for shitlisted nicks" },
614
{ "SCANV", "ScanV", do_scan, 0, "%R[%Bchannel%R]%n\n- Scans %R[%Bchannel%R]%n or current channel for voice" },
615
{ "SEND", NULL, do_send_text, 0, NULL },
616
{ "SENDLINE", empty_string, sendlinecmd, 0, NULL },
617
{ "SERVER", NULL, servercmd, 0, "%Y<%nserver%Y>%n\n- Changes to %Y<%nserver%Y>%n" },
618
{ "SERVLIST", "SERVLIST", send_comm, 0, "- Displays available services" },
619
{ "SET", NULL, setcmd, 0, "- Set Variables" },
620
{ "SETAR", NULL, set_autoreply, 0, "%Y<%n-|d|pat1 pat2 ..%Y>%n\n- Adds or removes from your auto-response" },
621
{ "SETENV", NULL, setenvcmd, 0, NULL },
622
{ "SHIFT", NULL, shift_cmd, 0, scripting_command },
623
#ifdef WANT_USERLIST
624
{ "SHITLIST", NULL, showshitlist, 0, "- Displays internal shitlist" },
625
#endif
626
{ "SHOOK", NULL, shookcmd, 0, NULL },
627
{ "SHOWIDLE", "ShowIdle", showidle, 0, "%Y<-sort %R[none|time|host|nick%R]%Y> %R[%Bchannel%R]%n\n- Shows idle people on current channel or %R[%Bchannel%R]%n" },
628
{ "SHOWLOCK", "ShowLock", mode_lock, 0, "- Show the mode lock on the channel" },
629
{ "SHOWSPLIT", NULL, linklook, 0, "- Shows split servers" },
630
{ "SHOWWORDKICK",NULL, show_word_kick, 0, "- Shows the internal banned word list" },
631
632
#ifdef WANT_CHAN_NICK_SERV
633
{ "SILENCE", "SILENCE", send_comm, 0, NULL },
634
#endif
635
{ "SLEEP", NULL, sleepcmd, 0, scripting_command },
636
{ "SPAM", NULL, spam, 0, NULL },
637
{ "SPING", "Sping", sping, 0, "%Y<%nserver|.|-clear%Y>%n\n- Checks how lagged you are to %Y<%nserver%Y>%n" },
638
{ "SQUERY", "SQUERY", send_2comm, 0, "%Y<%nservice%Y> <%ntext%Y>%n\n - Sends %Y<%ntext%Y>%n to %Y<%nservice%Y>%n" },
639
{ "SQUIT", "SQUIT", send_2comm, 0, "%Y<%nserver1%Y>%n %R[%nserver2%R]%n\n%Y*%n Requires irc operator status\n- Disconnects %Y<%nserver1%Y>%n from current server or %R[%nserver2%R]%n" },
640
{ "STACK", NULL, stackcmd, 0, scripting_command },
641
{ "STATS", "STATS", do_stats, 0, NULL },
642
{ "STUB", "Stub", stubcmd, 0, "(alias|assign) <name> <file> [<file ...]" },
643
#ifdef GUI
644
{ "SUBMENU", NULL, os2submenu, 0, "GUI - Adds a submenu to a menu" },
645
#endif
646
{ "SUMMON", "SUMMON", send_comm, 0, "%Y<%nuser%Y> %R[%nserver%R [%nchannel%R]]%n\n- calls %Y<%nuser%Y>%n on %R[%nserver%R]%n to %R[%nchannel%R]%n" },
647
{ "SV", "Sv", show_version, 0, "%R[%nnick|#channel%R]%n\nShow Client Version information" },
648
{ "SWALLOP", "SWALLOPS", e_wall, 0, NULL },
649
#ifdef WANT_OPERVIEW
650
{ "SWATCH", NULL, s_watch, 0, "- Display or Modify what messages you want to see from the server"},
651
#endif
652
{ "SWITCH", "SWITCH", switchcmd, 0, scripting_command },
653
{ "T", "TOPIC", e_topic, 0, "%Y<%ntext%Y>%n\n- Sets %Y<%ntext%Y>%n as topic on current channel"},
654
{ "TBAN", NULL, tban, 0, "- Interactive channel ban delete" },
655
{ "TBK", "TBK", kickban, 0, "%Y<%Cnick%Y>%n %R[%ntime%R]%n\n- Deops, bans and kicks %Y<%Cnick%Y>%n for %R[%ntime%R]%n" },
656
{ "TCL", NULL, tcl_command, 0, "<-version> <command>" },
657
{ "TIGNORE", NULL, tignore, 0, NULL },
658
{ "TIME", "TIME", send_comm, 0, "- Shows time and date of current server" },
659
{ "TIMER", "TIMER", timercmd, 0, NULL },
660
{ "TKB", "TKB", kickban, 0, "%Y<%Cnick%Y>%n %R[%ntime%R]%n\n- Deops, kicks, and bans %Y<%Cnick%Y>%n for %R[%ntime%R]%n" },
661
{ "TKLINE", "TKLINE", send_kline, 0, "%Y<%nuser%y@%nhost%Y> <%nreason%Y>%n\n%Y*%n Requires irc operator status\n- Adds a temporary K-line" },
662
{ "TLOCK", "TLock", topic_lock, 0, "%Y<%Bchannel%Y>%n %R[%non%G|%noff%R]%n\n- [Un]Locks %Y<%Bchannel%Y>%n with the current topic" },
663
{ "TOGGLE", NULL, do_toggle, 0, "- Various Client toggles which can be change" },
664
{ "TOPIC", "TOPIC", e_topic, 0, "- Change or show the current or specified channel topic" },
665
{ "TRACE", "TRACE", do_trace, 0, "<argument> <server>\n- Without a specified server it shows the current connections on local server\n- Arguments: -s -u -o trace for servers, users, ircops" },
666
{ "TRACEKILL", "TraceKill", tracekill, 0, NULL },
667
{ "TRACESERV", "TraceServ", traceserv, 0, NULL },
668
{ "TYPE", NULL, type, 0, scripting_command },
669
{ "U", NULL, users, 0, "- Shows users on current channel" },
670
{ "UB", NULL, unban, 0, "%R[%Cnick%R]%n\n- Removes ban on %R[%Cnick%R]%n" },
671
{ "UMODE", "MODE", umodecmd, 0, "%Y<%nmode%Y>%n\n- Sets %Y<%nmode%Y>%n on yourself" },
672
{ "UNAJOIN", "UnAjoin", auto_join, 0, "%Y<%Bchannel%Y>%n\n- Removes autojoin %Y<%Bchannel%Y>%n from list" },
673
{ "UNBAN", NULL, unban, 0, NULL },
674
{ "UNBANWORD", "UnWordKick", add_ban_word, 0, "- Removes a banned word" },
675
{ "UNFORWARD", "NoForward", do_forward, 0, "%Y<%Cnick%G|%Bchannel%Y>\n- Remove %Y<%Cnick%G|%Bchannel%Y> from forward list" },
676
{ "UNIDLE", "UnIdle", addidle, 0, "%Y<%Bchannel%Y>%n\n- Removes %Y<%Bchannel%Y>%n from idle list" },
677
{ "UNIG", "UnIg", do_ig, 0, "%Y<%Cnick%Y>%n\n- UnIgnores %Y<%Cnick%Y>%n"},
678
{ "UNIGH", "UnIgH", do_ig, 0, "%Y<%Cnick%Y>%n\n- Removes %Y<%Cnick%Y>%n's host from the ignore list" },
679
{ "UNKEY", NULL, do_unkey, 0, "- Removes channel key from current channel" },
680
{ "UNKLINE", "UNKLINE", send_kline, 0, "<host|host,host2> remove klines for host(s)" },
681
{ "UNLAMENICK","UnLameNick", add_bad_nick, 0, "%Y<%nnick(s)%Y>%n\n- Remove nicks from you lame nick list"},
682
{ "UNLESS", "UNLESS", ifcmd, 0, scripting_command },
683
{ "UNLOAD", NULL, unload, 0, "- Unloads all loaded scripts" },
684
#ifdef WANT_DLL
685
{ "UNLOADDLL", NULL, unload_dll, 0, "- Unloads loaded a plugin" },
686
#endif
687
{ "UNSCREW", NULL, do_unscrew, 0, "%Y<%Cnick%Y>%n\n- Unscrew %Y<%Cnick%Y>%n" },
688
{ "UNSHIFT", NULL, unshift_cmd, 0, scripting_command },
689
#ifdef WANT_USERLIST
690
{ "UNSHIT", "UnShit", add_shit, 0, "%Y<%nnick%Y> <%nchannel%Y>%n" },
691
#endif
692
{ "UNTIL", "UNTIL", whilecmd, 0, scripting_command },
693
{ "UNTOPIC", "UNTOPIC", untopic, 0, "- Unsets a channel topic" },
694
#ifdef WANT_USERLIST
695
{ "UNUSER", "UnUser", add_user, 0, "%Y<%nnick%W|%nnick!user@hostname%Y> <%n#channel%W|%n*%Y>%n" },
696
#endif
697
{ "UNVOICE", "v", dodeop, 0, NULL },
698
{ "UNWORDKICK", "UnWordKick", add_ban_word, 0, "%Y<%n#channel%Y> <%nword%Y>%n" },
699
{ "UPING", "uPing", pingcmd, 0, NULL },
700
{ "UPTIME", NULL, do_uptime, 0, NULL },
701
{ "URL", NULL, url_grabber, 0, NULL },
702
{ "USER", NULL, users, 0, NULL },
703
{ "USERHOST", NULL, userhostcmd, 0, NULL },
704
#ifdef WANT_USERLIST
705
{ "USERINFO", NULL, set_user_info, 0, NULL },
706
#endif
707
{ "USERIP", "USERIP", useripcmd, 0, NULL },
708
#ifdef WANT_USERLIST
709
{ "USERLIST", NULL, showuserlist, 0, NULL },
710
#endif
711
{ "USERS", "USERS", send_comm, 0, "%R[%nserver%R]%n\n- Show users on %R[%nserver%R]%n (as finger @host)" },
712
#ifdef WANT_USERLIST
713
{ "USERSHOW", "UserShow", set_user_info, 0, NULL },
714
#endif
715
{ "USLEEP", NULL, usleepcmd, 0, NULL },
716
{ "USRIP", "USRIP", usripcmd, 0, NULL },
717
{ "VER", "Version", ctcp_version, 0, NULL },
718
{ "VERSION", "VERSION", version1, 0, NULL },
719
{ "VOICE", "v", doop, 0, NULL },
720
{ "W", "W", whocmd, 0, NULL },
721
{ "WAIT", NULL, waitcmd, 0, scripting_command },
722
{ "WALL", "WALL", ChanWallOp, 0, NULL },
723
{ "WALLCHOPS", "WALLCHOPS", send_2comm, 0, NULL },
724
{ "WALLMSG", NULL, ChanWallOp, 0, NULL },
725
{ "WALLOPS", "WALLOPS", e_wall, 0, NULL },
726
{ "WATCH", "WATCH", watchcmd, 0, NULL },
727
{ "WHICH", "WHICH", BX_load, 0, "- Shows which script would be loaded without loading it" },
728
{ "WHILE", "WHILE", whilecmd, 0, scripting_command },
729
{ "WHO", "Who", whocmd, SERVERREQ, NULL },
730
{ "WHOIS", "WHOIS", whois, SERVERREQ, NULL },
731
{ "WHOKILL", "WhoKill", whokill, SERVERREQ, "%Y<%Cnick%G!%nuser%Y@%nhostname%Y>%n %R[%nreason%R]%n\n%Y*%n Requires irc operator status\n- Kills multiple clients matching the filter %Y<%Cnick%G!%nuser%Y@%nhostname%Y>%n with %R[%n%W:%nreason%R]%n" },
732
{ "WHOLEFT", "WhoLeft", whowas, SERVERREQ, NULL },
733
{ "WHOWAS", "WhoWas", whois, SERVERREQ, NULL },
734
{ "WI", "Whois", whois, SERVERREQ, NULL },
735
{ "WII", NULL, my_whois, SERVERREQ, NULL },
736
{ "WILC", "WILC", my_whois, 0, NULL },
737
{ "WILCR", "WILCR", my_whois, 0, NULL },
738
{ "WILM", "WILM", my_whois, 0, NULL },
739
{ "WILN", "WILN", my_whois, 0, NULL },
740
{ "WINDOW", NULL, windowcmd, 0, "Various window commands. use /window help" },
741
{ "WORDLIST", NULL, show_word_kick, 0, NULL },
742
{ "WSET", NULL, wset_variable, 0, NULL },
743
{ "WW", "WhoWas", whois, 0, NULL },
744
{ "XDEBUG", NULL, xdebugcmd, 0, NULL },
745
{ "XECHO", "XECHO", echocmd, 0, NULL },
746
{ "XEVAL", "XEVAL", xevalcmd, 0, NULL },
747
{ "XQUOTE", "XQUOTE", quotecmd, 0, NULL },
748
{ "XTRA", "XTRA", e_privmsg, 0, NULL },
749
{ "XTYPE", NULL, xtypecmd, 0, NULL },
750
{ NULL, NULL, comment, 0, NULL }
751
};
752
753
/* number of entries in irc_command array */
754
#define NUMBER_OF_COMMANDS (sizeof(irc_command) / sizeof(IrcCommand)) - 2
755
756
BUILT_IN_COMMAND(about)
757
{
758
#ifdef GUI
759
static char *about_text =
760
"Grtz To: Trench, HappyCrappy, Yak, Zircon, Otiluke, Masonry,\n\
761
BuddahX, Hob, Lifendel, JondalaR, JVaughn, suicide, NovaLogic,\n\
762
Jordy, BigHead,Ananda, Hybrid, Reefa, BlackJac, GenX, MHacker,\n\
763
PSiLiCON, hop, Sheik, psykotyk, oweff, icetrey, Power, sideshow,\n\
764
Raistlin, Mustang, [Nuke], Rosmo, Sellfone, Drago and bark0de!\n\n\
765
Mailing list is at <[email protected]>\n";
766
gui_about_box(about_text);
767
return;
768
#else
769
int i = strip_ansi_in_echo;
770
strip_ansi_in_echo = 0;
771
772
#if defined(WINNT) || defined(__EMX__)
773
put_it(" ");
774
#else
775
charset_ibmpc();
776
put_it(" ");
777
#endif
778
#ifdef ASCII_LOGO
779
put_it(" ,");
780
put_it(" . ,$");
781
put_it(" . ,$'");
782
put_it(" . . ,$'");
783
put_it(" : ,g$p, . $, ,$'");
784
put_it(" y&$ `\"` .,. $&y `$, ,$'");
785
put_it(" $$$ o oooy$$$yoo o $$$ `$, ,$' -acidjazz");
786
put_it(" . $$$%%yyyp, gyp`$$$'gyyyyyyp, $$$yyyyp, `$, ,$' .");
787
put_it(" . yxxxx $$$\"`\"$$$ $$$ $$$ $y$\"`\"$$$ $$$\"`\"$$$ xxx`$,$'xxxxxxy .");
788
put_it(" $ $$7 l$$ $$$ $$$ $$7 \"\"\" $$7 ly$ .$' $");
789
put_it(" $ $$b dy$ $$$ $y$ $$b $$$ $$b d$$ ,$`$, $");
790
put_it(" . $xxxx $$$uuu$$$ $$$ $$$ $$$uuu$$$ $$$ $$$ x ,$'x`$, xxxx$ .");
791
put_it(" . \"\"\" \"\"\" \"\"\" \"\"\" \"\"\" ,$' `$, .");
792
put_it(" b i t c h - x ,$' `$,");
793
put_it(" $' `$,");
794
put_it(" ' `$,");
795
put_it(" `$,");
796
put_it(" `$");
797
put_it(" `");
798
put_it(empty_string);
799
put_it(" ");
800
put_it(" Grtz To: Trench, HappyCrappy, Yak, Zircon, Otiluke, Masonry, BuddahX, Hob, ");
801
put_it(" Lifendel, JondalaR, JVaughn, Suicide, NovaLogic, Jordy, BigHead, ");
802
put_it(" Ananda, Hybrid, Reefa, BlackJac, GenX, MHacker, PSiLiCON, ");
803
put_it(" hop, Sheik, psykotyk, oweff, icetrey, Power, sideshow, Raistlin, ");
804
put_it(" [Nuke], Rosmo and Bark0de! ");
805
put_it(" A special thanks to ccm.net for co-locating BitchX.com ");
806
put_it(" Mailing list is at <[email protected]> ");
807
put_it(empty_string);
808
#else
809
put_it(" �������������������������������������������������������������� ������� ��");
810
put_it(" �� ��������������� ��������������������� ������������������ ������� ��");
811
put_it("�� �� ���� ��� ��������� ��  ��� �� ������� ����� �������� ��");
812
put_it("�� ��  ������� ��� �� �� �� �� ������������������ �� ��");
813
put_it("�  �� �� �  �� �� �������  �� ������������ ���� �� ��");
814
put_it("�� �� �� �� �� �� �� �� �� ������������������ �� ��");
815
put_it("�� �� �� �� �� �� �� �� �� ��������������������� ��");
816
put_it("�� �� ��  ���� �� ���� �� ��� ��  �������� ���� �����������");
817
put_it("������������������������������������������������������������������  ����������");
818
put_it(" ����������������������������������������������������������� �����  ��� �� ��");
819
put_it(" ��������������������������������������������������������rE���� ���� �� ��");
820
put_it(empty_string);
821
put_it("���������������������������������������������������������������������������ܲ�");
822
put_it("� ");
823
put_it("� Grtz To: Trench, HappyCrappy, Yak, Zircon, Otiluke, Masonry, BuddahX, Hob, �");
824
put_it("� Lifendel, JondalaR, JVaughn, suicide, NovaLogic, Jordy, BigHead, �");
825
put_it("� Ananda, Hybrid, Reefa, BlackJac, GenX, MHacker, PSiLiCON, �");
826
put_it("� hop, Sheik, psykotyk, oweff, icetrey, Power, sideshow, Raistlin, �");
827
put_it("� Mustang, [Nuke], Rosmo, Sellfone, Drago and bark0de! �");
828
put_it("� Mailing list is at <[email protected]> �");
829
put_it("������������������������������������������������������������������������������");
830
put_it(empty_string);
831
#endif
832
#if !defined(WINNT) && !defined(__EMX__)
833
#if defined(LATIN1)
834
charset_lat1();
835
#elif defined(CHARSET_CUSTOM)
836
charset_cst();
837
#endif
838
#endif
839
strip_ansi_in_echo = i;
840
#endif
841
}
842
843
BUILT_IN_COMMAND(dcc_stat_comm)
844
{
845
dcc_stats(NULL, NULL);
846
}
847
848
void handle_dcc_chat(UserhostItem *stuff, char *nick, char *args)
849
{
850
if (!stuff || !stuff->nick || !nick || !strcmp(stuff->user, "<UNKNOWN>") || !strcmp(stuff->host, "<UNKNOWN>"))
851
{
852
bitchsay("No such nick %s", nick);
853
return;
854
}
855
dcc_chat(NULL, args);
856
}
857
858
BUILT_IN_COMMAND(init_dcc_chat)
859
{
860
char *nick = NULL;
861
if (args && *args)
862
{
863
char *n;
864
while ((nick = next_arg(args, &args)))
865
{
866
while ((n = next_in_comma_list(nick, &nick)))
867
{
868
if (!n || !*n) break;
869
if (!my_stricmp(n, get_server_nickname(from_server))) continue;
870
userhostbase(n, handle_dcc_chat, 1, n, NULL);
871
}
872
}
873
}
874
}
875
876
#ifdef WANT_FTP
877
BUILT_IN_COMMAND(init_ftp)
878
{
879
if (args && *args)
880
dcc_ftpopen(NULL, args);
881
}
882
#endif
883
884
char *glob_commands(char *name, int *cnt, int pmatch)
885
{
886
IrcCommand *var = NULL;
887
char *loc_match;
888
char *mylist = NULL;
889
*cnt = 0;
890
/* let's do a command completion here */
891
if (!(var = find_command(name, cnt)))
892
return m_strdup(empty_string);
893
loc_match = alloca(strlen(name)+2);
894
sprintf(loc_match, "%s*", (name && *name) ? name : empty_string);
895
while (wild_match(loc_match, var->name))
896
{
897
m_s3cat(&mylist, space, var->name);
898
var++;
899
}
900
return m_strdup(mylist ? mylist : empty_string);
901
}
902
903
/*
904
* find_command: looks for the given name in the command list, returning a
905
* pointer to the first match and the number of matches in cnt. If no
906
* matches are found, null is returned (as well as cnt being 0). The command
907
* list is sorted, so we do a binary search. The returned commands always
908
* points to the first match in the list. If the match is exact, it is
909
* returned and cnt is set to the number of matches * -1. Thus is 4 commands
910
* matched, but the first was as exact match, cnt is -4.
911
*/
912
IrcCommand *BX_find_command(char *com, int *cnt)
913
{
914
IrcCommand *retval;
915
int loc;
916
917
/*
918
* As a special case, the empty or NULL command is send_text.
919
*/
920
if (!com || !*com)
921
{
922
*cnt = -1;
923
return irc_command;
924
}
925
926
retval = (IrcCommand *)find_fixed_array_item ((void *)irc_command, sizeof(IrcCommand), NUMBER_OF_COMMANDS + 1, com, cnt, &loc);
927
return retval;
928
}
929
930
#ifdef WANT_DLL
931
IrcCommandDll * find_dll_command(char *com, int *cnt)
932
{
933
int len = 0;
934
935
if (com && (len = strlen(com)) && dll_commands)
936
{
937
int min,
938
max;
939
IrcCommandDll *old, *old_next = NULL;
940
941
*cnt = 0;
942
min = 1;
943
max = 0;
944
for (old = dll_commands; old; old = old->next)
945
max++;
946
947
old = dll_commands;
948
while (1)
949
{
950
if (!my_strnicmp(com, old->name, len))
951
{
952
if (!old_next)
953
old_next = old;
954
(*cnt)++;
955
}
956
if (old->next == NULL)
957
{
958
if (old_next && strlen(old_next->name) == len)
959
*cnt *= -1;
960
return (old_next);
961
}
962
else
963
old = old->next;
964
}
965
}
966
else
967
{
968
*cnt = -1;
969
return (NULL);
970
}
971
}
972
#endif
973
974
/* IRCUSER command. Changes your userhost on the fly. Takes effect
975
* the next time you connect to a server
976
*/
977
BUILT_IN_COMMAND(set_username)
978
{
979
char *blah;
980
981
if ((blah = next_arg(args, &args)))
982
{
983
if (!strcmp(blah, "-"))
984
strmcpy(username, empty_string, NAME_LEN);
985
else
986
strmcpy(username, blah, NAME_LEN);
987
say("Username has been changed to '%s'",username);
988
}
989
}
990
991
/* This code is courtesy of Richie B. ([email protected])
992
* Modified by Christian Deimel ([email protected]), now, if no argument is
993
* given, a random name is chosen
994
*/
995
/*
996
* REALNAME command. Changes the current realname. This will only be parsed
997
* to the server when the client is connected again.
998
*/
999
BUILT_IN_COMMAND(realname_cmd)
1000
{
1001
1002
if (*args)
1003
{
1004
strmcpy(realname, args, REALNAME_LEN);
1005
say("Realname at next server connnection: %s", realname);
1006
}
1007
else
1008
{
1009
char *s = NULL;
1010
s = get_realname(get_server_nickname(from_server));
1011
strmcpy(realname, s, REALNAME_LEN);
1012
say("Randomly chose a new ircname: %s", realname);
1013
}
1014
}
1015
1016
BUILT_IN_COMMAND(pop_cmd)
1017
{
1018
extern char *function_pop(char *, char *);
1019
char *blah = function_pop(NULL, args);
1020
new_free(&blah);
1021
}
1022
1023
BUILT_IN_COMMAND(push_cmd)
1024
{
1025
extern char *function_push(char *, char *);
1026
char *blah = function_push(NULL, args);
1027
new_free(&blah);
1028
}
1029
1030
BUILT_IN_COMMAND(shift_cmd)
1031
{
1032
extern char *function_shift(char *, char *);
1033
char *blah = function_shift(NULL, args);
1034
1035
new_free(&blah);
1036
}
1037
1038
BUILT_IN_COMMAND(unshift_cmd)
1039
{
1040
extern char *function_unshift(char *, char *);
1041
char *blah = function_unshift(NULL, args);
1042
1043
new_free(&blah);
1044
}
1045
1046
BUILT_IN_COMMAND(do_forward)
1047
{
1048
1049
if (command && (!my_stricmp(command, "NOFORWARD") || !my_stricmp(command, "UNFORWARD")))
1050
{
1051
if (forwardnick)
1052
{
1053
bitchsay("No longer forwarding messages to %s", forwardnick);
1054
send_to_server("NOTICE %s :%s is no longer forwarding to you",
1055
forwardnick, get_server_nickname(from_server));
1056
}
1057
new_free(&forwardnick);
1058
return;
1059
}
1060
if (args && *args)
1061
{
1062
char *q;
1063
malloc_strcpy(&forwardnick, args);
1064
if ((q = strchr(forwardnick, ' ')))
1065
*q = 0;
1066
send_to_server("NOTICE %s :%s is now forwarding messages to you",
1067
forwardnick, get_server_nickname(from_server));
1068
bitchsay("Now forwarding messages to %s", forwardnick);
1069
}
1070
return;
1071
}
1072
1073
BUILT_IN_COMMAND(blesscmd)
1074
{
1075
bless_local_stack();
1076
}
1077
1078
BUILT_IN_COMMAND(do_oops)
1079
{
1080
const char *to = next_arg(args, &args);
1081
const char *sent_nick = get_server_sent_nick(from_server);
1082
const char *sent_body = get_server_sent_body(from_server);
1083
1084
if (sent_nick && sent_body && to && *to)
1085
{
1086
send_to_server("PRIVMSG %s :Oops, that /msg wasn't for you", sent_nick);
1087
send_to_server("PRIVMSG %s :%s", to, sent_body);
1088
if (window_display && do_hook(SEND_MSG_LIST, "%s %s", to, sent_body))
1089
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_MSG_FSET), "%s %s %s %s", update_clock(GET_TIME),
1090
to, get_server_nickname(from_server), sent_body));
1091
}
1092
}
1093
1094
/*
1095
* RECONNECT command. Closes the server, and then reconnects again.
1096
* Works also while connected to multiple servers. It only reconnects to the
1097
* current server number (which is stored in from_server).
1098
* This command puts the REALNAME command in effect.
1099
*/
1100
BUILT_IN_COMMAND(reconnect_cmd)
1101
{
1102
char scommnd[6];
1103
1104
if (from_server == -1)
1105
{
1106
bitchsay("Try connecting to a server first.");
1107
return;
1108
}
1109
if (do_hook(DISCONNECT_LIST, "Reconnecting to server"))
1110
put_it("%s", convert_output_format("$G Reconnecting to server %K[%W$1%K]", "%s %d", update_clock(GET_TIME), from_server));
1111
1112
snprintf(scommnd, 5, "+%i", from_server);
1113
1114
/* close server will take care of the .reconnect variable */
1115
set_server_reconnecting(from_server, 1);
1116
close_server(from_server,(args && *args) ? args : "Reconnecting");
1117
clean_server_queues(from_server);
1118
window_check_servers(from_server);
1119
servercmd(NULL, scommnd, empty_string, NULL);
1120
1121
}
1122
1123
/* End of contributed code */
1124
1125
/* clear: the CLEAR command. Figure it oUt */
1126
BUILT_IN_COMMAND(my_clear)
1127
{
1128
char *arg;
1129
int all = 0,
1130
scrollback = 0,
1131
unhold = 0;
1132
1133
1134
while ((arg = next_arg(args, &args)) != NULL)
1135
{
1136
/* -ALL and ALL here becuase the help files used to be wrong */
1137
if (!my_strnicmp(arg, "A", 1) || !my_strnicmp(arg+1, "A", 1))
1138
all = 1;
1139
/* UNHOLD */
1140
else if (!my_strnicmp(arg+1, "U", 1))
1141
unhold = 1;
1142
else if (!my_strnicmp(arg+1, "S", 1))
1143
scrollback = 1;
1144
}
1145
if (all)
1146
clear_all_windows(unhold, scrollback);
1147
else
1148
{
1149
if (scrollback)
1150
clear_scrollback(get_window_by_refnum(0));
1151
if (unhold)
1152
set_hold_mode(NULL, OFF, 1);
1153
clear_window_by_refnum(0);
1154
}
1155
#if defined(WINNT) || defined(__EMX__)
1156
refresh_screen(0, NULL);
1157
#endif
1158
update_input(UPDATE_JUST_CURSOR);
1159
}
1160
1161
1162
BUILT_IN_COMMAND(do_invite)
1163
{
1164
char *inick;
1165
ChannelList *chan = NULL;
1166
int server = from_server;
1167
1168
1169
if (args && *args)
1170
{
1171
while(1)
1172
{
1173
inick = next_arg(args, &args);
1174
if (!inick)
1175
return;
1176
if (args && *args)
1177
{
1178
if (!is_channel(args) || !(chan = prepare_command(&server, args, NO_OP)))
1179
return;
1180
}
1181
else
1182
if (!(chan = prepare_command(&server, NULL, NO_OP)))
1183
return;
1184
1185
if (!chan)
1186
return;
1187
my_send_to_server(server, "INVITE %s %s%s%s", inick, chan->channel, chan->key?space:empty_string, chan->key?chan->key:empty_string);
1188
}
1189
}
1190
return;
1191
}
1192
1193
1194
BUILT_IN_COMMAND(umodecmd)
1195
{
1196
1197
send_to_server("%s %s %s", command, get_server_nickname(from_server),
1198
(args && *args) ? args : empty_string);
1199
}
1200
1201
1202
BUILT_IN_COMMAND(do_getout)
1203
{
1204
char *channel = NULL;
1205
ChannelList *chan = NULL;
1206
AJoinList *tmp = NULL;
1207
int server = from_server;
1208
int all = 0;
1209
1210
1211
if (command && !my_stricmp(command, "PARTALL"))
1212
all = 1;
1213
if (!all)
1214
{
1215
if (args)
1216
channel = next_arg(args, &args);
1217
if (!(chan = prepare_command(&server, channel?make_channel(channel):channel, NO_OP)))
1218
return;
1219
my_send_to_server(server, "PART %s", chan->channel);
1220
if ((tmp = (AJoinList *)remove_from_list((List **)&ajoin_list, chan->channel)))
1221
{
1222
if (!tmp->ajoin_list)
1223
{
1224
new_free(&tmp->name);
1225
new_free(&tmp->key);
1226
new_free(&tmp);
1227
}
1228
else
1229
add_to_list((List **)&ajoin_list, (List *)tmp);
1230
}
1231
}
1232
else
1233
{
1234
for (chan = get_server_channels(server); chan; chan = chan->next)
1235
{
1236
my_send_to_server(server, "PART %s", chan->channel);
1237
if ((tmp = (AJoinList *)remove_from_list((List **)&ajoin_list, chan->channel)))
1238
{
1239
if (!tmp->ajoin_list)
1240
{
1241
new_free(&tmp->name);
1242
new_free(&tmp->key);
1243
new_free(&tmp);
1244
}
1245
else
1246
add_to_list((List **)&ajoin_list, (List *)tmp);
1247
}
1248
}
1249
}
1250
}
1251
1252
/* 12-19-02 Logan, Tilt and Digital got totally drunk */
1253
BUILT_IN_COMMAND(do_unscrew)
1254
{
1255
char *channel = NULL;
1256
int server = from_server;
1257
ChannelList *chan;
1258
1259
1260
if (args && *args)
1261
channel = next_arg(args, &args);
1262
1263
if (!(chan = prepare_command(&server, channel, NEED_OP)))
1264
return;
1265
1266
my_send_to_server(server, "MODE %s -k %s", chan->channel, chan->key);
1267
my_send_to_server(server, "MODE %s +k \033(B\033[2J", chan->channel);
1268
my_send_to_server(server, "MODE %s -k \033(B\033[2J", chan->channel);
1269
}
1270
1271
BUILT_IN_COMMAND(do_4op)
1272
{
1273
char *channel = NULL;
1274
char *nick = NULL;
1275
ChannelList *chan;
1276
int server = from_server;
1277
1278
1279
1280
if (args && *args)
1281
channel = next_arg(args, &args);
1282
1283
if (channel)
1284
{
1285
if (is_channel(channel))
1286
nick = args;
1287
else
1288
{
1289
nick = channel;
1290
channel = NULL;
1291
}
1292
}
1293
if (!(chan = prepare_command(&server, channel, NEED_OP)))
1294
return;
1295
1296
if (!nick)
1297
return;
1298
my_send_to_server(server, "MODE %s +oooo %s %s %s %s", chan->channel, nick, nick, nick, nick);
1299
}
1300
1301
enum SCAN_TYPE {
1302
SCAN_ALL, SCAN_VOICES, SCAN_CHANOPS, SCAN_NONOPS, SCAN_IRCOPS,
1303
SCAN_FRIENDS, SCAN_SHITLISTED
1304
};
1305
1306
/* nick_in_scan
1307
*
1308
* Test if a nick should be shown in a /SCAN, according to the
1309
* scan type and nick!user@host mask. A NULL mask matches all nicks.
1310
*/
1311
int nick_in_scan(NickList *nick, enum SCAN_TYPE scan_type, char *mask)
1312
{
1313
switch(scan_type)
1314
{
1315
case SCAN_VOICES:
1316
if (!nick_isvoice(nick)) return 0;
1317
break;
1318
1319
case SCAN_CHANOPS:
1320
if (!nick_isop(nick) && !nick_ishalfop(nick)) return 0;
1321
break;
1322
1323
case SCAN_NONOPS:
1324
if (nick_isop(nick) || nick_ishalfop(nick)) return 0;
1325
break;
1326
1327
case SCAN_IRCOPS:
1328
if (!nick_isircop(nick)) return 0;
1329
break;
1330
1331
case SCAN_FRIENDS:
1332
if (!nick->userlist) return 0;
1333
break;
1334
1335
case SCAN_SHITLISTED:
1336
if (!nick->shitlist) return 0;
1337
break;
1338
1339
case SCAN_ALL:
1340
default:
1341
break;
1342
}
1343
1344
/* mask == NULL matches all nicks */
1345
if (!mask)
1346
return 1;
1347
1348
return nick_match(nick, mask);
1349
}
1350
1351
BUILT_IN_COMMAND(do_scan)
1352
{
1353
enum SCAN_TYPE scan_type = SCAN_ALL;
1354
char *channel = NULL;
1355
ChannelList *chan;
1356
NickList *nick, *snick = NULL;
1357
char *s;
1358
char *buffer = NULL;
1359
int n_inscan = 0, n_total = 0;
1360
int count = 0;
1361
int server;
1362
int sorted = NICKSORT_NORMAL;
1363
char *match_host = NULL;
1364
int cols = get_int_var(NAMES_COLUMNS_VAR);
1365
1366
if (!cols)
1367
cols = 1;
1368
1369
if (command)
1370
{
1371
if (!my_stricmp(command, "scanv"))
1372
scan_type = SCAN_VOICES;
1373
else if (!my_stricmp(command, "scano"))
1374
scan_type = SCAN_CHANOPS;
1375
else if (!my_stricmp(command, "scann"))
1376
scan_type = SCAN_NONOPS;
1377
else if (!my_stricmp(command, "scanf"))
1378
scan_type = SCAN_FRIENDS;
1379
else if (!my_stricmp(command, "scans"))
1380
scan_type = SCAN_SHITLISTED;
1381
else if (!my_stricmp(command, "scani"))
1382
scan_type = SCAN_IRCOPS;
1383
}
1384
1385
while ((s = next_arg(args, &args)))
1386
{
1387
if (is_channel(s)) {
1388
if (!channel)
1389
{
1390
channel = s;
1391
}
1392
1393
continue;
1394
}
1395
1396
if (*s == '-')
1397
{
1398
if (!my_strnicmp(s, "-sort", 3))
1399
sorted = NICKSORT_NONE;
1400
else if (!my_strnicmp(s, "-nick", 3))
1401
sorted = NICKSORT_NICK;
1402
else if (!my_strnicmp(s, "-host", 3))
1403
sorted = NICKSORT_HOST;
1404
else if (!my_strnicmp(s, "-stat", 3))
1405
sorted = NICKSORT_STAT;
1406
1407
continue;
1408
}
1409
1410
if ((strlen(s) == 1) && (scan_type == SCAN_ALL))
1411
{
1412
switch(*s)
1413
{
1414
case 'v':
1415
case 'V':
1416
scan_type = SCAN_VOICES;
1417
break;
1418
1419
case 'o':
1420
case 'O':
1421
scan_type = SCAN_CHANOPS;
1422
break;
1423
1424
case 'n':
1425
case 'N':
1426
scan_type = SCAN_NONOPS;
1427
break;
1428
1429
case 'f':
1430
case 'F':
1431
scan_type = SCAN_FRIENDS;
1432
break;
1433
1434
case 's':
1435
case 'S':
1436
scan_type = SCAN_SHITLISTED;
1437
break;
1438
1439
case 'i':
1440
case 'I':
1441
scan_type = SCAN_IRCOPS;
1442
break;
1443
}
1444
1445
continue;
1446
}
1447
1448
if (!match_host)
1449
{
1450
match_host = s;
1451
}
1452
}
1453
1454
if (!(chan = prepare_command(&server, channel, NO_OP)))
1455
return;
1456
1457
reset_display_target();
1458
1459
snick = sorted_nicklist(chan, sorted);
1460
1461
/* Count nicks - total and shown */
1462
for (nick = snick; nick; nick = nick->next)
1463
{
1464
n_total++;
1465
1466
if (nick_in_scan(nick, scan_type, match_host))
1467
n_inscan++;
1468
}
1469
1470
/* Output the header line */
1471
switch(scan_type)
1472
{
1473
case SCAN_VOICES:
1474
s = fget_string_var(FORMAT_NAMES_VOICE_FSET);
1475
break;
1476
1477
case SCAN_CHANOPS:
1478
s = fget_string_var(FORMAT_NAMES_OP_FSET);
1479
break;
1480
1481
case SCAN_IRCOPS:
1482
s = fget_string_var(FORMAT_NAMES_IRCOP_FSET);
1483
break;
1484
1485
case SCAN_FRIENDS:
1486
s = fget_string_var(FORMAT_NAMES_FRIEND_FSET);
1487
break;
1488
1489
case SCAN_NONOPS:
1490
s = fget_string_var(FORMAT_NAMES_NONOP_FSET);
1491
break;
1492
1493
case SCAN_SHITLISTED:
1494
s = fget_string_var(FORMAT_NAMES_SHIT_FSET);
1495
break;
1496
1497
case SCAN_ALL:
1498
default:
1499
s = fget_string_var(FORMAT_NAMES_FSET);
1500
}
1501
1502
put_it("%s",
1503
convert_output_format(s, "%s %s %d %d %s",
1504
update_clock(GET_TIME), chan->channel, n_inscan, n_total,
1505
match_host ? match_host : empty_string));
1506
1507
for (nick = snick; nick; nick = nick->next)
1508
{
1509
char *nick_format;
1510
char *user_format;
1511
char *nick_buffer = NULL;
1512
char nick_sym;
1513
1514
if (!nick_in_scan(nick, scan_type, match_host))
1515
continue;
1516
1517
/* Determine the nick format string to use */
1518
if (!my_stricmp(nick->nick, get_server_nickname(server)))
1519
nick_format = fget_string_var(FORMAT_NAMES_NICK_ME_FSET);
1520
else if (nick->userlist && (nick->userlist->flags & ADD_BOT))
1521
nick_format = fget_string_var(FORMAT_NAMES_NICK_BOT_FSET);
1522
else if (nick->userlist)
1523
nick_format = fget_string_var(FORMAT_NAMES_NICK_FRIEND_FSET);
1524
else if (nick->shitlist)
1525
nick_format = fget_string_var(FORMAT_NAMES_NICK_SHIT_FSET);
1526
else
1527
nick_format = fget_string_var(FORMAT_NAMES_NICK_FSET);
1528
1529
/* Determine the user format and indicator symbol to use. */
1530
if (nick_isop(nick))
1531
{
1532
user_format = fget_string_var(FORMAT_NAMES_USER_CHANOP_FSET);
1533
nick_sym = '@';
1534
}
1535
else if (nick_ishalfop(nick))
1536
{
1537
user_format = fget_string_var(FORMAT_NAMES_USER_CHANOP_FSET);
1538
nick_sym = '%';
1539
}
1540
else if (nick_isvoice(nick))
1541
{
1542
user_format = fget_string_var(FORMAT_NAMES_USER_VOICE_FSET);
1543
nick_sym = '+';
1544
}
1545
else if (nick_isircop(nick))
1546
{
1547
user_format = fget_string_var(FORMAT_NAMES_USER_IRCOP_FSET);
1548
nick_sym = '*';
1549
}
1550
else
1551
{
1552
user_format = fget_string_var(FORMAT_NAMES_USER_FSET);
1553
nick_sym = '.';
1554
}
1555
1556
/* Construct the string */
1557
malloc_strcpy(&nick_buffer, convert_output_format(nick_format,
1558
"%s", nick->nick));
1559
malloc_strcat(&buffer,
1560
convert_output_format(user_format, "%c %s", nick_sym,
1561
nick_buffer));
1562
malloc_strcat(&buffer, space);
1563
new_free(&nick_buffer);
1564
1565
/* If this completes a line, output it */
1566
if (count++ >= (cols - 1))
1567
{
1568
if (fget_string_var(FORMAT_NAMES_BANNER_FSET))
1569
put_it("%s%s", convert_output_format(fget_string_var(FORMAT_NAMES_BANNER_FSET), NULL, NULL), buffer);
1570
else
1571
put_it("%s", buffer);
1572
new_free(&buffer);
1573
count = 0;
1574
}
1575
}
1576
1577
/* If a partial line is left, output it */
1578
if (count)
1579
{
1580
if (fget_string_var(FORMAT_NAMES_BANNER_FSET))
1581
put_it("%s%s", convert_output_format(fget_string_var(FORMAT_NAMES_BANNER_FSET), NULL, NULL), buffer);
1582
else
1583
put_it("%s", buffer);
1584
new_free(&buffer);
1585
}
1586
1587
/* Write the footer */
1588
if (fget_string_var(FORMAT_NAMES_FOOTER_FSET))
1589
put_it("%s",
1590
convert_output_format(fget_string_var(FORMAT_NAMES_FOOTER_FSET),
1591
"%s %s %d %d %s", update_clock(GET_TIME), chan->channel,
1592
n_inscan, n_total, match_host ? match_host : empty_string));
1593
1594
clear_sorted_nicklist(&snick);
1595
}
1596
1597
BUILT_IN_COMMAND(do_mynames)
1598
{
1599
char *channel = NULL;
1600
int server = from_server;
1601
int all = 0;
1602
ChannelList *chan;
1603
1604
1605
if (args)
1606
{
1607
if (*args == '-' && tolower(*(args+1)) == 'a')
1608
all = 1;
1609
else
1610
channel = next_arg(args, &args);
1611
}
1612
if (all)
1613
{
1614
for (chan = get_server_channels(from_server); chan; chan = chan->next)
1615
my_send_to_server(server, "NAMES %s", chan->channel);
1616
1617
}
1618
else
1619
{
1620
if (!(chan = prepare_command(&server, channel, NO_OP)))
1621
return;
1622
1623
my_send_to_server(server, "NAMES %s", chan->channel);
1624
}
1625
}
1626
1627
BUILT_IN_COMMAND(my_whois)
1628
{
1629
char *nick = NULL;
1630
1631
if (command)
1632
{
1633
if (!strcmp(command, "WILM"))
1634
nick = get_server_recv_nick(from_server);
1635
else if (!strcmp(command, "WILN"))
1636
nick = last_notice[0].from;
1637
else if (!strcmp(command, "WILC"))
1638
nick = last_sent_ctcp[0].to;
1639
else if (!strcmp(command, "WILCR"))
1640
nick = last_ctcp[0].from;
1641
1642
if (!nick)
1643
{
1644
bitchsay("You have no friends");
1645
return;
1646
}
1647
}
1648
else if (args && *args)
1649
{
1650
while ((nick = next_arg(args, &args)))
1651
send_to_server("WHOIS %s %s", nick, nick);
1652
return;
1653
}
1654
else
1655
{
1656
nick = get_target_by_refnum(0);
1657
1658
if (!nick || is_channel(nick))
1659
nick = get_server_nickname(from_server);
1660
}
1661
1662
send_to_server("WHOIS %s %s", nick, nick);
1663
}
1664
1665
BUILT_IN_COMMAND(do_unkey)
1666
{
1667
char *channel = NULL;
1668
int server = from_server;
1669
ChannelList *chan;
1670
1671
1672
if (args)
1673
channel = next_arg(args, &args);
1674
if (!(chan = prepare_command(&server, channel, NEED_OP)))
1675
return;
1676
if (chan->key)
1677
my_send_to_server(server, "MODE %s -k %s", chan->channel, chan->key);
1678
}
1679
1680
BUILT_IN_COMMAND(pingcmd)
1681
{
1682
struct timeval tp;
1683
char *to;
1684
char buffer[101];
1685
int ping_type = get_int_var(PING_TYPE_VAR);
1686
1687
1688
if (command && !my_stricmp(command, "uPING"))
1689
ping_type = 1;
1690
get_time(&tp);
1691
1692
if ((to = next_arg(args, &args)) == NULL || !strcmp(to, "*"))
1693
{
1694
if ((to = get_current_channel_by_refnum(0)) == NULL)
1695
if (!(to = get_target_by_refnum(0)))
1696
to = zero;
1697
}
1698
1699
switch(ping_type)
1700
{
1701
case 1:
1702
snprintf(buffer, 100, "%s PING %lu %lu", to, (unsigned long)tp.tv_sec,(unsigned long)tp.tv_usec);
1703
break;
1704
case 2:
1705
snprintf(buffer, 100, "%s ECHO %lu %lu", to, (unsigned long)tp.tv_sec,(unsigned long)tp.tv_usec);
1706
break;
1707
default:
1708
snprintf(buffer, 100, "%s PING %lu", to, (unsigned long)now);
1709
}
1710
ctcp(command, buffer, empty_string, NULL);
1711
}
1712
1713
BUILT_IN_COMMAND(ctcp_version)
1714
{
1715
char *person;
1716
int type = 0;
1717
1718
1719
if ((person = next_arg(args, &args)) == NULL || !strcmp(person, "*"))
1720
{
1721
if ((person = get_current_channel_by_refnum(0)) == NULL)
1722
if (!(person = get_target_by_refnum(0)))
1723
person = zero;
1724
}
1725
if ((type = in_ctcp()) == -1)
1726
echocmd(NULL, "*** You may not use the CTCP command in an ON CTCP_REPLY!", empty_string, NULL);
1727
else
1728
{
1729
send_ctcp(type, person, CTCP_VERSION, NULL);
1730
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_CTCP_FSET),
1731
"%s %s %s",update_clock(GET_TIME), person, "VERSION"));
1732
add_last_type(&last_sent_ctcp[0], 1, NULL, NULL, person, "VERSION");
1733
}
1734
}
1735
1736
BUILT_IN_COMMAND(do_offers)
1737
{
1738
char *person;
1739
int type = 0;
1740
1741
1742
if ((person = next_arg(args, &args)) == NULL || !strcmp(person, "*"))
1743
{
1744
if ((person = get_current_channel_by_refnum(0)) == NULL)
1745
person = zero;
1746
}
1747
if ((type = in_ctcp()) == -1)
1748
echocmd(NULL, "*** You may noT use the CTCP command in an ON CTCP_REPLY!", empty_string, NULL);
1749
else
1750
{
1751
send_ctcp(type, person, CTCP_CDCC2, "%s", "LIST");
1752
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_CTCP_FSET),
1753
"%s %s %s",update_clock(GET_TIME), person, "XDCC LIST"));
1754
add_last_type(&last_sent_ctcp[0], 1, NULL, NULL, person, "CDCC LIST");
1755
}
1756
}
1757
1758
/*ARGSUSED*/
1759
BUILT_IN_COMMAND(ctcp)
1760
{
1761
char *to;
1762
char *stag = NULL;
1763
int tag;
1764
int type;
1765
1766
1767
if ((to = next_arg(args, &args)) != NULL)
1768
{
1769
if (!strcmp(to, "*"))
1770
if ((to = get_current_channel_by_refnum(0)) == NULL)
1771
to = zero;
1772
1773
if ((stag = next_arg(args, &args)) != NULL)
1774
tag = get_ctcp_val(upper(stag));
1775
else
1776
tag = CTCP_VERSION;
1777
1778
if ((type = in_ctcp()) == -1)
1779
say("You may not use the CTCP command from an ON CTCP_REPLY!");
1780
else
1781
{
1782
if (args && *args)
1783
send_ctcp(type, to, tag, "%s", args);
1784
else
1785
send_ctcp(type, to, tag, NULL);
1786
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_CTCP_FSET),
1787
"%s %s %s %s",update_clock(GET_TIME), to, stag ? stag : "VERSION", args ? args: empty_string));
1788
add_last_type(&last_sent_ctcp[0], 1, NULL, NULL, to, stag? stag : "VERSION");
1789
}
1790
}
1791
}
1792
1793
/*ARGSUSED*/
1794
BUILT_IN_COMMAND(hookcmd)
1795
{
1796
1797
if (*args)
1798
do_hook(HOOK_LIST, "%s", args);
1799
}
1800
1801
BUILT_IN_COMMAND(dcc)
1802
{
1803
1804
if (*args)
1805
process_dcc(args);
1806
else
1807
dcc_glist(NULL, NULL);
1808
}
1809
1810
BUILT_IN_COMMAND(deop)
1811
{
1812
send_to_server("MODE %s -o", get_server_nickname(from_server));
1813
}
1814
1815
BUILT_IN_COMMAND(funny_stuff)
1816
{
1817
char *arg,
1818
*stuff;
1819
int min = 0,
1820
max = 0,
1821
flags = 0,
1822
ircu = 0;
1823
1824
1825
stuff = empty_string;
1826
if (!args || !*args)
1827
{
1828
bitchsay("Doing this is not a good idea. Add -YES if you really mean it");
1829
return;
1830
}
1831
while ((arg = next_arg(args, &args)) != NULL)
1832
{
1833
if (*arg == '/' || *arg == '-')
1834
{
1835
if (my_strnicmp(arg+1, "I", 1) == 0) /* MAX */
1836
ircu = 1;
1837
else if (my_strnicmp(arg+1, "MA", 2) == 0) /* MAX */
1838
{
1839
if ((arg = next_arg(args, &args)) != NULL)
1840
max = atoi(arg);
1841
}
1842
else if (my_strnicmp(arg+1, "MI", 2) == 0) /* MIN */
1843
{
1844
if ((arg = next_arg(args, &args)) != NULL)
1845
min = atoi(arg);
1846
}
1847
else if (my_strnicmp(arg+1, "A", 1) == 0) /* ALL */
1848
flags &= ~(FUNNY_PUBLIC | FUNNY_PRIVATE);
1849
else if (my_strnicmp(arg+1, "PU", 2) == 0) /* PUBLIC */
1850
{
1851
flags |= FUNNY_PUBLIC;
1852
flags &= ~FUNNY_PRIVATE;
1853
}
1854
else if (my_strnicmp(arg+1, "PR", 2) == 0) /* PRIVATE */
1855
{
1856
flags |= FUNNY_PRIVATE;
1857
flags &= ~FUNNY_PUBLIC;
1858
}
1859
else if (my_strnicmp(arg+1, "T", 1) == 0) /* TOPIC */
1860
flags |= FUNNY_TOPIC;
1861
else if (my_strnicmp(arg+1, "W", 1) == 0) /* WIDE */
1862
flags |= FUNNY_WIDE;
1863
else if (my_strnicmp(arg+1, "U", 1) == 0) /* USERS */
1864
flags |= FUNNY_USERS;
1865
else if (my_strnicmp(arg+1, "N", 1) == 0) /* NAME */
1866
flags |= FUNNY_NAME;
1867
else if (!my_strnicmp(arg+1, "Y", 1))
1868
;
1869
else
1870
stuff = arg;
1871
}
1872
else stuff = arg;
1873
}
1874
set_funny_flags(min, max, flags);
1875
if (!strcmp(stuff, "*"))
1876
if (!(stuff = get_current_channel_by_refnum(0)))
1877
stuff = empty_string;
1878
if (strchr(stuff, '*'))
1879
{
1880
funny_match(stuff);
1881
if (min && ircu)
1882
{
1883
if (max)
1884
send_to_server("%s >%d,<%d", command, min - 1, max + 1);
1885
else
1886
send_to_server("%s >%d", command, min - 1);
1887
}
1888
else if (max && ircu)
1889
send_to_server("%s <%d", command, max + 1);
1890
else
1891
send_to_server("%s %s", command, empty_string);
1892
}
1893
else
1894
{
1895
funny_match(NULL);
1896
if (min && ircu)
1897
{
1898
if (max)
1899
send_to_server("%s >%d,<%d", command, min - 1, max + 1);
1900
else
1901
send_to_server("%s >%d", command, min - 1);
1902
}
1903
else if (max && ircu)
1904
send_to_server("%s <%d", command, max + 1);
1905
else
1906
send_to_server("%s %s", command, stuff);
1907
}
1908
}
1909
1910
/*
1911
This isnt a command, its used by the wait command. Since its extern,
1912
and it doesnt use anything static in this file, im sure it doesnt
1913
belong here.
1914
*/
1915
void oh_my_wait (int servnum)
1916
{
1917
int w_server;
1918
1919
if ((w_server = servnum) == -1)
1920
w_server = primary_server;
1921
1922
if (is_server_connected(w_server))
1923
{
1924
int old_doing_privmsg = doing_privmsg;
1925
int old_doing_notice = doing_notice;
1926
int old_in_ctcp_flag = in_ctcp_flag;
1927
int old_from_server = from_server;
1928
1929
waiting_out++;
1930
lock_stack_frame();
1931
my_send_to_server(w_server, "%s", lame_wait_nick);
1932
while (waiting_in < waiting_out)
1933
io("oh_my_wait");
1934
1935
doing_privmsg = old_doing_privmsg;
1936
doing_notice = old_doing_notice;
1937
in_ctcp_flag = old_in_ctcp_flag;
1938
from_server = old_from_server;
1939
}
1940
}
1941
1942
BUILT_IN_COMMAND(waitcmd)
1943
{
1944
char *ctl_arg = next_arg(args, &args);
1945
1946
if (from_server == -1)
1947
return;
1948
if (ctl_arg && !my_strnicmp(ctl_arg, "-c", 2))
1949
{
1950
WaitCmd *new_wait;
1951
1952
new_wait = (WaitCmd *) new_malloc(sizeof(WaitCmd));
1953
new_wait->stuff = m_strdup(args);
1954
new_wait->next = NULL;
1955
1956
if (end_wait_list)
1957
end_wait_list->next = new_wait;
1958
end_wait_list = new_wait;
1959
if (!start_wait_list)
1960
start_wait_list = new_wait;
1961
send_to_server("%s", wait_nick);
1962
}
1963
1964
else if (ctl_arg && !my_strnicmp(ctl_arg, "for", 3))
1965
{
1966
clear_sent_to_server(from_server);
1967
parse_line(NULL, args, subargs, 0, 0, 1);
1968
if (sent_to_server(from_server))
1969
oh_my_wait(from_server);
1970
clear_sent_to_server(from_server);
1971
}
1972
1973
else if (ctl_arg && *ctl_arg == '%')
1974
{
1975
int w_index = is_valid_process(ctl_arg);
1976
1977
if (w_index != -1)
1978
{
1979
if (args && *args)
1980
{
1981
if (!my_strnicmp(args, "-cmd", 4))
1982
next_arg(args, &args);
1983
add_process_wait(w_index, args?args:empty_string);
1984
}
1985
else
1986
{
1987
set_input(empty_string);
1988
lock_stack_frame();
1989
while (process_is_running(ctl_arg))
1990
io("wait %proc");
1991
unlock_stack_frame();
1992
}
1993
}
1994
}
1995
else if (ctl_arg)
1996
debugyell("Unknown argument to /WAIT");
1997
else
1998
{
1999
oh_my_wait(from_server);
2000
clear_sent_to_server(from_server);
2001
}
2002
}
2003
2004
int check_wait_command(char *nick)
2005
{
2006
if ((waiting_out > waiting_in) && !strcmp(nick, lame_wait_nick))
2007
{
2008
waiting_in++;
2009
unlock_stack_frame();
2010
return 1;
2011
}
2012
if (start_wait_list && !strcmp(nick, wait_nick))
2013
{
2014
WaitCmd *old = start_wait_list;
2015
2016
start_wait_list = old->next;
2017
if (old->stuff)
2018
{
2019
parse_line("WAIT", old->stuff, empty_string, 0, 0, 1);
2020
new_free(&old->stuff);
2021
}
2022
if (end_wait_list == old)
2023
end_wait_list = NULL;
2024
new_free((char **)&old);
2025
return 1;
2026
}
2027
return 0;
2028
}
2029
2030
BUILT_IN_COMMAND(redirect)
2031
{
2032
char *who;
2033
2034
2035
if (!(who = next_arg(args, &args)))
2036
return;
2037
if (!strcmp(who, "*") && !(who = get_current_channel_by_refnum(0)))
2038
{
2039
bitchsay("Must be on a channel to redirect to '*'");
2040
return;
2041
}
2042
2043
if (!my_stricmp(who, get_server_nickname(from_server)))
2044
{
2045
bitchsay("You may not redirect output to yourself");
2046
return;
2047
}
2048
2049
2050
if ((*who == '=') && !dcc_activechat(who + 1))
2051
{
2052
bitchsay("No active DCC CHAT:chat connection for %s", who+1);
2053
return;
2054
}
2055
2056
set_server_redirect(from_server, who);
2057
clear_sent_to_server(from_server);
2058
parse_line(NULL, args, NULL, 0, 0, 1);
2059
2060
if (sent_to_server(from_server))
2061
send_to_server("***%s", who);
2062
else
2063
set_server_redirect(from_server, NULL);
2064
}
2065
2066
BUILT_IN_COMMAND(sleepcmd)
2067
{
2068
char *arg;
2069
2070
2071
if ((arg = next_arg(args, &args)) != NULL)
2072
sleep(atoi(arg));
2073
}
2074
2075
/*
2076
* echocmd: simply displays the args to the screen, or, if it's XECHO,
2077
* processes the flags first, then displays the text on
2078
* the screen
2079
* XECHO
2080
*/
2081
BUILT_IN_COMMAND(echocmd)
2082
{
2083
unsigned display;
2084
char *flag_arg;
2085
int temp;
2086
int all_windows = 0;
2087
int x = -1, y = -1, raw = 0, more = 1;
2088
int banner = 0;
2089
int no_log = 0;
2090
unsigned long from_level = 0;
2091
unsigned long lastlog_level = 0;
2092
2093
char *stuff = NULL;
2094
Window *old_target_window = target_window;
2095
2096
int old_und = 0, old_rev = 0, old_bold = 0,
2097
old_color = 0, old_blink = 0, old_ansi = 0;
2098
int xtended = 0;
2099
const char *saved_from = NULL;
2100
unsigned long saved_level = 0;
2101
2102
save_display_target(&saved_from, &saved_level);
2103
if (command && *command == 'X')
2104
{
2105
while (more && args && (*args == '-' || *args == '/'))
2106
{
2107
switch(toupper(args[1]))
2108
{
2109
case 'C':
2110
{
2111
next_arg(args, &args);
2112
target_window = current_window;
2113
break;
2114
}
2115
case 'L':
2116
{
2117
flag_arg = next_arg(args, &args);
2118
if (toupper(flag_arg[2]) == 'I') /* LINE */
2119
{
2120
int to_line = 0;
2121
2122
if (!target_window)
2123
{
2124
debugyell("%s: -LINE only works if -WIN is specified first", command);
2125
target_window = old_target_window;
2126
return;
2127
}
2128
else if (target_window->scratch_line == -1)
2129
{
2130
debugyell("%s: -LINE only works on scratch windows", command);
2131
target_window = old_target_window;
2132
return;
2133
}
2134
2135
to_line = my_atol(next_arg(args, &args));
2136
if (to_line < 0 || to_line >= target_window->display_size)
2137
{
2138
debugyell("%s: -LINE %d is out of range for window (max %d)",
2139
command, to_line, target_window->display_size - 1);
2140
target_window = old_target_window;
2141
return;
2142
}
2143
target_window->scratch_line = to_line;
2144
}
2145
else /* LEVEL */
2146
{
2147
if (!(flag_arg = next_arg(args, &args)))
2148
break;
2149
if ((temp = parse_lastlog_level(flag_arg, 0)) != 0)
2150
{
2151
lastlog_level = set_lastlog_msg_level(temp);
2152
from_level = message_from_level(temp);
2153
}
2154
}
2155
break;
2156
}
2157
2158
case 'W':
2159
{
2160
flag_arg = next_arg(args, &args);
2161
if (!(flag_arg = next_arg(args, &args)))
2162
break;
2163
if (isdigit((unsigned char)*flag_arg))
2164
target_window = get_window_by_refnum(my_atol(flag_arg));
2165
else
2166
target_window = get_window_by_name(flag_arg);
2167
break;
2168
}
2169
2170
case 'T':
2171
{
2172
flag_arg = next_arg(args, &args);
2173
if (!(flag_arg = next_arg(args, &args)))
2174
break;
2175
target_window = get_window_target_by_desc(flag_arg);
2176
break;
2177
}
2178
case 'A':
2179
case '*':
2180
next_arg(args, &args);
2181
all_windows = 1;
2182
break;
2183
case 'K': /* X -- allow all attributes to be outputted */
2184
{
2185
next_arg(args, &args);
2186
2187
old_und = get_int_var(UNDERLINE_VIDEO_VAR);
2188
old_rev = get_int_var(INVERSE_VIDEO_VAR);
2189
old_bold = get_int_var(BOLD_VIDEO_VAR);
2190
old_color = get_int_var(COLOR_VAR);
2191
old_blink = get_int_var(BLINK_VIDEO_VAR);
2192
old_ansi = get_int_var(DISPLAY_ANSI_VAR);
2193
2194
set_int_var(UNDERLINE_VIDEO_VAR, 1);
2195
set_int_var(INVERSE_VIDEO_VAR, 1);
2196
set_int_var(BOLD_VIDEO_VAR, 1);
2197
set_int_var(COLOR_VAR, 1);
2198
set_int_var(BLINK_VIDEO_VAR, 1);
2199
set_int_var(DISPLAY_ANSI_VAR, 1);
2200
2201
xtended = 1;
2202
break;
2203
}
2204
case 'X':
2205
next_arg(args, &args);
2206
if (!(flag_arg = next_arg(args, &args)))
2207
break;
2208
x = my_atol(flag_arg);
2209
break;
2210
case 'Y':
2211
next_arg(args, &args);
2212
if (!(flag_arg = next_arg(args, &args)))
2213
break;
2214
y = my_atol(flag_arg);
2215
break;
2216
case 'R':
2217
next_arg(args, &args);
2218
if (target_window)
2219
output_screen = target_window->screen;
2220
else
2221
output_screen = current_window->screen;
2222
tputs_x(args);
2223
term_flush();
2224
target_window = old_target_window;
2225
return;
2226
case 'B':
2227
next_arg(args, &args);
2228
banner = 1;
2229
break;
2230
case 'N':
2231
next_arg(args, &args);
2232
no_log = 1;
2233
break;
2234
case 'S': /* SAY */
2235
{
2236
next_arg(args, &args);
2237
if (!window_display)
2238
{
2239
target_window = old_target_window;
2240
return;
2241
}
2242
break;
2243
}
2244
2245
case '-':
2246
{
2247
next_arg(args, &args);
2248
more = 0;
2249
break;
2250
}
2251
default:
2252
{
2253
more = 0;
2254
break;
2255
}
2256
}
2257
if (!args)
2258
args = empty_string;
2259
}
2260
}
2261
2262
display = window_display;
2263
window_display = 1;
2264
strip_ansi_in_echo = 0;
2265
2266
if (no_log)
2267
inhibit_logging = 1;
2268
2269
if (banner == 1)
2270
{
2271
malloc_strcpy(&stuff, numeric_banner());
2272
if (*stuff)
2273
{
2274
m_3cat(&stuff, space, args);
2275
args = stuff;
2276
}
2277
}
2278
else if (banner != 0)
2279
abort();
2280
2281
if (all_windows == 1)
2282
{
2283
Window *win = NULL;
2284
while ((traverse_all_windows(&win)))
2285
{
2286
target_window = win;
2287
put_echo(args);
2288
}
2289
}
2290
else if (all_windows != 0)
2291
abort();
2292
else if (x > -1 || y > -1 || raw)
2293
{
2294
if (x <= -1)
2295
x = 0;
2296
if (y <= -1)
2297
{
2298
if (target_window)
2299
y = target_window->cursor;
2300
else
2301
y = current_window->cursor;
2302
}
2303
if (!raw)
2304
term_move_cursor(x, y);
2305
tputs_x(args);
2306
term_flush();
2307
}
2308
else
2309
put_echo(args);
2310
2311
strip_ansi_in_echo = 1;
2312
if (xtended)
2313
{
2314
set_int_var(UNDERLINE_VIDEO_VAR, old_und);
2315
set_int_var(INVERSE_VIDEO_VAR, old_rev);
2316
set_int_var(BOLD_VIDEO_VAR, old_bold);
2317
set_int_var(COLOR_VAR, old_color);
2318
set_int_var(BLINK_VIDEO_VAR, old_blink);
2319
set_int_var(DISPLAY_ANSI_VAR, old_ansi);
2320
}
2321
if (lastlog_level)
2322
{
2323
set_lastlog_msg_level(lastlog_level);
2324
message_from_level(from_level);
2325
}
2326
if (stuff)
2327
new_free(&stuff);
2328
if (no_log)
2329
inhibit_logging = 0;
2330
window_display = display;
2331
set_display_target(saved_from, saved_level);
2332
target_window = old_target_window;
2333
}
2334
2335
/*
2336
*/
2337
2338
static void oper_password_received(char *data, char *line)
2339
{
2340
send_to_server("OPER %s %s", data, line);
2341
if (line && *line)
2342
memset(line, 0, strlen(line)-1);
2343
}
2344
2345
/* oper: the OPER command. */
2346
BUILT_IN_COMMAND(oper)
2347
{
2348
char *password;
2349
char *nick;
2350
2351
oper_command = 1;
2352
if (!(nick = next_arg(args, &args)))
2353
nick = get_server_nickname(from_server);
2354
if (!(password = next_arg(args, &args)))
2355
{
2356
add_wait_prompt("Operator Password:", oper_password_received, nick, WAIT_PROMPT_LINE, 0);
2357
return;
2358
}
2359
send_to_server("OPER %s %s", nick, password);
2360
memset(password, 0, strlen(password));
2361
}
2362
2363
#ifndef PUBLIC_ACCESS
2364
/* This generates a file of your ircII setup */
2365
void really_save(char *ircrc_file, int flags, int save_all, int save_append)
2366
{
2367
FILE *fp;
2368
char * mode[] = {"w", "a"};
2369
2370
if ((fp = fopen(ircrc_file, mode[save_append])) != NULL)
2371
{
2372
if (flags & SFLAG_ALIAS)
2373
save_aliases(fp, save_all);
2374
if (flags & SFLAG_ASSIGN)
2375
save_assigns(fp, save_all);
2376
if (flags & SFLAG_BIND)
2377
save_bindings(fp, save_all);
2378
if (flags & SFLAG_ON)
2379
save_hooks(fp, save_all);
2380
if (flags & SFLAG_NOTIFY)
2381
save_notify(fp);
2382
if (flags & SFLAG_WATCH)
2383
save_watch(fp);
2384
if (flags & SFLAG_SET)
2385
save_variables(fp, save_all);
2386
if (flags & SFLAG_SERVER)
2387
save_servers(fp);
2388
fclose(fp);
2389
bitchsay("IRCII settings saved to %s", ircrc_file);
2390
}
2391
else
2392
bitchsay("Error opening %s: %s", ircrc_file, strerror(errno));
2393
}
2394
#endif
2395
2396
/* Full scale abort. Does a "save" into the filename in line, and
2397
then does a coredump */
2398
BUILT_IN_COMMAND(abortcmd)
2399
{
2400
#ifdef PUBLIC_ACCESS
2401
bitchsay("This command has been disabled on a public access system");
2402
return;
2403
#else
2404
char *filename = next_arg(args, &args);
2405
2406
filename = filename ? filename : "irc.aborted";
2407
really_save(filename, SFLAG_ALL, 0, 0);
2408
abort();
2409
#endif
2410
}
2411
2412
2413
2414
/* save_settings: saves the current state of IRCII to a file */
2415
BUILT_IN_COMMAND(save_settings)
2416
{
2417
#ifdef PUBLIC_ACCESS
2418
bitchsay("This command has been disabled on a public access system");
2419
return;
2420
#else
2421
char *arg = NULL;
2422
char *fn = NULL;
2423
int save_append = 0;
2424
int save_global = 0;
2425
int save_flags = 0;
2426
2427
while ((arg = next_arg(args, &args)) != NULL)
2428
{
2429
if ('-' != *arg && '/' != *arg) {
2430
fn = arg;
2431
continue;
2432
}
2433
upper(++arg);
2434
if (!strncmp("ALIAS", arg, 3))
2435
save_flags |= SFLAG_ALIAS;
2436
else if (!strncmp("ASSIGN", arg, 2))
2437
save_flags |= SFLAG_ALIAS;
2438
else if (!strncmp("BIND", arg, 1))
2439
save_flags |= SFLAG_BIND;
2440
else if (!strncmp("ON", arg, 1))
2441
save_flags |= SFLAG_ON;
2442
else if (!strncmp("SERVER", arg, 3))
2443
save_flags |= SFLAG_SERVER;
2444
else if (!strncmp("SET", arg, 3))
2445
save_flags |= SFLAG_SET;
2446
else if (!strncmp("NOTIFY", arg, 1))
2447
save_flags |= SFLAG_NOTIFY;
2448
else if (!strncmp("WATCH", arg, 1))
2449
save_flags |= SFLAG_WATCH;
2450
else if (!strncmp("ALL", arg, 3))
2451
save_flags = SFLAG_ALL;
2452
else if (!strncmp("APPEND", arg, 3))
2453
save_append = 1;
2454
else if (!strncmp("GLOBAL", arg, 2))
2455
save_global = 1;
2456
else if (!strncmp("FILE", arg, 1))
2457
fn = next_arg(args, &args);
2458
else
2459
bitchsay("Unrecognised option");
2460
}
2461
2462
if (!save_flags)
2463
return;
2464
2465
if (!(arg = expand_twiddle((fn && *fn) ? fn : bircrc_file)))
2466
{
2467
bitchsay("Unknown user");
2468
return;
2469
}
2470
2471
really_save(arg, save_flags, save_global, save_append);
2472
new_free(&arg);
2473
#endif
2474
}
2475
2476
2477
BUILT_IN_COMMAND(usleepcmd)
2478
{
2479
char *arg;
2480
struct timeval pause;
2481
time_t nms;
2482
2483
if ((arg = next_arg(args, &args)))
2484
{
2485
nms = (time_t)my_atol(arg);
2486
pause.tv_sec = nms / 1000000;
2487
pause.tv_usec = nms % 1000000;
2488
select(0, NULL, NULL, NULL, &pause);
2489
}
2490
else
2491
say("Usage: USLEEP <usec>");
2492
}
2493
2494
AJoinList *add_to_ajoin_list(char *channel, char *args, int type)
2495
{
2496
/* type == 1, then we have a real autojoin entry.
2497
* type == 0, then it's just a channel to join.
2498
*/
2499
AJoinList *new = NULL;
2500
2501
if (!(new = (AJoinList *)list_lookup((List **) &ajoin_list, channel, 0, !REMOVE_FROM_LIST)))
2502
{
2503
char *key, *group;
2504
key = next_arg(args, &args);
2505
2506
new = (AJoinList *) new_malloc(sizeof(AJoinList));
2507
new->name = m_strdup(channel);
2508
if(key && *key == '-')
2509
{
2510
group = next_arg(args, &args);
2511
2512
if(group)
2513
new->group = m_strdup(group);
2514
key = next_arg(args, &args);
2515
}
2516
if (key && *key)
2517
new->key = m_strdup(key);
2518
new->ajoin_list = type;
2519
new->server = -1;
2520
add_to_list((List **)&ajoin_list, (List *)new);
2521
}
2522
return new;
2523
}
2524
2525
BUILT_IN_COMMAND(auto_join)
2526
{
2527
char *channel = NULL;
2528
AJoinList *new = NULL;
2529
extern int run_level, do_ignore_ajoin;
2530
2531
if (command && *command && !my_stricmp(command, "AJoinList"))
2532
{
2533
int count = 0;
2534
for (new = ajoin_list; new; new = new->next)
2535
{
2536
if (!new->ajoin_list) continue;
2537
if (!count)
2538
put_it("AJoin List");
2539
put_it("%20s server/group: %s%s%s", new->name, new->group?new->group:"<none>",
2540
new->key?" key: ":empty_string, new->key?new->key:empty_string);
2541
count++;
2542
}
2543
if (count)
2544
put_it("End of AJoin List");
2545
return;
2546
}
2547
if (!args || !*args)
2548
return;
2549
2550
/* If the user used the ignore ajoin switch and
2551
* we aren't in interactive mode, abort.
2552
*/
2553
if(do_ignore_ajoin && run_level != 2)
2554
return;
2555
2556
channel = next_arg(args, &args);
2557
if (command && *command && !my_stricmp(command, "UNAJOIN"))
2558
{
2559
if (channel && (new = (AJoinList *)remove_from_list((List **)&ajoin_list, make_channel(channel))))
2560
{
2561
if (new->ajoin_list)
2562
{
2563
bitchsay("Removing Auto-Join channel %s", new->name);
2564
new_free(&new->name);
2565
new_free(&new->key);
2566
new_free((char **)&new);
2567
} else
2568
add_to_list((List **)&ajoin_list, (List *)new);
2569
}
2570
return;
2571
}
2572
2573
if (!channel || !(new = add_to_ajoin_list(make_channel(channel), args, 1)))
2574
return;
2575
if (is_server_connected(from_server)/* && get_server_channels(from_server)*/)
2576
{
2577
bitchsay("Auto-Joining %s%s%s", new->name, new->key?space:empty_string, new->key?new->key:empty_string);
2578
if(!new->group || is_server_valid(new->group, from_server))
2579
{
2580
if(get_int_var(JOIN_NEW_WINDOW_VAR) && (current_window->current_channel || current_window->query_nick))
2581
win_create(JOIN_NEW_WINDOW_VAR, 0);
2582
send_to_server("JOIN %s %s", new->name, new->key? new->key:empty_string);
2583
}
2584
}
2585
}
2586
2587
/*
2588
* e_channel: does the channel command. I just added displaying your current
2589
* channel if none is given
2590
*/
2591
BUILT_IN_COMMAND(e_channel)
2592
{
2593
char *chan;
2594
int len;
2595
char *buffer=NULL;
2596
2597
set_display_target(NULL, LOG_CURRENT);
2598
if ((chan = next_arg(args, &args)) != NULL)
2599
{
2600
len = strlen(chan);
2601
if (!my_strnicmp(chan, "-i", 2))
2602
{
2603
if (invite_channel)
2604
send_to_server("%s %s %s", command, invite_channel, args);
2605
else
2606
bitchsay("You have not been invited to a channel!");
2607
}
2608
else
2609
{
2610
if (!(buffer = make_channel(chan)))
2611
return;
2612
if (!is_server_connected(from_server))
2613
add_to_ajoin_list(buffer, args, 0);
2614
else if (is_on_channel(buffer, from_server, get_server_nickname(from_server)))
2615
{
2616
/* XXXX -
2617
right here we want to check to see if the
2618
channel is bound to this window. if it is,
2619
we set it as the default channel. If it
2620
is not, we warn the user that we cant do it
2621
*/
2622
if (is_bound_anywhere(buffer) &&
2623
!(is_bound_to_window(current_window, buffer)))
2624
bitchsay("Channel %s is bound to another window", buffer);
2625
2626
else
2627
{
2628
is_current_channel(buffer, from_server, 1);
2629
if (do_hook(CHANNEL_SWITCH_LIST, "%s", set_current_channel_by_refnum(0, buffer)))
2630
bitchsay("You are now talking to channel %s", set_current_channel_by_refnum(0, buffer));
2631
update_all_windows();
2632
set_input_prompt(current_window, get_string_var(INPUT_PROMPT_VAR), 0);
2633
update_input(UPDATE_ALL);
2634
}
2635
}
2636
else
2637
{
2638
if(get_int_var(JOIN_NEW_WINDOW_VAR) && (current_window->current_channel || current_window->query_nick))
2639
win_create(JOIN_NEW_WINDOW_VAR, 0);
2640
send_to_server("%s %s%s%s", command, buffer, args?space:empty_string, args?args:empty_string);
2641
if (!is_bound(buffer, from_server))
2642
malloc_strcpy(&current_window->waiting_channel, buffer);
2643
}
2644
}
2645
update_all_status(current_window, NULL, 0);
2646
}
2647
else
2648
list_channels();
2649
reset_display_target();
2650
}
2651
2652
/* comment: does the /COMMENT command, useful in .ircrc */
2653
BUILT_IN_COMMAND(comment)
2654
{
2655
/* nothing to do... */
2656
}
2657
2658
/*
2659
* e_nick: does the /NICK command. Records the users current nickname and
2660
* sends the command on to the server
2661
*/
2662
BUILT_IN_COMMAND(e_nick)
2663
{
2664
char *nick;
2665
2666
2667
if (!(nick = next_arg(args, &args)))
2668
{
2669
bitchsay("Your nickname is %s", get_server_nickname(get_window_server(0)));
2670
if (get_pending_nickname(get_window_server(0)))
2671
say("A nickname change to %s is pending.", get_pending_nickname(get_window_server(0)));
2672
2673
return;
2674
}
2675
if (!(nick = check_nickname(nick)))
2676
{
2677
bitchsay("Nickname specified is illegal.");
2678
return;
2679
}
2680
nick_command_is_pending(from_server, 1);
2681
change_server_nickname(from_server, nick);
2682
set_string_var(AUTO_RESPONSE_STR_VAR, nick);
2683
}
2684
2685
/* version: does the /VERSION command with some IRCII version stuff */
2686
BUILT_IN_COMMAND(version1)
2687
{
2688
char *host;
2689
2690
2691
if ((host = next_arg(args, &args)) != NULL)
2692
send_to_server("%s %s", command, host);
2693
else
2694
{
2695
bitchsay("Client: %s (internal version %s)", irc_version, internal_version);
2696
send_to_server("%s", command);
2697
}
2698
}
2699
2700
/* Functions used by e_hostname to generate a list of local interface
2701
* addreses (vhosts).
2702
*/
2703
2704
/* add_address()
2705
*
2706
* This converts a local address to a character string, and adds it to the
2707
* list of addresses if not a duplicate or a special address. If norev
2708
* is not set, it also looks up the hostname.
2709
*/
2710
void add_address(Virtuals **vhost_list, int norev, struct sockaddr *sa)
2711
{
2712
struct sockaddr_in * const sin = (struct sockaddr_in *)sa;
2713
const char *result = NULL;
2714
Virtuals *vhost;
2715
#ifdef IPV6
2716
struct sockaddr_in6 * const sin6 = (struct sockaddr_in6 *)sa;
2717
char addr[128];
2718
socklen_t slen = 0;
2719
#else
2720
struct hostent *host;
2721
#endif /* IPV6 */
2722
2723
#ifdef IPV6
2724
if (sa->sa_family == AF_INET)
2725
{
2726
slen = sizeof(struct sockaddr);
2727
result = inet_ntop(sa->sa_family, &sin->sin_addr, addr, sizeof addr);
2728
}
2729
else if (sa->sa_family == AF_INET6)
2730
{
2731
slen = sizeof(struct sockaddr_in6);
2732
result = inet_ntop(sa->sa_family, &sin6->sin6_addr, addr, sizeof addr);
2733
}
2734
#else /* IPV6 */
2735
if (sa->sa_family == AF_INET)
2736
{
2737
result = inet_ntoa(sin->sin_addr);
2738
}
2739
#endif
2740
2741
if (result == NULL)
2742
return;
2743
2744
/* Ignore INADDR_ANY, loopback and link-local addresses (see RFC 2373) */
2745
if (!strcmp(result, "127.0.0.1") ||
2746
!strcmp(result, "0.0.0.0") ||
2747
!strcmp(result, "::1") ||
2748
!strcmp(result, "0::1") ||
2749
!strcmp(result, "::") ||
2750
!strcmp(result, "0::0") ||
2751
!strncasecmp(result, "fe8", 3) ||
2752
!strncasecmp(result, "fe9", 3) ||
2753
!strncasecmp(result, "fea", 3) ||
2754
!strncasecmp(result, "feb", 3))
2755
{
2756
return;
2757
}
2758
2759
for (vhost = *vhost_list; vhost ; vhost = vhost->next)
2760
{
2761
/* Ignore duplicates */
2762
if (!strcasecmp(result, vhost->address))
2763
return;
2764
}
2765
2766
/* Got a new address, so add it to the list */
2767
vhost = (Virtuals *) new_malloc(sizeof(Virtuals));
2768
2769
/* Set the address and hostname strings */
2770
vhost->address = m_strdup(result);
2771
#ifdef IPV6
2772
if (!norev && !getnameinfo(sa, slen, addr, sizeof addr, NULL, 0, 0))
2773
{
2774
vhost->hostname = m_strdup(addr);
2775
}
2776
else
2777
{
2778
vhost->hostname = m_strdup(result);
2779
}
2780
#else
2781
if (!norev && (host = gethostbyaddr(&sin->sin_addr, sizeof(sin->sin_addr),
2782
AF_INET)))
2783
{
2784
vhost->hostname = m_strdup(host->h_name);
2785
}
2786
else
2787
{
2788
vhost->hostname = m_strdup(result);
2789
}
2790
#endif
2791
2792
add_to_list((List **)vhost_list, (List *)vhost);
2793
2794
return;
2795
}
2796
2797
#ifdef IPV6
2798
/* add_addrs_getifaddrs()
2799
*
2800
* This uses getifaddrs() to find local interface addresses.
2801
* On some older versions of glibc this only finds IPv4 addreses. */
2802
void add_addrs_getifaddrs(Virtuals **vhost_list, int norev)
2803
{
2804
struct ifaddrs *addr_list, *ifa;
2805
2806
if (getifaddrs(&addr_list) != 0)
2807
{
2808
yell("getifaddrs() failed.");
2809
return;
2810
}
2811
2812
for (ifa = addr_list; ifa; ifa = ifa->ifa_next)
2813
{
2814
if ((ifa->ifa_flags & IFF_UP) && ifa->ifa_addr)
2815
add_address(vhost_list, norev, ifa->ifa_addr);
2816
}
2817
2818
freeifaddrs(addr_list);
2819
return;
2820
}
2821
2822
/* add_addrs_proc_net
2823
*
2824
* For the benefit of systems with the older glibc, this function looks
2825
* in /proc/net/if_inet6 for IPv6 addresses. This is called on all IPv6
2826
* platforms, but if /proc/net/if_inet6 doesn't exist, no harm, no foul.
2827
*
2828
* A line in this file looks like:
2829
fe80000000000000025056fffec00008 0a 40 20 80 vmnet8
2830
*/
2831
void add_addrs_proc_net(Virtuals **vhost_list, int norev)
2832
{
2833
FILE *fptr;
2834
char proc_net_line[200];
2835
char address[64];
2836
char *p;
2837
int i;
2838
struct sockaddr_in6 sin6;
2839
2840
if ((fptr = fopen("/proc/net/if_inet6", "r")) == NULL)
2841
{
2842
return;
2843
}
2844
2845
2846
while (fgets(proc_net_line, sizeof proc_net_line, fptr))
2847
{
2848
/* Copy the address, adding : as necessary */
2849
p = address;
2850
2851
for (i = 0; i < 32 && proc_net_line[i]; i++)
2852
{
2853
*p++ = proc_net_line[i];
2854
if ((i < 31) && (i % 4 == 3))
2855
{
2856
*p++ = ':';
2857
}
2858
}
2859
*p = '\0';
2860
2861
/* We rely on inet_pton to catch any bogus addresses here */
2862
if (inet_pton(AF_INET6, p, &sin6.sin6_addr) > 0)
2863
{
2864
sin6.sin6_family = AF_INET6;
2865
2866
add_address(vhost_list, norev, (struct sockaddr *)&sin6);
2867
}
2868
}
2869
2870
fclose(fptr);
2871
return;
2872
}
2873
2874
#endif /* ifdef IPV6 */
2875
2876
#if defined(SANE_SIOCGIFCONF)
2877
/* add_addrs_ioctl
2878
*
2879
* This uses the old SIOCGIFCONF ioctl to find local interface addresses.
2880
* It can only find IPv4 addresses.
2881
*/
2882
void add_addrs_ioctl(Virtuals **vhost_list, int norev)
2883
{
2884
int s;
2885
size_t len;
2886
char *buf = NULL;
2887
struct ifconf ifc;
2888
struct ifreq *ifr;
2889
2890
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
2891
return;
2892
2893
len = 0;
2894
do {
2895
len += 4 * sizeof(*ifr);
2896
RESIZE(buf, char, len);
2897
2898
ifc.ifc_buf = buf;
2899
ifc.ifc_len = len;
2900
2901
if (ioctl(s, SANE_SIOCGIFCONF, &ifc) < 0)
2902
return;
2903
} while ((ifc.ifc_len + sizeof(*ifr) + 64 >= len) && (len < 200000));
2904
2905
for (ifr = (struct ifreq *)buf; (char *)ifr < buf + ifc.ifc_len; ifr++)
2906
{
2907
if (ioctl(s, SIOCGIFFLAGS, (char *)ifr) != 0)
2908
continue;
2909
2910
if (!(ifr->ifr_flags & IFF_UP))
2911
continue;
2912
2913
if (ioctl(s, SIOCGIFADDR,(char *)ifr) != 0)
2914
continue;
2915
2916
add_address(vhost_list, norev, &ifr->ifr_addr);
2917
}
2918
2919
close(s);
2920
return;
2921
}
2922
#endif /* if defined(SANE_SIOCGIFCONF) */
2923
2924
/* get_local_addrs
2925
*
2926
* Construct a linked list of local interface addresses, using whatever
2927
* methods are appropriate on the platform.
2928
*/
2929
void get_local_addrs(Virtuals **vhost_list, int norev)
2930
{
2931
*vhost_list = NULL;
2932
2933
#ifdef IPV6
2934
add_addrs_getifaddrs(vhost_list, norev);
2935
add_addrs_proc_net(vhost_list, norev);
2936
#elif defined(SANE_SIOCGIFCONF)
2937
add_addrs_ioctl(vhost_list, norev);
2938
#endif
2939
}
2940
2941
BUILT_IN_COMMAND(e_hostname)
2942
{
2943
int norev = 0;
2944
char *newhost = NULL;
2945
char *arg = next_arg(args, &args);
2946
2947
if (arg && !strcasecmp(arg, "-norev"))
2948
{
2949
norev = 1;
2950
arg = next_arg(args, &args);
2951
}
2952
2953
if (arg && *arg && *arg != '#' && !is_number(arg))
2954
{
2955
malloc_strcpy(&newhost, arg);
2956
}
2957
else
2958
{
2959
Virtuals *virtuals, *new;
2960
int i;
2961
int switch_to = 0;
2962
2963
if (arg)
2964
{
2965
if (*arg == '#')
2966
arg++;
2967
2968
switch_to = my_atol(arg);
2969
}
2970
2971
get_local_addrs(&virtuals, norev);
2972
2973
for (i = 1; virtuals; i++)
2974
{
2975
new = virtuals;
2976
virtuals = virtuals->next;
2977
if (i == 1)
2978
put_it("%s", convert_output_format("$G Current hostnames available", NULL, NULL));
2979
2980
put_it("%s", convert_output_format("%K[%W$[3]0%K] %B$1", "%d %s", i, new->hostname));
2981
if (i == switch_to)
2982
newhost = new->hostname;
2983
else
2984
new_free(&new->hostname);
2985
new_free(&new->address);
2986
new_free(&new);
2987
}
2988
}
2989
2990
if (newhost)
2991
{
2992
int reconn = 0;
2993
#ifndef IPV6
2994
struct hostent *hp;
2995
#endif
2996
2997
/* Reconnect if hostname has changed */
2998
if (LocalHostName && strcmp(LocalHostName, newhost))
2999
reconn = 1;
3000
3001
malloc_strcpy(&LocalHostName, newhost);
3002
#ifndef IPV6
3003
if ((hp = gethostbyname(LocalHostName)))
3004
memcpy((void *)&LocalHostAddr.sf_addr, hp->h_addr, sizeof(struct in_addr));
3005
#endif
3006
3007
bitchsay("Local host name is now [%s]", LocalHostName);
3008
new_free(&newhost);
3009
3010
if (reconn)
3011
reconnect_cmd(NULL, NULL, NULL, NULL);
3012
}
3013
}
3014
3015
extern void display_bitchx (int);
3016
3017
BUILT_IN_COMMAND(info)
3018
{
3019
3020
if (!args || !*args)
3021
{
3022
display_bitchx(-1);
3023
return;
3024
}
3025
else if (isdigit((unsigned char)*args))
3026
{
3027
display_bitchx(my_atol(args));
3028
return;
3029
}
3030
send_to_server("%s %s", command, args);
3031
}
3032
3033
BUILT_IN_COMMAND(setenvcmd)
3034
{
3035
char *env_var;
3036
3037
if ((env_var = next_arg(args, &args)) != NULL)
3038
bsd_setenv(env_var, args, 1);
3039
else
3040
say("Usage: SETENV <var-name> <value>");
3041
}
3042
3043
/*
3044
* whois: the WHOIS and WHOWAS commands. This translates the
3045
* to the whois handlers in whois.c
3046
*/
3047
BUILT_IN_COMMAND(whois)
3048
{
3049
char *nick;
3050
if (!my_stricmp(command, "WHOWAS"))
3051
{
3052
char *word_one = next_arg (args, &args);
3053
#if 0
3054
if (args && *args)
3055
malloc_sprintf(&stuff, "%s %s", word_one, args);
3056
else if (word_one && *word_one)
3057
malloc_sprintf(&stuff, "%s %d", word_one, get_int_var(NUM_OF_WHOWAS_VAR));
3058
else
3059
malloc_sprintf(&stuff, "%s %d", get_server_nickname(from_server), get_int_var(NUM_OF_WHOWAS_VAR));
3060
#endif
3061
send_to_server("WHOWAS %s %s", (word_one && *word_one) ?
3062
word_one : get_server_nickname(from_server),
3063
(args && *args) ? args : ltoa(get_int_var(NUM_OF_WHOWAS_VAR)));
3064
return;
3065
}
3066
if (!(nick = next_arg(args, &args))) /* whois command */
3067
{
3068
char *target;
3069
target = get_target_by_refnum(0);
3070
if (target && !is_channel(target))
3071
send_to_server("WHOIS %s", target);
3072
else
3073
send_to_server("WHOIS %s", get_server_nickname(from_server));
3074
}
3075
else
3076
send_to_server("WHOIS %s%s%s", nick, (args && *args) ? space : empty_string, (args && *args)? args : empty_string);
3077
}
3078
3079
3080
/*
3081
* query: the /QUERY command. Works much like the /MSG, I'll let you figure
3082
* it out.
3083
*/
3084
BUILT_IN_COMMAND(query)
3085
{
3086
if(args && *args)
3087
win_create(QUERY_NEW_WINDOW_VAR, 0);
3088
window_query(current_window, &args, NULL);
3089
update_window_status(current_window, 0);
3090
}
3091
3092
void read_away_log(char *stuff, char *line)
3093
{
3094
3095
if (!line || !*line || (line && toupper(*line) == 'Y'))
3096
readlog(NULL, NULL, NULL, NULL);
3097
update_input(UPDATE_ALL);
3098
}
3099
3100
BUILT_IN_COMMAND(back)
3101
{
3102
int minutes = 0;
3103
int hours = 0;
3104
int seconds = 0;
3105
int silent = 0;
3106
3107
if (!current_window || from_server == -1)
3108
return;
3109
if (command && !my_stricmp(command, "gone"))
3110
silent = 1;
3111
if (get_server_awaytime(from_server))
3112
{
3113
time_t current_t = now - get_server_awaytime(from_server);
3114
int old_server = from_server;
3115
from_server = current_window->server;
3116
3117
hours = current_t / 3600;
3118
minutes = (current_t - (hours * 3600)) / 60;
3119
seconds = current_t % 60;
3120
3121
3122
if (get_int_var(SEND_AWAY_MSG_VAR) && !silent)
3123
{
3124
bitchsay("You were /away for %i hours %i minutes and %i seconds. [\002BX\002-MsgLog %s]",
3125
hours, minutes, seconds,
3126
on_off(get_int_var(MSGLOG_VAR)));
3127
{
3128
char str[BIG_BUFFER_SIZE+1];
3129
char reason[BIG_BUFFER_SIZE+1];
3130
char fset[BIG_BUFFER_SIZE+1];
3131
*reason = 0;
3132
quote_it(args ? args : get_server_away(from_server), NULL, reason);
3133
if(fget_string_var(FORMAT_BACK_FSET))
3134
{
3135
quote_it(stripansicodes(convert_output_format(fget_string_var(FORMAT_BACK_FSET), "%s %d %d %d %d %s",
3136
update_clock(GET_TIME), hours, minutes, seconds,
3137
get_int_var(MSGCOUNT_VAR), reason)), NULL, fset);
3138
snprintf(str, BIG_BUFFER_SIZE,
3139
"PRIVMSG %%s :ACTION %s", fset);
3140
send_msg_to_channels(get_server_channels(from_server), from_server, str);
3141
}
3142
}
3143
}
3144
set_server_away(from_server, NULL, silent);
3145
from_server = old_server;
3146
}
3147
else
3148
set_server_away(from_server, NULL, silent);
3149
if (get_int_var(MSGLOG_VAR))
3150
log_toggle(0, NULL);
3151
3152
set_server_awaytime(from_server, 0);
3153
if (get_int_var(MSGLOG_VAR))
3154
{
3155
char tmp[100];
3156
sprintf(tmp, " read /away msgs (%d msg%s) log [Y/n]? ", get_int_var(MSGCOUNT_VAR), plural(get_int_var(MSGCOUNT_VAR)));
3157
add_wait_prompt(tmp, read_away_log, empty_string, WAIT_PROMPT_LINE, 1);
3158
}
3159
set_int_var(MSGCOUNT_VAR, 0);
3160
update_all_status(current_window, NULL, 0);
3161
}
3162
3163
/*
3164
* away: the /AWAY command. Keeps track of the away message locally, and
3165
* sends the command on to the server.
3166
*/
3167
BUILT_IN_COMMAND(away)
3168
{
3169
int len;
3170
char *arg = NULL;
3171
int flag = AWAY_ONE;
3172
int i,
3173
silent = 0;
3174
3175
3176
if (command && !my_stricmp(command, "awaymsg"))
3177
{
3178
extern char *awaymsg;
3179
if (args && *args)
3180
{
3181
malloc_strcpy(&awaymsg, args);
3182
bitchsay("Your auto-away msg has been set to \"%s\"", awaymsg);
3183
}
3184
else
3185
{
3186
new_free(&awaymsg);
3187
bitchsay("Your auto-away msg has been unset");
3188
}
3189
return;
3190
}
3191
if (*args)
3192
{
3193
if ((*args == '-') || (*args == '/'))
3194
{
3195
arg = strchr(args, ' ');
3196
if (arg)
3197
*arg++ = '\0';
3198
else
3199
arg = empty_string;
3200
len = strlen(args);
3201
if (!my_strnicmp(args+1, "A", 1)) /* all */
3202
{
3203
flag = AWAY_ALL;
3204
args = arg;
3205
}
3206
else if (!my_strnicmp(args+1, "O", 1))/* one */
3207
{
3208
flag = AWAY_ONE;
3209
args = arg;
3210
}
3211
else
3212
return;
3213
}
3214
}
3215
if (command && !my_stricmp(command, "gone"))
3216
silent = 1;
3217
if (flag == AWAY_ALL)
3218
{
3219
for (i = 0; i < server_list_size(); i++)
3220
set_server_away(i, args, silent);
3221
}
3222
else
3223
{
3224
if (args && *args)
3225
set_server_away(from_server, args, silent);
3226
else
3227
back(command, args, NULL, NULL);
3228
}
3229
update_all_status(current_window, NULL, 0);
3230
}
3231
3232
#if 0
3233
#ifndef RAND_MAX
3234
#define RAND_MAX 213234444
3235
#endif
3236
#endif
3237
3238
static void real_quit (char *dummy, char *ptr)
3239
{
3240
3241
if (ptr && *ptr)
3242
{
3243
if (*ptr == 'Y' || *ptr == 'y')
3244
{
3245
irc_exit(1, dummy, "%s", convert_output_format(fget_string_var(FORMAT_SIGNOFF_FSET), "%s %s %s %s", update_clock(GET_TIME), get_server_nickname(get_window_server(0)), m_sprintf("%s@%s", username, hostname), dummy));
3246
}
3247
}
3248
bitchsay("Excelllaaant!!");
3249
}
3250
3251
/* e_quit: The /QUIT, /EXIT, etc command */
3252
BUILT_IN_COMMAND(e_quit)
3253
{
3254
int old_server = from_server;
3255
char Reason[BIG_BUFFER_SIZE];
3256
int active_dcc = 0;
3257
3258
3259
if (args && *args)
3260
strcpy(Reason, args);
3261
else
3262
strcpy(Reason, get_signoffreason(get_server_nickname(from_server)));
3263
if (!*Reason)
3264
strcpy(Reason, irc_version);
3265
3266
active_dcc = get_active_count();
3267
if (active_dcc)
3268
add_wait_prompt("Active DCC\'s. Really Quit [y/N] ? ", real_quit, Reason, WAIT_PROMPT_LINE, 1);
3269
else
3270
{
3271
from_server = old_server;
3272
irc_exit(1, Reason, "%s", convert_output_format(fget_string_var(FORMAT_SIGNOFF_FSET), "%s %s %s %s", update_clock(GET_TIME), get_server_nickname(get_window_server(0)), m_sprintf("%s@%s", username, hostname), Reason));
3273
}
3274
}
3275
3276
/* flush: flushes all pending stuff coming from the server */
3277
BUILT_IN_COMMAND(flush)
3278
{
3279
3280
if (get_int_var(HOLD_MODE_VAR))
3281
flush_everything_being_held(NULL);
3282
bitchsay("Standby, Flushing server output...");
3283
flush_server();
3284
bitchsay("Done");
3285
}
3286
3287
/* e_wall: used for WALLOPS */
3288
BUILT_IN_COMMAND(e_wall)
3289
{
3290
3291
if ((!args || !*args))
3292
return;
3293
set_display_target(NULL, LOG_WALLOP);
3294
send_to_server("%s :%s", command, args);
3295
if (get_server_flag(from_server, USER_MODE_W))
3296
put_it("!! %s", args);
3297
add_last_type(&last_sent_wall[0], 1, get_server_nickname(from_server), NULL, "*", args);
3298
reset_display_target();
3299
}
3300
3301
/*
3302
* e_privmsg: The MSG command, displaying a message on the screen indicating
3303
* the message was sent. Also, this works for the NOTICE command.
3304
*/
3305
BUILT_IN_COMMAND(e_privmsg)
3306
{
3307
char *nick;
3308
3309
3310
if ((nick = next_arg(args, &args)) != NULL)
3311
{
3312
if (!strcmp(nick, "."))
3313
{
3314
if (!(nick = get_server_sent_nick(from_server)))
3315
{
3316
bitchsay("You have not sent a message to anyone yet");
3317
return;
3318
}
3319
}
3320
else if (!strcmp(nick, ","))
3321
{
3322
if (!(nick = get_server_recv_nick(from_server)))
3323
{
3324
bitchsay("You have not received a message from anyone yet");
3325
return;
3326
}
3327
}
3328
else if (!strcmp(nick, "*") && (!(nick = get_current_channel_by_refnum(0))))
3329
nick = zero;
3330
send_text(nick, args, command, window_display, 1);
3331
}
3332
}
3333
3334
/*
3335
* quote: handles the QUOTE command. args are a direct server command which
3336
* is simply send directly to the server
3337
*/
3338
BUILT_IN_COMMAND(quotecmd)
3339
{
3340
int old_from_server = from_server;
3341
int all_servers = 0;
3342
3343
if (command && *command == 'X')
3344
{
3345
while (args && (*args == '-' || *args == '/'))
3346
{
3347
char *flag = next_arg(args, &args);
3348
if (!my_strnicmp(flag + 1, "S", 1)) /* SERVER */
3349
{
3350
int sval = my_atol(next_arg(args, &args));
3351
if (is_server_open(sval))
3352
from_server = sval;
3353
}
3354
else if (!my_strnicmp(flag+1, "ALL", 3) && args && *args)
3355
{
3356
next_arg(args, &args);
3357
all_servers++;
3358
}
3359
}
3360
}
3361
3362
3363
if (args && *args)
3364
{
3365
char *comm = new_next_arg(args, &args);
3366
protocol_command *p;
3367
int cnt;
3368
int loc;
3369
3370
upper(comm);
3371
p = (protocol_command *)find_fixed_array_item(
3372
(void *)rfc1459, sizeof(protocol_command),
3373
num_protocol_cmds + 1, comm, &cnt, &loc);
3374
3375
/*
3376
* If theyre dispatching some protocol commands we
3377
* dont know about, then let them, without complaint.
3378
*/
3379
#if 0
3380
if (cnt < 0 && (rfc1459[loc].flags & PROTO_NOQUOTE))
3381
{
3382
yell("Doing /QUOTE %s is not permitted. Use the client's built in command instead.", comm);
3383
from_server = old_from_server;
3384
return;
3385
}
3386
#endif
3387
/*
3388
* If we know its going to cause a problem in the
3389
* future, whine about it.
3390
*/
3391
#if 0
3392
if (cnt < 0 && (rfc1459[loc].flags & PROTO_DEPREC))
3393
yell("Doing /QUOTE %s is discouraged because it will break the client in the future. Use the client's built in command instead.", comm);
3394
#endif
3395
if (all_servers)
3396
{
3397
int i;
3398
for (i = 0; i < server_list_size(); i++)
3399
{
3400
if (is_server_connected(i))
3401
{
3402
from_server = i;
3403
send_to_server("%s %s", comm, args ? args:empty_string);
3404
rfc1459[loc].bytes += strlen(args);
3405
rfc1459[loc].count++;
3406
}
3407
}
3408
}
3409
else
3410
{
3411
send_to_server("%s %s", comm, args ? args : empty_string);
3412
rfc1459[loc].bytes += strlen(comm) + (args? strlen(args) : 0);
3413
rfc1459[loc].count++;
3414
}
3415
}
3416
3417
from_server = old_from_server;
3418
}
3419
3420
/*
3421
* send_comm: the generic command function. Uses the full command name found
3422
* in 'command', combines it with the 'args', and sends it to the server
3423
*/
3424
BUILT_IN_COMMAND(send_comm)
3425
{
3426
3427
if (args && *args)
3428
send_to_server("%s %s", command, args);
3429
else
3430
send_to_server("%s", command);
3431
}
3432
3433
BUILT_IN_COMMAND(do_trace)
3434
{
3435
char *flags = NULL, *serv = NULL;
3436
3437
set_server_trace_flag(from_server, 0);
3438
while (args && *args)
3439
{
3440
flags = next_arg(args, &args);
3441
if (flags && *flags=='-')
3442
{
3443
switch(toupper(*(flags+1)))
3444
{
3445
case 'O':
3446
set_server_trace_flag(from_server, get_server_trace_flag(from_server) | TRACE_OPER);
3447
break;
3448
case 'U':
3449
set_server_trace_flag(from_server, get_server_trace_flag(from_server) | TRACE_USER);
3450
break;
3451
case 'S':
3452
set_server_trace_flag(from_server, get_server_trace_flag(from_server) | TRACE_SERVER);
3453
default:
3454
break;
3455
}
3456
continue;
3457
}
3458
if (flags && *flags != '-')
3459
serv = flags;
3460
else
3461
serv = next_arg(args, &args);
3462
}
3463
if (get_server_trace_flag(from_server) & TRACE_OPER)
3464
bitchsay("Tracing server %s%sfor Operators", serv?serv:empty_string,serv?space:empty_string);
3465
if (get_server_trace_flag(from_server) & TRACE_USER)
3466
bitchsay("Tracing server %s%sfor Users", serv?serv:empty_string,serv?space:empty_string);
3467
if (get_server_trace_flag(from_server) & TRACE_SERVER)
3468
bitchsay("Tracing server %s%sfor servers", serv?serv:empty_string,serv?space:empty_string);
3469
send_to_server("%s%s%s", command, serv?space:empty_string, serv?serv:empty_string);
3470
}
3471
3472
BUILT_IN_COMMAND(do_stats)
3473
{
3474
char *flags = NULL, *serv = NULL;
3475
char *new_flag = empty_string;
3476
char *str = NULL;
3477
3478
set_server_stat_flag(from_server, 0);
3479
flags = next_arg(args, &args);
3480
if (flags)
3481
{
3482
switch(*flags)
3483
{
3484
case 'o':
3485
set_server_stat_flag(from_server, get_server_stat_flag(from_server) | STATS_OLINE);
3486
str = "%GType Host Nick";
3487
break;
3488
case 'y':
3489
set_server_stat_flag(from_server, get_server_stat_flag(from_server) | STATS_YLINE);
3490
str = "%GType Class PingF ConnF MaxLi SendQ";
3491
break;
3492
case 'i':
3493
set_server_stat_flag(from_server, get_server_stat_flag(from_server) | STATS_ILINE);
3494
str = "%GType Host Host Port Class";
3495
break;
3496
case 'h':
3497
set_server_stat_flag(from_server, get_server_stat_flag(from_server) | STATS_HLINE);
3498
str = "%GType Server Mask Server Name";
3499
break;
3500
case 'l':
3501
set_server_stat_flag(from_server, get_server_stat_flag(from_server) | STATS_LINK);
3502
str = "%Glinknick|server sendq smsgs sbytes rmsgs rbytes timeopen";
3503
break;
3504
case 'c':
3505
set_server_stat_flag(from_server, get_server_stat_flag(from_server) | STATS_CLASS);
3506
str = "%GType Host Host Port Class";
3507
break;
3508
case 'u':
3509
set_server_stat_flag(from_server, get_server_stat_flag(from_server) | STATS_UPTIME);
3510
break;
3511
case 'k':
3512
set_server_stat_flag(from_server, get_server_stat_flag(from_server) | STATS_TKLINE);
3513
str = "%GType Host UserName Reason";
3514
break;
3515
case 'K':
3516
set_server_stat_flag(from_server, get_server_stat_flag(from_server) | STATS_KLINE);
3517
str = "%GType Host UserName Reason";
3518
break;
3519
case 'm':
3520
set_server_stat_flag(from_server, get_server_stat_flag(from_server) | STATS_MLINE);
3521
default:
3522
break;
3523
}
3524
new_flag = flags;
3525
}
3526
if (args && *args)
3527
serv = args;
3528
else
3529
serv = get_server_itsname(from_server);
3530
if (str)
3531
put_it("%s", convert_output_format(str, NULL, NULL));
3532
send_to_server("%s %s %s", command, new_flag, serv);
3533
}
3534
3535
BUILT_IN_COMMAND(untopic)
3536
{
3537
char *channel = NULL;
3538
ChannelList *chan;
3539
int server;
3540
3541
args = sindex(args, "^ ");
3542
3543
if (is_channel(args))
3544
channel = next_arg(args, &args);
3545
3546
if (!(chan = prepare_command(&server, channel, PC_TOPIC)))
3547
return;
3548
3549
my_send_to_server(server, "TOPIC %s :", chan->channel);
3550
}
3551
3552
BUILT_IN_COMMAND(e_topic)
3553
{
3554
char *channel = NULL;
3555
ChannelList *chan;
3556
int server;
3557
3558
args = sindex(args, "^ ");
3559
3560
if (is_channel(args))
3561
{
3562
channel = next_arg(args, &args);
3563
args = sindex(args, "^ ");
3564
}
3565
3566
if (!(chan = prepare_command(&server, channel, args ? PC_TOPIC : NO_OP)))
3567
return;
3568
3569
if (args)
3570
{
3571
add_last_type(&last_sent_topic[0], 1, NULL, NULL, chan->channel, args);
3572
my_send_to_server(server, "TOPIC %s :%s", chan->channel, args);
3573
}
3574
else
3575
my_send_to_server(server, "TOPIC %s", chan->channel);
3576
}
3577
3578
/* MTOPIC by singe_ stolen from an idea by MHacker
3579
* the code is basically from below with a few mods,
3580
* and some added bloatcode(tm). Further modified by panasync
3581
*/
3582
BUILT_IN_COMMAND(do_mtopic)
3583
{
3584
ChannelList *chan;
3585
3586
if (from_server != -1)
3587
{
3588
int count = 0;
3589
for (chan = get_server_channels(from_server); chan; chan = chan->next)
3590
{
3591
if (!chan->have_op)
3592
continue;
3593
send_to_server("TOPIC %s :%s", chan->channel, args ? args : empty_string);
3594
count++;
3595
}
3596
if (!count)
3597
bitchsay("You're not an op on any channels");
3598
} else
3599
bitchsay("No server for this window");
3600
}
3601
3602
BUILT_IN_COMMAND(send_2comm)
3603
{
3604
char *reason = NULL;
3605
3606
3607
#ifdef CDE
3608
args = next_arg(args, &reason);
3609
if (!args)
3610
args = empty_string;
3611
#endif
3612
if (!(args = next_arg(args, &reason)))
3613
args = empty_string;
3614
if (!reason || !*reason)
3615
reason = empty_string;
3616
3617
if (!args || !*args || !strcmp(args, "*"))
3618
{
3619
args = get_current_channel_by_refnum(0);
3620
if (!args || !*args)
3621
args = "*"; /* what-EVER */
3622
}
3623
if (reason && *reason)
3624
send_to_server("%s %s :%s", command, args, reason);
3625
else
3626
send_to_server("%s %s", command, args);
3627
}
3628
3629
BUILT_IN_COMMAND(send_kill)
3630
{
3631
char *reason = NULL;
3632
char *r_file;
3633
char *nick;
3634
char *arg = NULL, *save_arg = NULL;
3635
3636
#if 0
3637
args = next_arg(args, &reason);
3638
if (!args)
3639
args = empty_string;
3640
#endif
3641
3642
#if defined(WINNT)
3643
r_file = m_sprintf("%s/BitchX.kil",get_string_var(CTOOLZ_DIR_VAR));
3644
#else
3645
r_file = m_sprintf("%s/BitchX.kill",get_string_var(CTOOLZ_DIR_VAR));
3646
#endif
3647
3648
if ((reason = strchr(args, ' ')) != NULL)
3649
*reason++ = '\0';
3650
else
3651
if ((reason = get_reason(args, r_file)))
3652
reason = empty_string;
3653
new_free(&r_file);
3654
3655
if (!strcmp(args, "*"))
3656
{
3657
ChannelList *chan = NULL;
3658
NickList *n = NULL;
3659
arg = get_current_channel_by_refnum(0);
3660
if (!arg || !*arg)
3661
return; /* what-EVER */
3662
else
3663
{
3664
if (!(chan = lookup_channel(arg, from_server, 0)))
3665
return;
3666
arg = NULL;
3667
for (n = next_nicklist(chan, NULL); n; n = next_nicklist(chan, n))
3668
{
3669
if (isme(n->nick)) continue;
3670
m_s3cat(&arg, ",", n->nick);
3671
}
3672
save_arg = arg;
3673
}
3674
}
3675
else
3676
{
3677
malloc_strcpy(&arg, args);
3678
save_arg = arg;
3679
}
3680
while ((nick = next_in_comma_list(arg, &arg)))
3681
{
3682
if (!nick || !*nick)
3683
break;
3684
if (reason && *reason)
3685
send_to_server("%s %s :%s", command, nick, reason);
3686
else
3687
send_to_server("%s %s", command, nick);
3688
}
3689
new_free(&save_arg);
3690
}
3691
3692
/*
3693
* send_kick: sends a kick message to the server. Works properly with
3694
* kick comments.
3695
*/
3696
3697
BUILT_IN_COMMAND(send_kick)
3698
{
3699
char *kickee,
3700
*comment,
3701
*channel = NULL;
3702
ChannelList *chan;
3703
int server = from_server;
3704
3705
3706
if (!(channel = next_arg(args, &args)))
3707
return;
3708
3709
if (!(kickee = next_arg(args, &args)))
3710
return;
3711
3712
comment = args?args:get_reason(kickee, NULL);
3713
3714
reset_display_target();
3715
if (!(chan = prepare_command(&server, (channel && !strcmp(channel, "*"))?NULL:channel, NEED_OP)))
3716
return;
3717
3718
my_send_to_server(server, "%s %s %s :%s", command, chan->channel, kickee, comment);
3719
}
3720
3721
BUILT_IN_COMMAND(send_mode)
3722
{
3723
char *channel;
3724
3725
if ((channel = get_current_channel_by_refnum(0)))
3726
send_to_server("%s %s %s", command, channel, args? args: empty_string);
3727
else if (args && *args)
3728
send_to_server("%s %s", command, args);
3729
}
3730
3731
/*
3732
* send_channel_com: does the same as send_com for command where the first
3733
* argument is a channel name. If the first argument is *, it is expanded
3734
* to the current channel (a la /WHO).
3735
*/
3736
BUILT_IN_COMMAND(send_channel_com)
3737
{
3738
char *ptr,
3739
*s;
3740
3741
ptr = next_arg(args, &args);
3742
3743
if (ptr && !strcmp(ptr, "*"))
3744
{
3745
if ((s = get_current_channel_by_refnum(0)) != NULL)
3746
send_to_server("%s %s %s", command, s, args?args:empty_string);
3747
else
3748
say("%s * is not valid since you are not on a channel", command);
3749
}
3750
else if (ptr)
3751
send_to_server("%s %s %s", command, ptr, args?args:empty_string);
3752
}
3753
3754
/*
3755
* Returns 1 if the given built in command exists,
3756
* Returns 0 if not.
3757
*/
3758
int command_exist (char *command)
3759
{
3760
int num;
3761
char buf[BIG_BUFFER_SIZE];
3762
3763
if (!command || !*command)
3764
return 0;
3765
3766
strcpy(buf, command);
3767
upper(buf);
3768
3769
if (find_command(buf, &num))
3770
return (num < 0) ? 1 : 0;
3771
3772
return 0;
3773
}
3774
3775
void redirect_text (int to_server, const char *nick_list, const char *text, char *command, int hook, int log)
3776
{
3777
static int recursion = 0;
3778
int old_from_server = from_server;
3779
int allow = 0;
3780
3781
from_server = to_server;
3782
if (recursion++ == 0)
3783
allow = do_hook(REDIRECT_LIST, "%s %s", nick_list, text);
3784
3785
/*
3786
* Dont hook /ON REDIRECT if we're being called recursively
3787
*/
3788
if (allow)
3789
send_text(nick_list, text, command, hook, log);
3790
3791
recursion--;
3792
from_server = old_from_server;
3793
}
3794
3795
3796
3797
3798
struct target_type
3799
{
3800
char *nick_list;
3801
char *message;
3802
int hook_type;
3803
char *command;
3804
char *format;
3805
unsigned long level;
3806
char *output;
3807
char *other_output;
3808
};
3809
3810
int current_target = 0;
3811
3812
/*
3813
* The whole shebang.
3814
*
3815
* The message targets are parsed and collected into one of 4 buckets.
3816
* This is not too dissimilar to what was done before, except now i
3817
* feel more comfortable about how the code works.
3818
*
3819
* Bucket 0 -- Unencrypted PRIVMSGs to nicknames
3820
* Bucket 1 -- Unencrypted PRIVMSGs to channels
3821
* Bucket 2 -- Unencrypted NOTICEs to nicknames
3822
* Bucket 3 -- Unencrypted NOTICEs to channels
3823
*
3824
* All other messages (encrypted, and DCC CHATs) are dispatched
3825
* immediately, and seperately from all others. All messages that
3826
* end up in one of the above mentioned buckets get sent out all
3827
* at once.
3828
*/
3829
void BX_send_text(const char *nick_list, const char *text, char *command, int hook, int log)
3830
{
3831
int i,
3832
old_server,
3833
not_done = 1,
3834
is_current = 0,
3835
old_window_display = window_display;
3836
char *current_nick,
3837
*next_nick,
3838
*free_nick,
3839
*line,
3840
*key = NULL;
3841
static int sent_text_recursion = 0;
3842
3843
struct target_type target[4] =
3844
{
3845
{NULL, NULL, SEND_MSG_LIST, "PRIVMSG", "*%s*> %s" , LOG_MSG, NULL, NULL },
3846
{NULL, NULL, SEND_PUBLIC_LIST, "PRIVMSG", "%s> %s" , LOG_PUBLIC, NULL, NULL },
3847
{NULL, NULL, SEND_NOTICE_LIST, "NOTICE", "-%s-> %s" , LOG_NOTICE, NULL, NULL },
3848
{NULL, NULL, SEND_NOTICE_LIST, "NOTICE", "-%s-> %s" , LOG_NOTICE, NULL, NULL }
3849
};
3850
3851
3852
3853
target[0].output = fget_string_var(FORMAT_SEND_MSG_FSET);
3854
target[1].output = fget_string_var(FORMAT_SEND_PUBLIC_FSET);
3855
target[1].other_output = fget_string_var(FORMAT_SEND_PUBLIC_OTHER_FSET);
3856
target[2].output = fget_string_var(FORMAT_SEND_NOTICE_FSET);
3857
target[3].output = fget_string_var(FORMAT_SEND_NOTICE_FSET);
3858
target[3].other_output = fget_string_var(FORMAT_SEND_NOTICE_FSET);
3859
3860
if (sent_text_recursion)
3861
hook = 0;
3862
window_display = hook;
3863
sent_text_recursion++;
3864
free_nick = next_nick = m_strdup(nick_list);
3865
3866
while ((current_nick = next_nick))
3867
{
3868
if ((next_nick = strchr(current_nick, ',')))
3869
*next_nick++ = 0;
3870
3871
if (!*current_nick)
3872
continue;
3873
3874
if (*current_nick == '%')
3875
{
3876
if ((i = get_process_index(&current_nick)) == -1)
3877
say("Invalid process specification");
3878
else
3879
text_to_process(i, text, 1);
3880
}
3881
/*
3882
* This test has to be here because it is legal to
3883
* send an empty line to a process, but not legal
3884
* to send an empty line anywhere else.
3885
*/
3886
else if (!text || !*text)
3887
;
3888
#ifdef WANT_FTP
3889
else if (*current_nick == '-')
3890
dcc_ftpcommand(current_nick+1, (char *)text);
3891
#endif
3892
else if (*current_nick == '"')
3893
send_to_server("%s", text);
3894
else if (*current_nick == '/')
3895
{
3896
line = m_opendup(current_nick, space, text, NULL);
3897
parse_command(line, 0, empty_string);
3898
new_free(&line);
3899
}
3900
else if (*current_nick == '=')
3901
{
3902
if (!is_number(current_nick + 1) &&
3903
!dcc_activechat(current_nick + 1) &&
3904
!dcc_activebot(current_nick+1) &&
3905
!dcc_activeraw(current_nick+1))
3906
{
3907
yell("No DCC CHAT connection open to %s", current_nick + 1);
3908
continue;
3909
}
3910
if ((key = is_crypted(current_nick)))
3911
{
3912
char *breakage;
3913
breakage = LOCAL_COPY(text);
3914
line = crypt_msg(breakage, key);
3915
}
3916
else
3917
line = m_strdup(text);
3918
3919
old_server = from_server;
3920
from_server = -1;
3921
if (dcc_activechat(current_nick+1))
3922
{
3923
dcc_chat_transmit(current_nick + 1, line, line, command, hook);
3924
if (hook)
3925
addtabkey(current_nick, "msg", 0);
3926
}
3927
else if (dcc_activebot(current_nick + 1))
3928
dcc_bot_transmit(current_nick + 1, line, command);
3929
else
3930
dcc_raw_transmit(current_nick + 1, line, command);
3931
3932
add_last_type(&last_sent_dcc[0], MAX_LAST_MSG, NULL, NULL, current_nick+1, (char *)text);
3933
from_server = old_server;
3934
new_free(&line);
3935
}
3936
else
3937
{
3938
char *copy = NULL;
3939
if (doing_notice)
3940
{
3941
say("You cannot send a message from within ON NOTICE");
3942
continue;
3943
}
3944
3945
copy = LOCAL_COPY(text);
3946
3947
if (!(i = is_channel(current_nick)) && hook)
3948
addtabkey(current_nick, "msg", 0);
3949
3950
if (doing_notice || (command && !strcmp(command, "NOTICE")))
3951
i += 2;
3952
3953
if ((key = is_crypted(current_nick)))
3954
{
3955
set_display_target(current_nick, target[i].level);
3956
3957
line = crypt_msg(copy, key);
3958
if (hook && do_hook(target[i].hook_type, "%s %s", current_nick, copy))
3959
put_it("%s", convert_output_format(fget_string_var(target[i].hook_type == SEND_MSG_LIST?FORMAT_SEND_ENCRYPTED_MSG_FSET:FORMAT_SEND_ENCRYPTED_NOTICE_FSET),
3960
"%s %s %s %s",update_clock(GET_TIME), get_server_nickname(from_server),current_nick, text));
3961
3962
send_to_server("%s %s :%s", target[i].command, current_nick, line);
3963
new_free(&line);
3964
reset_display_target();
3965
}
3966
else
3967
{
3968
if (target[i].nick_list)
3969
malloc_strcat(&target[i].nick_list, ",");
3970
malloc_strcat(&target[i].nick_list, current_nick);
3971
if (!target[i].message)
3972
target[i].message = (char *)text;
3973
}
3974
}
3975
}
3976
3977
for (i = 0; i < 4; i++)
3978
{
3979
char *copy = NULL;
3980
char *s = NULL;
3981
ChannelList *chan = NULL;
3982
const char *old_mf;
3983
unsigned long old_ml;
3984
int blah_hook = 0;
3985
3986
if (!target[i].message)
3987
continue;
3988
3989
save_display_target(&old_mf, &old_ml);
3990
set_display_target(target[i].nick_list, target[i].level);
3991
copy = m_strdup(target[i].message);
3992
3993
/* do we forward this?*/
3994
3995
if (forwardnick && not_done)
3996
{
3997
send_to_server("NOTICE %s :-> *%s* %s", forwardnick, nick_list, copy);
3998
not_done = 0;
3999
}
4000
4001
/* log it if logging on */
4002
if (log)
4003
logmsg(LOG_SEND_MSG, target[i].nick_list, 0, "%s", copy);
4004
/* save this for /oops */
4005
4006
if (i == 1 || i == 3)
4007
{
4008
char *channel;
4009
is_current = is_current_channel(target[i].nick_list, from_server, 0);
4010
if ((channel = get_current_channel_by_refnum(0)))
4011
{
4012
NickList *nick = NULL;
4013
if ((chan = lookup_channel(channel, from_server, 0)))
4014
{
4015
nick = find_nicklist_in_channellist(get_server_nickname(from_server), chan, 0);
4016
update_stats((i == 1) ?PUBLIC_LIST : NOTICE_LIST, nick, chan, 0);
4017
}
4018
}
4019
}
4020
else
4021
is_current = 1;
4022
4023
if (hook && (blah_hook = do_hook(target[i].hook_type, "%s %s", target[i].nick_list, copy)))
4024
;
4025
/* supposedly if this is called before the do_hook
4026
* it can cause a problem with scripts.
4027
*/
4028
4029
if (blah_hook || chan)
4030
s = convert_output_format(is_current ? target[i].output : target[i].other_output,
4031
"%s %s %s %s",update_clock(GET_TIME), target[i].nick_list, get_server_nickname(from_server), copy);
4032
if (blah_hook)
4033
put_it("%s", s);
4034
4035
if (chan)
4036
add_to_log(chan->msglog_fp, now, s, logfile_line_mangler);
4037
4038
if ((i == 0))
4039
{
4040
set_server_sent_nick(from_server, target[0].nick_list);
4041
set_server_sent_body(from_server, copy);
4042
add_last_type(&last_sent_msg[0], MAX_LAST_MSG, NULL, NULL, target[i].nick_list, copy);
4043
}
4044
else if ((i == 2) || (i == 3))
4045
add_last_type(&last_sent_notice[0], MAX_LAST_MSG, target[i].nick_list, NULL, get_server_nickname(from_server), copy);
4046
4047
send_to_server("%s %s :%s", target[i].command, target[i].nick_list, copy);
4048
new_free(&copy);
4049
new_free(&target[i].nick_list);
4050
target[i].message = NULL;
4051
restore_display_target(old_mf, old_ml);
4052
}
4053
4054
if (hook && get_server_away(from_server) && get_int_var(AUTO_UNMARK_AWAY_VAR))
4055
parse_line(NULL, "AWAY", empty_string, 0, 0, 1);
4056
4057
new_free(&free_nick);
4058
window_display = old_window_display;
4059
sent_text_recursion--;
4060
}
4061
4062
BUILT_IN_COMMAND(do_send_text)
4063
{
4064
char *tmp;
4065
char *text = args;
4066
char *cmd = NULL;
4067
4068
if (command)
4069
tmp = get_current_channel_by_refnum(0);
4070
else
4071
{
4072
tmp = get_target_by_refnum(0);
4073
cmd = get_target_cmd_by_refnum(0);
4074
}
4075
if (cmd)
4076
{
4077
#ifdef WANT_DLL
4078
int dllcnt = -1;
4079
IrcCommandDll *dll = NULL;
4080
dll = find_dll_command(cmd, &dllcnt);
4081
if (dll && (dllcnt == -1 || dllcnt == 1))
4082
dll->func (dll_commands, dll->server_func, text, NULL, dll->help);
4083
else
4084
#endif
4085
if (!my_stricmp(cmd, "SAY") || !my_stricmp(cmd, "PRIVMSG") || !my_stricmp(cmd, "MSG"))
4086
send_text(tmp, text, NULL, 1, 1);
4087
else if (!my_stricmp(cmd, "NOTICE"))
4088
send_text(tmp, text, "NOTICE", 1, 1);
4089
else if (!my_strnicmp(cmd, "WALLO", 5))
4090
e_wall("WALLOPS", text, NULL, NULL);
4091
else if (!my_strnicmp(cmd, "SWALLO", 6))
4092
e_wall("SWALLOPS", text, NULL, NULL);
4093
else if(!my_strnicmp(cmd, "WALLC", 5))
4094
ChanWallOp(NULL, text, NULL, NULL);
4095
#ifndef BITCHX_LITE
4096
else if (!my_stricmp(cmd, "CSAY"))
4097
csay(NULL, text, NULL, NULL);
4098
else if (!my_stricmp(cmd, "CMSG"))
4099
cmsg(NULL, text, NULL, NULL);
4100
#endif
4101
else
4102
send_text(tmp, text, NULL, 1, 1);
4103
}
4104
else
4105
send_text(tmp, text, NULL, 1, 1);
4106
}
4107
4108
BUILT_IN_COMMAND(do_msay)
4109
{
4110
char *channels = NULL;
4111
int i = get_window_server(0);
4112
ChannelList *chan;
4113
4114
if (i != -1)
4115
{
4116
int old_from_server = from_server;
4117
for (chan = get_server_channels(i); chan; chan = chan->next)
4118
{
4119
malloc_strcat(&channels, chan->channel);
4120
if (chan->next)
4121
malloc_strcat(&channels, ",");
4122
}
4123
from_server = i;
4124
if (channels)
4125
send_text(channels, args, NULL, 1, 1);
4126
new_free(&channels);
4127
from_server = old_from_server;
4128
} else
4129
bitchsay("No server for this window");
4130
}
4131
4132
/*
4133
* command_completion: builds lists of commands and aliases that match the
4134
* given command and displays them for the user's lookseeing
4135
*/
4136
char **get_builtins (char *, int *);
4137
void command_completion(char unused, char *not_used)
4138
{
4139
int do_aliases = 1,
4140
do_functions = 1;
4141
int cmd_cnt = 0,
4142
alias_cnt = 0,
4143
dll_cnt = 0,
4144
function_cnt = 0,
4145
i,
4146
c;
4147
char **aliases = NULL;
4148
char **functions = NULL;
4149
4150
char *line = NULL,
4151
*com,
4152
*cmdchars,
4153
*rest,
4154
firstcmdchar[2] = "/";
4155
IrcCommand *command;
4156
#ifdef WANT_DLL
4157
IrcCommandDll *dll = NULL;
4158
#endif
4159
char buffer[BIG_BUFFER_SIZE + 1];
4160
4161
4162
malloc_strcpy(&line, get_input());
4163
if ((com = next_arg(line, &rest)) != NULL)
4164
{
4165
if (!(cmdchars = get_string_var(CMDCHARS_VAR)))
4166
cmdchars = DEFAULT_CMDCHARS;
4167
if (*com == '/' || strchr(cmdchars, *com))
4168
{
4169
*firstcmdchar = *cmdchars;
4170
com++;
4171
if (*com && strchr(cmdchars, *com))
4172
{
4173
do_aliases = 0;
4174
do_functions = 0;
4175
alias_cnt = 0;
4176
function_cnt = 0;
4177
com++;
4178
}
4179
else if (*com && strchr("$", *com))
4180
{
4181
do_aliases = 0;
4182
alias_cnt = 0;
4183
do_functions = 1;
4184
com++;
4185
} else
4186
do_aliases = do_functions = 1;
4187
4188
upper(com);
4189
if (do_aliases)
4190
aliases = glob_cmd_alias(com, &alias_cnt);
4191
4192
if (do_functions)
4193
functions = get_builtins(com, &function_cnt);
4194
4195
if ((command = find_command(com, &cmd_cnt)) != NULL)
4196
{
4197
if (cmd_cnt < 0)
4198
cmd_cnt *= -1;
4199
/* special case for the empty string */
4200
if (!*command->name)
4201
{
4202
command++;
4203
cmd_cnt = NUMBER_OF_COMMANDS;
4204
}
4205
}
4206
#ifdef WANT_DLL
4207
if ((dll = find_dll_command(com, &dll_cnt)) != NULL)
4208
{
4209
if (dll_cnt < 0)
4210
dll_cnt *= -1;
4211
}
4212
#endif
4213
if ((alias_cnt == 1) && (cmd_cnt == 0) && (dll_cnt <= 0))
4214
{
4215
snprintf(buffer, BIG_BUFFER_SIZE, "%s%s %s", firstcmdchar, *aliases, rest);
4216
set_input(buffer);
4217
new_free((char **)aliases);
4218
new_free((char **)&aliases);
4219
update_input(UPDATE_ALL);
4220
}
4221
else if (((cmd_cnt == 1) && (dll_cnt <= 0) && (alias_cnt == 0)) ||
4222
((cmd_cnt == 0) && (dll_cnt == 1) && (alias_cnt == 0)) ||
4223
(((cmd_cnt == 1) && (alias_cnt == 1) &&
4224
!strcmp(aliases[0], command[0].name))
4225
#ifdef WANT_DLL
4226
|| ((dll_cnt == 1) && (alias_cnt == 1) && !strcmp(dll->name, aliases[0]))
4227
#endif
4228
))
4229
{
4230
snprintf(buffer, BIG_BUFFER_SIZE, "%s%s%s %s",
4231
firstcmdchar,
4232
do_aliases ? empty_string : firstcmdchar,
4233
#ifdef WANT_DLL
4234
cmd_cnt ? command[0].name : dll->name,
4235
#else
4236
command[0].name,
4237
#endif
4238
rest);
4239
set_input(buffer);
4240
update_input(UPDATE_ALL);
4241
}
4242
else
4243
{
4244
*buffer = 0;
4245
if (command)
4246
{
4247
*buffer = 0;
4248
c = 0;
4249
for (i = 0; i < cmd_cnt; i++)
4250
{
4251
if (i == 0)
4252
bitchsay("Commands:");
4253
strmcat(buffer, command[i].name, BIG_BUFFER_SIZE);
4254
strmcat(buffer, space, BIG_BUFFER_SIZE);
4255
if (++c == 4)
4256
{
4257
put_it("%s", convert_output_format("$G $[15]0 $[15]1 $[15]2 $[15]3", "%s", buffer));
4258
*buffer = 0;
4259
c = 0;
4260
}
4261
}
4262
if (c)
4263
put_it("%s", convert_output_format("$G $[15]0 $[15]1 $[15]2 $[15]3", "%s", buffer));
4264
#ifdef WANT_DLL
4265
if (dll_commands)
4266
bitchsay("Plugin Commands:");
4267
*buffer = 0;
4268
c = 0;
4269
for (dll = dll_commands; dll; dll = dll->next)
4270
{
4271
if (com && *com && my_strnicmp(com, dll->name, strlen(com)))
4272
continue;
4273
strmcat(buffer, dll->name, BIG_BUFFER_SIZE);
4274
strmcat(buffer, space, BIG_BUFFER_SIZE);
4275
if (++c == 4)
4276
{
4277
put_it("%s", convert_output_format("$G $[15]0 $[15]1 $[15]2 $[15]3", "%s", buffer));
4278
*buffer = 0;
4279
c = 0;
4280
}
4281
}
4282
if (c)
4283
put_it("%s", convert_output_format("$G $[15]0 $[15]1 $[15]2 $[15]3", "%s", buffer));
4284
#endif
4285
}
4286
if (aliases)
4287
{
4288
*buffer = 0;
4289
c = 0;
4290
for (i = 0; i < alias_cnt; i++)
4291
{
4292
if (i == 0)
4293
bitchsay("Aliases:");
4294
strmcat(buffer, aliases[i], BIG_BUFFER_SIZE);
4295
strmcat(buffer, space, BIG_BUFFER_SIZE);
4296
if (++c == 4)
4297
{
4298
put_it("%s", convert_output_format("$G $[15]0 $[15]1 $[15]2 $[15]3", "%s", buffer));
4299
*buffer = 0;
4300
c = 0;
4301
}
4302
new_free(&(aliases[i]));
4303
}
4304
if (strlen(buffer) > 1)
4305
put_it("%s", convert_output_format("$G $[15]0 $[15]1 $[15]2 $[15]3", "%s", buffer));
4306
new_free((char **)&aliases);
4307
}
4308
if (functions)
4309
{
4310
*buffer = 0;
4311
c = 0;
4312
for (i = 0; i < function_cnt; i++)
4313
{
4314
if (i == 0)
4315
bitchsay("Functions:");
4316
strmcat(buffer, functions[i], BIG_BUFFER_SIZE);
4317
strmcat(buffer, space, BIG_BUFFER_SIZE);
4318
if (++c == 4)
4319
{
4320
put_it("%s", convert_output_format("$G $[15]0 $[15]1 $[15]2 $[15]3", "%s", buffer));
4321
*buffer = 0;
4322
c = 0;
4323
}
4324
new_free(&(functions[i]));
4325
}
4326
if (strlen(buffer) > 1)
4327
put_it("%s", convert_output_format("$G $[15]0 $[15]1 $[15]2 $[15]3", "%s", buffer));
4328
new_free((char **)&functions);
4329
}
4330
if (!*buffer)
4331
term_beep();
4332
}
4333
}
4334
else
4335
term_beep();
4336
}
4337
else
4338
term_beep();
4339
new_free(&line);
4340
}
4341
4342
4343
BUILT_IN_COMMAND(e_call)
4344
{
4345
dump_call_stack();
4346
}
4347
4348
static int oper_issued = 0;
4349
4350
/* parse_line: This is the main parsing routine. It should be called in
4351
* almost all circumstances over parse_command().
4352
*
4353
* parse_line breaks up the line into commands separated by unescaped
4354
* semicolons if we are in non interactive mode. Otherwise it tries to leave
4355
* the line untouched.
4356
*
4357
* Currently, a carriage return or newline breaks the line into multiple
4358
* commands too. This is expected to stop at some point when parse_command
4359
* will check for such things and escape them using the ^P convention.
4360
* We'll also try to check before we get to this stage and escape them before
4361
* they become a problem.
4362
*
4363
* Other than these two conventions the line is left basically untouched.
4364
*/
4365
/* Ideas on parsing: Why should the calling function be responsible
4366
* for removing {} blocks? Why cant this parser cope with and {}s
4367
* that come up?
4368
*/
4369
void BX_parse_line (const char *name, char *org_line, const char *args, int hist_flag, int append_flag, int handle_local)
4370
{
4371
char *line = NULL,
4372
*stuff,
4373
*s,
4374
*t;
4375
int args_flag = 0,
4376
die = 0;
4377
4378
4379
4380
if (handle_local)
4381
make_local_stack((char *)name);
4382
4383
line = LOCAL_COPY(org_line);
4384
4385
if (!*org_line)
4386
do_send_text(NULL, empty_string, empty_string, NULL);
4387
else if (args) do
4388
{
4389
while (*line == '{')
4390
{
4391
if (!(stuff = next_expr(&line, '{')))
4392
{
4393
error("Unmatched {");
4394
destroy_local_stack();
4395
return;
4396
}
4397
if (((internal_debug & DEBUG_CMDALIAS) || (internal_debug & DEBUG_HOOK)) && alias_debug && !in_debug_yell)
4398
debugyell("%3d %s", debug_count++, stuff);
4399
parse_line(name, stuff, args, hist_flag, append_flag, handle_local);
4400
4401
if ((will_catch_break_exceptions && break_exception) ||
4402
(will_catch_return_exceptions && return_exception) ||
4403
(will_catch_continue_exceptions && continue_exception))
4404
{
4405
die = 1;
4406
break;
4407
}
4408
4409
while (line && *line && ((*line == ';') || (my_isspace(*line))))
4410
*line++ = '\0';
4411
}
4412
4413
if (!line || !*line || die)
4414
break;
4415
4416
stuff = expand_alias(line, args, &args_flag, &line);
4417
if (!line && append_flag && !args_flag && args && *args)
4418
m_3cat(&stuff, space, args);
4419
4420
if (((internal_debug & DEBUG_CMDALIAS) || (internal_debug & DEBUG_HOOK)) && alias_debug && !in_debug_yell)
4421
debugyell("%3d %s", debug_count++, stuff);
4422
4423
parse_command(stuff, hist_flag, (char *)args);
4424
new_free(&stuff);
4425
4426
if ((will_catch_break_exceptions && break_exception) ||
4427
(will_catch_return_exceptions && return_exception) ||
4428
(will_catch_continue_exceptions && continue_exception))
4429
break;
4430
} while (line && *line);
4431
else
4432
{
4433
if (load_depth != -1) /* CDE should this be != 1 or > 0 */
4434
parse_command(line, hist_flag, (char *)args);
4435
else
4436
{
4437
while ((s = line))
4438
{
4439
if ((t = sindex(line, "\r\n")))
4440
{
4441
*t++ = '\0';
4442
line = t;
4443
}
4444
else
4445
line = NULL;
4446
parse_command(s, hist_flag, (char *)args);
4447
4448
if ((will_catch_break_exceptions && break_exception) ||
4449
(will_catch_return_exceptions && return_exception) ||
4450
(will_catch_continue_exceptions && continue_exception))
4451
break;
4452
4453
}
4454
}
4455
debug_count = 1;
4456
}
4457
if (oper_issued)
4458
{
4459
memset(org_line, 0, strlen(org_line));
4460
oper_issued = 0;
4461
}
4462
if (handle_local)
4463
destroy_local_stack();
4464
return;
4465
}
4466
4467
4468
/*
4469
* parse_command: parses a line of input from the user. If the first
4470
* character of the line is equal to irc_variable[CMDCHAR_VAR].value, the
4471
* line is used as an irc command and parsed appropriately. If the first
4472
* character is anything else, the line is sent to the current channel or to
4473
* the current query user. If hist_flag is true, commands will be added to
4474
* the command history as appropriate. Otherwise, parsed commands will not
4475
* be added.
4476
*
4477
* Parse_command() only parses a single command. In general, you will want
4478
* to use parse_line() to execute things.Parse command recognized no quoted
4479
* characters or anything (beyond those specific for a given command being
4480
* executed).
4481
*/
4482
int BX_parse_command(register char *line, int hist_flag, char *sub_args)
4483
{
4484
static unsigned int level = 0;
4485
unsigned int display,
4486
old_display_var;
4487
char *cmdchars;
4488
const char *com;
4489
char *this_cmd = NULL;
4490
int args_flag = 0,
4491
add_to_hist,
4492
cmdchar_used = 0;
4493
int noisy = 1;
4494
4495
int old_alias_debug = alias_debug;
4496
4497
if (!line || !*line)
4498
return 0;
4499
4500
if (internal_debug & DEBUG_COMMANDS && !in_debug_yell)
4501
debugyell("Executing [%d] %s", level, line);
4502
level++;
4503
4504
if (!(cmdchars = get_string_var(CMDCHARS_VAR)))
4505
cmdchars = DEFAULT_CMDCHARS;
4506
4507
4508
this_cmd = LOCAL_COPY(line);
4509
set_current_command(this_cmd);
4510
add_to_hist = 1;
4511
display = window_display;
4512
old_display_var = (unsigned) get_int_var(DISPLAY_VAR);
4513
for ( ;*line;line++)
4514
{
4515
if (*line == '^' && (!hist_flag || cmdchar_used))
4516
{
4517
if (!noisy)
4518
break;
4519
noisy = 0;
4520
}
4521
else if ((!hist_flag && *line == '/') || strchr(cmdchars, *line))
4522
{
4523
cmdchar_used++;
4524
if (cmdchar_used > 2)
4525
break;
4526
}
4527
else
4528
break;
4529
}
4530
4531
if (!noisy)
4532
window_display = 0;
4533
com = line;
4534
4535
/*
4536
* always consider input a command unless we are in interactive mode
4537
* and command_mode is off. -lynx
4538
*/
4539
if (hist_flag && !cmdchar_used && !get_int_var(COMMAND_MODE_VAR))
4540
{
4541
do_send_text(NULL, line, empty_string, NULL);
4542
if (hist_flag && add_to_hist)
4543
add_to_history(this_cmd);
4544
/* Special handling for ' and : */
4545
}
4546
else if (*com == '\'' && get_int_var(COMMAND_MODE_VAR))
4547
{
4548
do_send_text(NULL, line+1, empty_string, NULL);
4549
if (hist_flag && add_to_hist)
4550
add_to_history(this_cmd);
4551
}
4552
else if ((*com == '@') || (*com == '('))
4553
{
4554
/* This kludge fixes a memory leak */
4555
char *tmp;
4556
char *my_line = LOCAL_COPY(line);
4557
char *l_ptr;
4558
/*
4559
* This new "feature" masks a weakness in the underlying
4560
* grammar that allowed variable names to begin with an
4561
* lparen, which inhibited the expansion of $s inside its
4562
* name, which caused icky messes with array subscripts.
4563
*
4564
* Anyhow, we now define any commands that start with an
4565
* lparen as being "expressions", same as @ lines.
4566
*/
4567
if (*com == '(')
4568
{
4569
if ((l_ptr = MatchingBracket(my_line + 1, '(', ')')))
4570
*l_ptr++ = 0;
4571
}
4572
4573
if ((tmp = parse_inline(my_line + 1, sub_args, &args_flag)))
4574
new_free(&tmp);
4575
4576
if (hist_flag && add_to_hist)
4577
add_to_history(this_cmd);
4578
}
4579
else
4580
{
4581
char *rest,
4582
*alias = NULL,
4583
*alias_name = NULL,
4584
*cline = NULL;
4585
IrcCommand *command = NULL;
4586
void *arglist = NULL;
4587
int cmd_cnt,
4588
alias_cnt = 0;
4589
#ifdef WANT_DLL
4590
int dll_cnt;
4591
IrcCommandDll *dll = NULL;
4592
#endif
4593
4594
if ((rest = strchr(line, ' ')))
4595
{
4596
cline = alloca((rest - line) + 1);
4597
strmcpy(cline, line, (rest - line));
4598
rest++;
4599
}
4600
else
4601
{
4602
cline = LOCAL_COPY(line);
4603
rest = empty_string;
4604
}
4605
4606
upper(cline);
4607
if (cline && !strcmp(cline, "OPER"))
4608
oper_issued++;
4609
4610
if (cmdchar_used < 2)
4611
alias = get_cmd_alias(cline, &alias_cnt, &alias_name, &arglist);
4612
4613
if (alias && alias_cnt < 0)
4614
{
4615
if (hist_flag && add_to_hist && !oper_issued)
4616
add_to_history(this_cmd);
4617
call_user_alias(alias_name, alias, rest, arglist);
4618
new_free(&alias_name);
4619
}
4620
else
4621
{
4622
/* History */
4623
if (*cline == '!')
4624
{
4625
if ((cline = do_history(cline + 1, rest)) != NULL)
4626
{
4627
if (level == 1)
4628
{
4629
set_input(cline);
4630
update_input(UPDATE_ALL);
4631
}
4632
else
4633
parse_command(cline, 0, sub_args);
4634
new_free(&cline);
4635
}
4636
else
4637
set_input(empty_string);
4638
}
4639
else
4640
{
4641
char unknown[] = "Unknown command:";
4642
4643
if (hist_flag && add_to_hist && !oper_issued)
4644
add_to_history(this_cmd);
4645
command = find_command(cline, &cmd_cnt);
4646
#ifdef WANT_DLL
4647
dll = find_dll_command(cline, &dll_cnt);
4648
if ((dll && (dll_cnt < 0)) || ((alias_cnt == 0) && (dll_cnt == 1)))
4649
{
4650
4651
strcpy(cx_function, dll->name);
4652
if (rest && *rest && !my_stricmp(rest, "-help") && dll->help)
4653
userage(cline, dll->help);
4654
else if (dll->func)
4655
{
4656
dll->func(dll_commands, dll->server_func, rest, sub_args, dll->help);
4657
if (dll->result)
4658
put_it("%s", dll->result);
4659
}
4660
else
4661
bitchsay("%s: command disabled", dll->name);
4662
*cx_function = 0;
4663
}
4664
else
4665
#endif
4666
if (cmd_cnt < 0 || (alias_cnt == 0 && cmd_cnt == 1))
4667
{
4668
if (rest && *rest && !my_stricmp(rest, "-help"))
4669
{
4670
if (command->help)
4671
userage(cline, command->help);
4672
#ifdef WANT_CHELP
4673
else
4674
chelp(NULL, cline, NULL, NULL);
4675
#endif
4676
} else if ((command->flags & SERVERREQ) && (connected_to_server == 0))
4677
bitchsay("%s: You are not connected to a server. Use /SERVER to connect.", com);
4678
else if (command->func)
4679
command->func(command->server_func, rest, sub_args, command->help);
4680
else
4681
bitchsay("%s: command disabled", command->name);
4682
}
4683
else if ((alias_cnt == 1 && cmd_cnt == 1 && (!strcmp(alias_name, command->name))) ||
4684
(alias_cnt == 1 && cmd_cnt == 0))
4685
{
4686
will_catch_return_exceptions++;
4687
parse_line(alias_name, alias, rest, 0, 1, 1);
4688
will_catch_return_exceptions--;
4689
return_exception = 0;
4690
}
4691
else if (!my_stricmp(com, get_server_nickname(from_server)))
4692
me(NULL, rest, empty_string, NULL);
4693
#ifdef WANT_TCL
4694
else
4695
{
4696
4697
if (tcl_interp)
4698
{
4699
int err;
4700
err = Tcl_Invoke(tcl_interp, cline, rest);
4701
if (err == TCL_OK)
4702
{
4703
if (tcl_interp->result && *tcl_interp->result)
4704
bitchsay("%s %s", *tcl_interp->result?empty_string:unknown, *tcl_interp->result?tcl_interp->result:empty_string);
4705
}
4706
else
4707
{
4708
if (alias_cnt + cmd_cnt > 1)
4709
bitchsay("Ambiguous command: %s", cline);
4710
else if (get_int_var(DISPATCH_UNKNOWN_COMMANDS_VAR))
4711
send_to_server("%s %s", cline, rest);
4712
else if (tcl_interp->result && *tcl_interp->result)
4713
{
4714
if (check_help_bind(cline))
4715
bitchsay("%s", tcl_interp->result);
4716
}
4717
else
4718
bitchsay("%s %s", unknown, cline);
4719
4720
}
4721
} else if (get_int_var(DISPATCH_UNKNOWN_COMMANDS_VAR))
4722
send_to_server("%s %s", cline, rest);
4723
else if (alias_cnt + cmd_cnt > 1)
4724
bitchsay("Ambiguous command: %s", cline);
4725
else
4726
bitchsay("%s %s", unknown, cline);
4727
}
4728
#else
4729
else if (get_int_var(DISPATCH_UNKNOWN_COMMANDS_VAR))
4730
send_to_server("%s %s", cline, rest);
4731
else if (alias_cnt + cmd_cnt > 1)
4732
bitchsay("Ambiguous command: %s", cline);
4733
else
4734
bitchsay("%s %s", unknown, cline);
4735
#endif
4736
}
4737
if (alias)
4738
new_free(&alias_name);
4739
}
4740
}
4741
4742
if (oper_issued)
4743
memset(this_cmd, 0, strlen(this_cmd));
4744
4745
if (old_display_var != get_int_var(DISPLAY_VAR))
4746
window_display = get_int_var(DISPLAY_VAR);
4747
else
4748
window_display = display;
4749
level--;
4750
unset_current_command();
4751
alias_debug = old_alias_debug;
4752
return 0;
4753
}
4754
4755
4756
struct load_info
4757
{
4758
char *filename;
4759
int line;
4760
int start_line;
4761
} load_level[MAX_LOAD_DEPTH] = {{ NULL, 0 }};
4762
4763
void dump_load_stack (int onelevel)
4764
{
4765
int i = load_depth;
4766
4767
if (i == -1)
4768
return;
4769
4770
debugyell("Right before line [%d] of file [%s]", load_level[i].line,
4771
load_level[i].filename);
4772
4773
if (!onelevel)
4774
{
4775
while (--i >= 0)
4776
{
4777
debugyell("Loaded right before line [%d] of file [%s]",
4778
load_level[i].line, load_level[i].filename);
4779
}
4780
}
4781
return;
4782
}
4783
4784
const char *current_filename (void)
4785
{
4786
if (load_depth == -1)
4787
return empty_string;
4788
else if (load_level[load_depth].filename)
4789
return load_level[load_depth].filename;
4790
else
4791
return empty_string;
4792
}
4793
4794
int current_line (void)
4795
{
4796
if (load_depth == -1)
4797
return -1;
4798
else
4799
return load_level[load_depth].line;
4800
}
4801
4802
4803
/*
4804
* load: the /LOAD command. Reads the named file, parsing each line as
4805
* though it were typed in (passes each line to parse_command).
4806
Right now, this is broken, as it doesnt handle the passing of
4807
the '-' flag, which is meant to force expansion of expandos
4808
with the arguments after the '-' flag. I think its a lame
4809
feature, anyhow. *sigh*.
4810
*/
4811
4812
BUILT_IN_COMMAND(BX_load)
4813
{
4814
#ifdef PUBLIC_ACCESS
4815
if (!never_connected)
4816
{
4817
bitchsay("This command is disabled for public access systems");
4818
return;
4819
}
4820
#else
4821
FILE *fp;
4822
char *filename,
4823
*expanded = NULL;
4824
int flag = 0;
4825
int paste_level = 0;
4826
register char *start;
4827
char *current_row = NULL;
4828
#define MAX_LINE_LEN 5 * BIG_BUFFER_SIZE
4829
char buffer[MAX_LINE_LEN + 1];
4830
int no_semicolon = 1;
4831
char *irc_path;
4832
int display = window_display;
4833
int ack = 0;
4834
4835
4836
if (!(irc_path = get_string_var(LOAD_PATH_VAR)))
4837
{
4838
bitchsay("LOAD_PATH has not been set");
4839
return;
4840
}
4841
4842
if (++load_depth == MAX_LOAD_DEPTH)
4843
{
4844
load_depth--;
4845
dump_load_stack(0);
4846
bitchsay("No more than %d levels of LOADs allowed", MAX_LOAD_DEPTH);
4847
return;
4848
}
4849
4850
display = window_display;
4851
window_display = 0;
4852
status_update(0);
4853
4854
/*
4855
* We iterate over the whole list -- if we use the -args flag, the
4856
* we will make a note to exit the loop at the bottom after we've
4857
* gone through it once...
4858
*/
4859
while (args && *args && (filename = next_arg(args, &args)))
4860
{
4861
/*
4862
If we use the args flag, then we will get the next
4863
filename (via continue) but at the bottom of the loop
4864
we will exit the loop
4865
*/
4866
if (!my_strnicmp(filename, "-args", strlen(filename)))
4867
{
4868
flag = 1;
4869
continue;
4870
}
4871
if (!end_strcmp(filename, ".tcl", 4))
4872
{
4873
#ifdef WANT_TCL
4874
if (Tcl_EvalFile(tcl_interp, filename) != TCL_OK)
4875
error("Unable to load filename %s[%s]", filename, tcl_interp->result);
4876
#endif
4877
continue;
4878
}
4879
if (!(expanded = expand_twiddle(filename)))
4880
{
4881
error("Unknown user for file %s", filename);
4882
continue;
4883
}
4884
4885
if (!(fp = uzfopen(&expanded, irc_path, 0)))
4886
{
4887
int owc = window_display;
4888
/* uzfopen emits an error if the file
4889
* is not found, so we dont have to. */
4890
window_display = 1;
4891
#ifdef WANT_DLL
4892
if (expanded)
4893
{
4894
dll_load(NULL, expanded, NULL, NULL);
4895
new_free(&expanded);
4896
window_display = owc;
4897
continue;
4898
}
4899
#endif
4900
if (connected_to_server && !load_depth)
4901
bitchsay("Unable to open file %s", filename);
4902
new_free(&expanded);
4903
window_display = owc;
4904
continue;
4905
}
4906
4907
if (command && *command == 'W')
4908
{
4909
yell ("%s", expanded);
4910
if (fp)
4911
fclose (fp);
4912
new_free(&expanded);
4913
continue;
4914
}
4915
/* Reformatted by jfn */
4916
/* *_NOT_* attached, so dont "fix" it */
4917
{
4918
int in_comment = 0;
4919
int comment_line = -1;
4920
int paste_line = -1;
4921
4922
current_row = NULL;
4923
load_level[load_depth].filename = expanded;
4924
load_level[load_depth].line = 1;
4925
4926
for (;;load_level[load_depth].line++)
4927
{
4928
int len;
4929
register char *ptr;
4930
4931
if (!(fgets(buffer,MAX_LINE_LEN, fp)))
4932
break;
4933
4934
for (start = buffer; my_isspace(*start); start++)
4935
;
4936
if (!*start || *start == '#')
4937
continue;
4938
4939
len = strlen(start);
4940
4941
/*
4942
* this line from stargazer to allow \'s in scripts for continued
4943
* lines <[email protected]>
4944
* If we have \\ at the end of the line, that
4945
* should indicate that we DONT want the slash to
4946
* escape the newline (hop)
4947
* We cant just do start[len-2] because we cant say
4948
* what will happen if len = 1... (a blank line)
4949
* SO....
4950
* If the line ends in a newline, and
4951
* If there are at least 2 characters in the line
4952
* and the 2nd to the last one is a \ and,
4953
* If there are EITHER 2 characters on the line or
4954
* the 3rd to the last character is NOT a \ and,
4955
* If the line isnt too big yet and,
4956
* If we can read more from the file,
4957
* THEN -- adjust the length of the string
4958
*/
4959
4960
while ( (start[len-1] == '\n') &&
4961
(len >= 2 && start[len-2] == '\\') &&
4962
(len < 3 || start[len-3] != '\\') &&
4963
(len < MAX_LINE_LEN) &&
4964
(fgets(&(start[len-2]), MAX_LINE_LEN - len, fp)))
4965
{
4966
len = strlen(start);
4967
load_level[load_depth].line++;
4968
}
4969
4970
if (start[len - 1] == '\n')
4971
start[--len] = 0;
4972
if (start[len-1] == '\r')
4973
start[--len] = 0;
4974
4975
while (start && *start)
4976
{
4977
char *optr = start;
4978
4979
/* Skip slashed brackets */
4980
while ((ptr = sindex(optr, "{};/")) &&
4981
ptr != optr && ptr[-1] == '\\')
4982
optr = ptr+1;
4983
4984
/*
4985
* if no_semicolon is set, we will not attempt
4986
* to parse this line, but will continue
4987
* grabbing text
4988
*/
4989
if (no_semicolon)
4990
no_semicolon = 0;
4991
else if ((!ptr || (ptr != start || *ptr == '/')) && current_row)
4992
{
4993
if (!paste_level)
4994
{
4995
parse_line(NULL, current_row, flag ? args :get_int_var(INPUT_ALIASES_VAR) ?empty_string: NULL, 0, 0, 1);
4996
new_free(&current_row);
4997
}
4998
else if (!in_comment)
4999
malloc_strcat(&current_row, ";");
5000
}
5001
5002
if (ptr)
5003
{
5004
char c = *ptr;
5005
5006
*ptr = '\0';
5007
if (!in_comment)
5008
malloc_strcat(&current_row, start);
5009
*ptr = c;
5010
5011
switch (c)
5012
{
5013
/* switch statement tabbed back */
5014
case '/' :
5015
{
5016
/* If we're in a comment, any slashes that arent preceeded by
5017
a star is just ignored (cause its in a comment, after all >;) */
5018
if (in_comment)
5019
{
5020
/* ooops! cant do ptr[-1] if ptr == optr... doh! */
5021
if ((ptr > start) && (ptr[-1] == '*'))
5022
{
5023
in_comment = 0;
5024
comment_line = -1;
5025
}
5026
else
5027
break;
5028
}
5029
/* We're not in a comment... should we start one? */
5030
else
5031
{
5032
/* COMMENT_BREAKAGE_VAR */
5033
if ((ptr[1] == '*') && (!get_int_var(COMMENT_BREAKAGE_VAR) || ptr == start))
5034
{
5035
/* Yep. its the start of a comment. */
5036
in_comment = 1;
5037
comment_line = load_level[load_depth].line;
5038
}
5039
else
5040
{
5041
/* Its NOT a comment. Tack it on the end */
5042
malloc_strcat(&current_row, "/");
5043
5044
/* Is the / is at the EOL? */
5045
if (ptr[1] == '\0')
5046
{
5047
/* If we are NOT in a block alias, */
5048
if (!paste_level)
5049
{
5050
/* Send the line off to parse_line */
5051
parse_line(NULL, current_row, flag ? args : get_int_var(INPUT_ALIASES_VAR) ? empty_string : NULL, 0, 0, 1);
5052
new_free(&current_row);
5053
ack = 0; /* no semicolon.. */
5054
}
5055
else
5056
/* Just add a semicolon and keep going */
5057
ack = 1; /* tack on a semicolon */
5058
}
5059
}
5060
5061
5062
}
5063
no_semicolon = 1 - ack;
5064
ack = 0;
5065
break;
5066
}
5067
case '{' :
5068
{
5069
if (in_comment)
5070
break;
5071
5072
/* If we are opening a brand new {} pair, remember the line */
5073
if (!paste_level)
5074
paste_line = load_level[load_depth].line;
5075
5076
paste_level++;
5077
if (ptr == start)
5078
malloc_strcat(&current_row, " {");
5079
else
5080
malloc_strcat(&current_row, "{");
5081
no_semicolon = 1;
5082
break;
5083
}
5084
case '}' :
5085
{
5086
if (in_comment)
5087
break;
5088
if (!paste_level)
5089
error("Unexpected } in %s, line %d", expanded, load_level[load_depth].line);
5090
else
5091
{
5092
--paste_level;
5093
5094
if (!paste_level)
5095
paste_line = -1;
5096
malloc_strcat(&current_row, "}"); /* } */
5097
no_semicolon = ptr[1]? 1: 0;
5098
}
5099
break;
5100
}
5101
case ';' :
5102
{
5103
if (in_comment)
5104
break;
5105
malloc_strcat(&current_row, ";");
5106
if (!ptr[1] && !paste_level)
5107
{
5108
parse_line(NULL, current_row, flag ? args : get_int_var(INPUT_ALIASES_VAR) ? empty_string : NULL, 0, 0, 1);
5109
new_free(&current_row);
5110
}
5111
else if (!ptr[1] && paste_level)
5112
no_semicolon = 0;
5113
else
5114
no_semicolon = 1;
5115
break;
5116
}
5117
/* End of reformatting */
5118
}
5119
start = ptr+1;
5120
}
5121
else
5122
{
5123
if (!in_comment)
5124
malloc_strcat(&current_row, start);
5125
start = NULL;
5126
}
5127
}
5128
}
5129
if (in_comment)
5130
error("File %s ended with an unterminated comment in line %d", expanded, comment_line);
5131
if (current_row)
5132
{
5133
if (paste_level)
5134
error("Unexpected EOF in %s trying to match '[' at line %d",
5135
expanded, paste_line);
5136
else
5137
parse_line(NULL,current_row, flag ? args: get_int_var(INPUT_ALIASES_VAR) ? empty_string : NULL,0,0, 1);
5138
new_free(&current_row);
5139
}
5140
}
5141
new_free(&expanded);
5142
fclose(fp);
5143
} /* end of the while loop that allows you to load
5144
more then one file at a time.. */
5145
5146
if (get_int_var(DISPLAY_VAR))
5147
window_display = display;
5148
5149
status_update(1);
5150
load_depth--;
5151
#endif
5152
}
5153
5154
5155
5156
/* The SENDLINE command.. */
5157
BUILT_IN_COMMAND(sendlinecmd)
5158
{
5159
int server;
5160
int display;
5161
5162
5163
server = from_server;
5164
display = window_display;
5165
window_display = 1;
5166
if (args && *args)
5167
parse_line(NULL, args, get_int_var(INPUT_ALIASES_VAR) ?empty_string : NULL, 1, 0, 1);
5168
update_input(UPDATE_ALL);
5169
window_display = display;
5170
from_server = server;
5171
}
5172
5173
/*
5174
* irc_clear_screen: the CLEAR_SCREEN function for BIND. Clears the screen and
5175
* starts it if it is held
5176
*/
5177
/*ARGSUSED*/
5178
void irc_clear_screen(char key, char *ptr)
5179
{
5180
5181
set_hold_mode(NULL, OFF, 1);
5182
my_clear(NULL, empty_string, empty_string, NULL);
5183
}
5184
5185
BUILT_IN_COMMAND(cd)
5186
{
5187
char *arg,
5188
*expand;
5189
char buffer[BIG_BUFFER_SIZE + 1];
5190
5191
if ((arg = new_next_arg(args, &args)) != NULL && *arg)
5192
{
5193
if ((expand = expand_twiddle(arg)) != NULL)
5194
{
5195
if (chdir(expand))
5196
{
5197
bitchsay("CD: %s %s", arg, strerror(errno));
5198
new_free(&expand);
5199
return;
5200
}
5201
new_free(&expand);
5202
}
5203
else
5204
{
5205
bitchsay("CD: %s No such directory", arg);
5206
return;
5207
}
5208
}
5209
if (getcwd(buffer, BIG_BUFFER_SIZE))
5210
bitchsay("Current directory: %s", buffer);
5211
else
5212
bitchsay("CD: %s", strerror(errno));
5213
}
5214
5215
BUILT_IN_COMMAND(exec_cmd)
5216
{
5217
char buffer[BIG_BUFFER_SIZE + 1];
5218
5219
snprintf(buffer, BIG_BUFFER_SIZE, "%s %s", command, args);
5220
execcmd(NULL, buffer, subargs, helparg);
5221
}
5222
5223
BUILT_IN_COMMAND(describe)
5224
{
5225
char *target;
5226
5227
5228
target = next_arg(args, &args);
5229
if (target && args && *args)
5230
{
5231
char *message;
5232
5233
message = args;
5234
if (!strcmp(target, "*"))
5235
if ((target = get_current_channel_by_refnum(0)) == NULL)
5236
target = zero;
5237
set_display_target(target, LOG_ACTION);
5238
send_ctcp(CTCP_PRIVMSG, target, CTCP_ACTION, "%s", message);
5239
5240
if (do_hook(SEND_ACTION_LIST, "%s %s", target, message))
5241
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_ACTION_OTHER_FSET),
5242
"%s %s %s %s", update_clock(GET_TIME), get_server_nickname(from_server), target, message));
5243
reset_display_target();
5244
}
5245
}
5246
5247
/*
5248
* New 'me' command.
5249
*/
5250
5251
BUILT_IN_COMMAND(me)
5252
{
5253
5254
if (args && *args)
5255
{
5256
char *target = NULL;
5257
if (!command)
5258
target = get_current_channel_by_refnum(0);
5259
else if (!my_stricmp(command, "dme"))
5260
{
5261
DCC_int *n = NULL;
5262
SocketList *s;
5263
int i;
5264
for (i = 0; i < get_max_fd()+1; i++)
5265
{
5266
if (!check_dcc_socket(i))
5267
continue;
5268
s = get_socket(i);
5269
n = (DCC_int *) s->info;
5270
if (!((s->flags & DCC_TYPES) == DCC_CHAT))
5271
continue;
5272
target = n->user;
5273
break;
5274
}
5275
}
5276
else if (!my_stricmp(command, "qme"))
5277
{
5278
target = current_window->query_nick;
5279
if (!target)
5280
{
5281
Window *tmp = NULL;
5282
while((traverse_all_windows(&tmp)))
5283
if((target = tmp->query_nick))
5284
break;
5285
}
5286
}
5287
else
5288
if (!(target = get_target_by_refnum(0)))
5289
target = get_current_channel_by_refnum(0);
5290
if (target)
5291
{
5292
char *message;
5293
message = args;
5294
set_display_target(target, LOG_ACTION);
5295
send_ctcp(CTCP_PRIVMSG, target, CTCP_ACTION, "%s", message);
5296
5297
if (do_hook(SEND_ACTION_LIST, "%s %s", target, message))
5298
{
5299
if (strchr("&#", *target))
5300
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_ACTION_FSET),
5301
"%s %s %s %s", update_clock(GET_TIME), get_server_nickname(from_server), target, message));
5302
else
5303
put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_ACTION_OTHER_FSET),
5304
"%s %s %s %s", update_clock(GET_TIME), get_server_nickname(from_server), target, message));
5305
}
5306
reset_display_target();
5307
}
5308
}
5309
}
5310
5311
/*
5312
* eval_inputlist: Cute little wrapper that calls parse_line() when we
5313
* get an input prompt ..
5314
*/
5315
5316
void eval_inputlist(char *args, char *line)
5317
{
5318
5319
parse_line(NULL, args, line ? line : empty_string, 0, 0, 1);
5320
}
5321
5322
BUILT_IN_COMMAND(xevalcmd)
5323
{
5324
char * flag;
5325
int old_from_server = from_server;
5326
Window *old_target_window = target_window;
5327
int old_refnum = current_window->refnum;
5328
5329
if (*command == 'X')
5330
{
5331
while (args && (*args == '-' || *args == '/'))
5332
{
5333
flag = next_arg(args, &args);
5334
if (!my_strnicmp(flag + 1, "S", 1)) /* SERVER */
5335
{
5336
int val = my_atol(next_arg(args, &args));
5337
if (is_server_open(val))
5338
from_server = val;
5339
}
5340
else if (!my_strnicmp(flag + 1, "W", 1)) /* WINDOW */
5341
{
5342
Window *win = get_window_by_desc(next_arg(args, &args));
5343
if (win)
5344
{
5345
current_window = win;
5346
target_window = win;
5347
}
5348
}
5349
}
5350
}
5351
5352
parse_line(NULL, args, subargs ? subargs : empty_string, 0, 0, 0);
5353
target_window = old_target_window;
5354
make_window_current_by_winref(old_refnum);
5355
from_server = old_from_server;
5356
}
5357
5358
BUILT_IN_COMMAND(evalcmd)
5359
{
5360
parse_line(NULL, args, subargs ? subargs : empty_string, 0, 0, 0);
5361
}
5362
5363
/*
5364
* inputcmd: the INPUT command. Takes a couple of arguements...
5365
* the first surrounded in double quotes, and the rest makes up
5366
* a normal ircII command. The command is evalutated, with $*
5367
* being the line that you input. Used add_wait_prompt() to prompt
5368
* the user... -phone, jan 1993.
5369
*/
5370
5371
BUILT_IN_COMMAND(inputcmd)
5372
{
5373
char *prompt;
5374
int wait_type;
5375
char *argument;
5376
int echo = 1;
5377
5378
5379
5380
5381
while (*args == '-')
5382
{
5383
argument = next_arg(args, &args);
5384
if (!my_stricmp(argument, "-noecho"))
5385
echo = 0;
5386
}
5387
5388
if (!(prompt = new_next_arg(args, &args)))
5389
{
5390
say("Usage: %s \"prompt\" { commands }", command);
5391
return;
5392
}
5393
5394
if (!my_stricmp(command, "INPUT"))
5395
wait_type = WAIT_PROMPT_LINE;
5396
else
5397
wait_type = WAIT_PROMPT_KEY;
5398
5399
while (my_isspace(*args))
5400
args++;
5401
5402
add_wait_prompt(prompt, eval_inputlist, args, wait_type, echo);
5403
}
5404
5405
BUILT_IN_COMMAND(xtypecmd)
5406
{
5407
char *arg;
5408
5409
5410
if (args && (*args == '-' || *args == '/'))
5411
{
5412
char saved = *args;
5413
args++;
5414
if ((arg = next_arg(args, &args)) != NULL)
5415
{
5416
if (!my_strnicmp(arg, "L", 1))
5417
{
5418
for (; *args; args++)
5419
input_add_character(*args, empty_string);
5420
}
5421
else
5422
bitchsay ("Unknown flag -%s to XTYPE", arg);
5423
return;
5424
}
5425
input_add_character(saved, empty_string);
5426
}
5427
else
5428
type(command, args, empty_string, helparg);
5429
return;
5430
}
5431
5432
BUILT_IN_COMMAND(beepcmd)
5433
{
5434
term_beep();
5435
}
5436
5437
BUILT_IN_COMMAND(e_debug)
5438
{
5439
int x;
5440
char buffer[BIG_BUFFER_SIZE + 1];
5441
5442
if (args && *args)
5443
{
5444
char *s, *copy;
5445
5446
copy = LOCAL_COPY(args);
5447
upper(copy);
5448
while ((s = next_arg(copy, &copy)))
5449
{
5450
char *t, *c;
5451
x = 1;
5452
c = new_next_arg(copy, &copy);
5453
if (!c || !*c)
5454
break;
5455
while ((t = next_in_comma_list(c, &c)))
5456
{
5457
if (!t || !*t)
5458
break;
5459
if (*t == '-')
5460
{
5461
t++;
5462
x = 0;
5463
}
5464
if (!my_stricmp(s, "ALIAS"))
5465
debug_alias(t, x);
5466
else if (!my_stricmp(s, "HOOK"))
5467
debug_hook(t, x);
5468
}
5469
}
5470
return;
5471
}
5472
*buffer = 0;
5473
for (x = 0; x < FD_SETSIZE; x++)
5474
{
5475
if (FD_ISSET(x, &readables))
5476
{
5477
strcat(buffer, space);
5478
strcat(buffer, ltoa(x));
5479
}
5480
}
5481
yell(buffer);
5482
}
5483
5484
BUILT_IN_COMMAND(pretend_cmd)
5485
{
5486
parse_server(args);
5487
}
5488
5489
/*
5490
* This is a quick and dirty hack (emphasis on dirty) that i whipped up
5491
* just for the heck of it. I feel really dirty about using the add_timer
5492
* call (bletch!) to fake a timeout for io(). The better answer would be
5493
* for io() to take an argument specifying the maximum threshold for a
5494
* timeout, but i didnt want to deal with that here. So i just add a
5495
* dummy timer event that does nothing (wasting two function calls and
5496
* about 20 bytes of memory), and call io() until the whole thing blows
5497
* over. Nice and painless. You might want to try this instead of /sleep,
5498
* since this is (obviously) non-blocking. This also calls time() for every
5499
* io event, so that might also start adding up. Oh well, TIOLI.
5500
*
5501
* Without an argument, it waits for the user to press a key. Any key.
5502
* and the key is accepted. Thats probably not right, ill work on that.
5503
*/
5504
static int e_pause_cb_throw = 0;
5505
static void e_pause_cb (char *u1, char *u2) { e_pause_cb_throw--; }
5506
5507
BUILT_IN_COMMAND(e_pause)
5508
{
5509
char *sec;
5510
long milliseconds;
5511
struct timeval start;
5512
5513
if (!(sec = next_arg(args, &args)))
5514
{
5515
int c_level = e_pause_cb_throw;
5516
5517
add_wait_prompt(empty_string, e_pause_cb,
5518
NULL, WAIT_PROMPT_DUMMY, 0);
5519
e_pause_cb_throw++;
5520
while (e_pause_cb_throw > c_level)
5521
io("pause");
5522
return;
5523
}
5524
5525
milliseconds = (long)(atof(sec) * 1000);
5526
get_time(&start);
5527
start.tv_usec += (milliseconds * 1000);
5528
start.tv_sec += (start.tv_usec / 1000000);
5529
start.tv_usec %= 1000000;
5530
5531
/*
5532
* I use comment here simply becuase its not going to mess
5533
* with the arguments.
5534
*/
5535
add_timer(0, empty_string, milliseconds, 1, (int (*)(void *, char *))comment, NULL, NULL, get_current_winref(), "pause");
5536
while (BX_time_diff(get_time(NULL), start) > 0)
5537
io("e_pause");
5538
}
5539
5540
#ifndef WANT_TCL
5541
5542
char tcl_versionstr[] = "";
5543
BUILT_IN_COMMAND(tcl_command)
5544
{
5545
bitchsay("This Client is not compiled with tcl support.");
5546
}
5547
5548
BUILT_IN_COMMAND(tcl_load)
5549
{
5550
tcl_command(NULL, NULL, NULL, NULL);
5551
}
5552
5553
#else
5554
BUILT_IN_COMMAND(tcl_load)
5555
{
5556
char *filename = NULL;
5557
int result = 0;
5558
reset_display_target();
5559
if ((filename = next_arg(args, &args)))
5560
{
5561
char *bla = NULL;
5562
if (get_string_var(LOAD_PATH_VAR))
5563
bla = path_search(filename, get_string_var(LOAD_PATH_VAR));
5564
if ((result = Tcl_EvalFile(tcl_interp, bla?bla:filename)) != TCL_OK)
5565
put_it("Tcl: [%s]",tcl_interp->result);
5566
else if (*tcl_interp->result)
5567
put_it("Tcl: [%s]", tcl_interp->result);
5568
}
5569
}
5570
5571
5572
#endif
5573
5574
5575
BUILT_IN_COMMAND(breakcmd)
5576
{
5577
if (!will_catch_break_exceptions)
5578
say("Cannot BREAK here.");
5579
else
5580
break_exception++;
5581
}
5582
5583
BUILT_IN_COMMAND(continuecmd)
5584
{
5585
if (!will_catch_continue_exceptions)
5586
say("Cannot CONTINUE here.");
5587
else
5588
continue_exception++;
5589
}
5590
5591
BUILT_IN_COMMAND(returncmd)
5592
{
5593
if (!will_catch_return_exceptions)
5594
say("Cannot RETURN here.");
5595
else
5596
{
5597
if (args && *args)
5598
{
5599
int o_w_d = window_display;
5600
window_display = 0;
5601
add_local_alias("FUNCTION_RETURN", args);
5602
window_display = o_w_d;
5603
}
5604
return_exception++;
5605
}
5606
}
5607
5608
5609
BUILT_IN_COMMAND(help)
5610
{
5611
int cnt = 1;
5612
int cntdll = 0;
5613
IrcCommand *cmd = NULL;
5614
#ifdef WANT_DLL
5615
IrcCommandDll *cmddll = NULL;
5616
#endif
5617
int c, i;
5618
char buffer[BIG_BUFFER_SIZE+1];
5619
char *comm = NULL;
5620
reset_display_target();
5621
if (args && *args)
5622
{
5623
comm = next_arg(args, &args);
5624
cmd = find_command(upper(comm), &cnt);
5625
#ifdef WANT_DLL
5626
cmddll = find_dll_command(comm, &cntdll);
5627
if (!cmd && !cmddll)
5628
#else
5629
if (!cmd)
5630
#endif
5631
{
5632
bitchsay("No such command [%s]", comm);
5633
return;
5634
}
5635
if (cmd == irc_command)
5636
{
5637
cmd = NULL;
5638
cnt = 0;
5639
}
5640
if (cnt < 0)
5641
{
5642
userage(cmd->name, cmd->help ? cmd->help : "No Help available Yet");
5643
return;
5644
}
5645
#ifdef WANT_DLL
5646
if (cntdll < 0 && cmddll)
5647
{
5648
userage(cmddll->name, cmddll->help ? cmddll->help : "No Help available Yet");
5649
return;
5650
}
5651
#endif
5652
}
5653
#ifdef WANT_DLL
5654
if (!cmd && !cmddll)
5655
#else
5656
if (!cmd)
5657
#endif
5658
{
5659
cmd = irc_command;
5660
cmd++;
5661
cnt = NUMBER_OF_COMMANDS;
5662
#ifdef WANT_DLL
5663
for (cmddll = dll_commands; cmddll; cmddll = cmddll->next)
5664
cntdll++;
5665
cmddll = dll_commands;
5666
#endif
5667
}
5668
else if (comm && *comm)
5669
{
5670
int tcnt = 0;
5671
tcnt = cnt + cntdll;
5672
put_it("%s", convert_output_format("$G Found %K[%W$0%K]%n matches for %K[%W$1%K]", "%d %s", tcnt, comm));
5673
}
5674
*buffer = 0;
5675
c = 0;
5676
for (i = 0; i < cnt; i++)
5677
{
5678
strmcat(buffer, cmd[i].name, BIG_BUFFER_SIZE);
5679
strmcat(buffer, space, BIG_BUFFER_SIZE);
5680
if (++c == 5)
5681
{
5682
put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
5683
*buffer = 0;
5684
c = 0;
5685
}
5686
}
5687
#ifdef WANT_DLL
5688
for (i = 0; i < cntdll && cmddll; cmddll = cmddll->next, i++)
5689
{
5690
strmcat(buffer, cmddll->name, BIG_BUFFER_SIZE);
5691
strmcat(buffer, space, BIG_BUFFER_SIZE);
5692
if (++c == 5)
5693
{
5694
put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
5695
*buffer = 0;
5696
c = 0;
5697
}
5698
}
5699
#endif
5700
if (c)
5701
put_it("%s", convert_output_format("$G $[13]0 $[13]1 $[13]2 $[13]3 $[13]4", "%s", buffer));
5702
userage("help", "%R[%ncommand%R]%n or /command -help %n to get help on specific commands");
5703
}
5704
5705
5706
5707