1 /*
2 * alias.c Handles command aliases for irc.c
3 *
4 * Written By Michael Sandrof
5 *
6 * Copyright (c) 1990 Michael Sandrof.
7 * Copyright (c) 1991, 1992 Troy Rollo.
8 * Copyright (c) 1992-2000 Matthew R. Green.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * minorly modified to add some extra functionality by:
35 * Joshua J. Drake <jduck@EFNet>
36 */
37
38 #include "irc.h"
39
40 #include "alias.h"
41 #include "channels.h"
42 #include "dcc.h"
43 #include "dma.h"
44 #include "status.h"
45 #include "edit.h"
46 #include "history.h"
47 #include "vars.h"
48 #include "ircaux.h"
49 #include "server.h"
50 /* #include "term.h" */
51 #include "screen.h"
52 #include "window.h"
53 #include "input.h"
54 #include "server.h"
55 #include "output.h"
56 #include "parse.h"
57
58 #include "bans.h"
59 #include "p2a.h"
60 #include "ninja.h"
61
62 #ifdef HAVE_CRYPT
63 # ifdef HAVE_CRYPT_H
64 # include <crypt.h>
65 # endif
66 #endif
67
68 /*
69 * define this to use the old way of managing allocations
70 * inside the guts of alias handling (static buffers, not
71 * malloc & realloc'ed ones).
72 */
73 #undef USE_OLD_ALIAS_ALLOC
74
75 extern int parse_number _((u_char **));
76 static u_char *next_unit _((u_char *, u_char *, int *, int));
77 static long randm _((long));
78 static u_char *lastop _((u_char *));
79 static u_char *arg_number _((int, int, u_char *));
80 static void do_alias_string _((void));
81 static Alias *find_alias _((Alias **, u_char *, int, int *));
82 static void insert_alias _((Alias **, Alias *));
83 static u_char *alias_arg _((u_char **, u_int *));
84 static u_char *find_inline _((u_char *));
85 static u_char *built_in_alias _((int));
86 static u_char *call_function _((u_char *, u_char *, u_char *, int *));
87 #ifndef USE_OLD_ALIAS_ALLOC
88 static void expander_addition _((u_char **, u_char *, int, u_char *));
89 static u_char *alias_special_char
90 _((u_char *, u_char **, u_char *, u_char *, u_char *, int *));
91 #else /* USE_OLD_ALIAS_ALLOC */
92 static void expander_addition _((u_char *, u_char *, int, u_char *));
93 static u_char *alias_special_char
94 _((u_char *, u_char *, u_char *, u_char *, u_char *, int *));
95 #endif /* USE_OLD_ALIAS_ALLOC */
96
97 static u_char *alias_detected _((void));
98 static u_char *alias_sent_nick _((void));
99 static u_char *alias_recv_nick _((void));
100 static u_char *alias_msg_body _((void));
101 static u_char *alias_joined_nick _((void));
102 static u_char *alias_public_nick _((void));
103 static u_char *alias_dollar _((void));
104 static u_char *alias_channel _((void));
105 static u_char *alias_server _((void));
106 static u_char *alias_query_nick _((void));
107 static u_char *alias_target _((void));
108 static u_char *alias_nick _((void));
109 static u_char *alias_invite _((void));
110 static u_char *alias_cmdchar _((void));
111 static u_char *alias_line _((void));
112 static u_char *alias_away _((void));
113 static u_char *alias_oper _((void));
114 static u_char *alias_chanop _((void));
115 static u_char *alias_modes _((void));
116 static u_char *alias_buffer _((void));
117 static u_char *alias_time _((void));
118 static u_char *alias_version _((void));
119 static u_char *alias_currdir _((void));
120 static u_char *alias_current_numeric _((void));
121 static u_char *alias_server_version _((void));
122
123 /* added by jduck */
124 static u_char *alias_hostname _((void));
125
126 typedef struct
127 {
128 u_char name;
129 u_char *(*func) _((void));
130 }
131 BuiltIns;
132
133 static FAR BuiltIns built_in[] = {
134 {'.', alias_sent_nick},
135 {',', alias_recv_nick},
136 {':', alias_joined_nick},
137 {';', alias_public_nick},
138 {'$', alias_dollar},
139 {'A', alias_away},
140 {'B', alias_msg_body},
141 {'C', alias_channel},
142 {'D', alias_detected},
143 {'E', alias_hostname},
144 /*
145 { 'F' },
146 { 'G' },
147 */
148 {'H', alias_current_numeric},
149 {'I', alias_invite},
150 /*
151 { 'J' },
152 */
153 {'K', alias_cmdchar},
154 {'L', alias_line},
155 {'M', alias_modes},
156 {'N', alias_nick},
157 {'O', alias_oper},
158 {'P', alias_chanop},
159 {'Q', alias_query_nick},
160 {'R', alias_server_version},
161 {'S', alias_server},
162 {'T', alias_target},
163 {'U', alias_buffer},
164 {'V', alias_version},
165 {'W', alias_currdir},
166 /*
167 {'X'},
168 {'Y'},
169 */
170 {'Z', alias_time},
171 {(u_char)0, NULL}
172 };
173
174 u_char *command_line = (u_char *) 0;
175
176 u_char *function_left _((u_char *));
177 u_char *function_right _((u_char *));
178 u_char *function_mid _((u_char *));
179 u_char *function_rand _((u_char *));
180 u_char *function_srand _((u_char *));
181 u_char *function_time _((u_char *));
182 u_char *function_stime _((u_char *));
183 u_char *function_index _((u_char *));
184 u_char *function_rindex _((u_char *));
185 u_char *function_match _((u_char *));
186 u_char *function_rmatch _((u_char *));
187 u_char *function_userhost _((u_char *));
188 u_char *function_strip _((u_char *));
189 u_char *function_encode _((u_char *));
190 u_char *function_decode _((u_char *));
191 u_char *function_ischannel _((u_char *));
192 u_char *function_ischanop _((u_char *));
193 #ifdef HAVE_CRYPT
194 u_char *function_crypt _((u_char *));
195 #endif /* HAVE_CRYPT */
196 u_char *function_hasvoice _((u_char *));
197 u_char *function_dcclist _((u_char *));
198 u_char *function_chatpeers _((u_char *));
199 u_char *function_word _((u_char *));
200 u_char *function_winnum _((u_char *));
201 u_char *function_winnam _((u_char *));
202 u_char *function_winrows _((u_char *));
203 u_char *function_wincols _((u_char *));
204 u_char *function_winvisible _((u_char *));
205 u_char *function_winserver _((u_char *));
206 u_char *function_winservergroup _((u_char *));
207 u_char *function_connect _((u_char *));
208 u_char *function_listen _((u_char *));
209 /*
210 * this is the same as ninja's function_etime()
211 * u_char *function_tdiff _((u_char *));
212 */
213 u_char *function_toupper _((u_char *));
214 u_char *function_tolower _((u_char *));
215 u_char *function_channels _((u_char *));
216 u_char *function_servers _((u_char *));
217 u_char *function_servertype _((u_char *));
218 u_char *function_curpos _((u_char *));
219 u_char *function_onchannel _((u_char *));
220 u_char *function_pid _((u_char *));
221 u_char *function_ppid _((u_char *));
222 u_char *function_chanusers _((u_char *));
223 u_char *function_idle _((u_char *));
224 u_char *function_querynick _((u_char *));
225 #ifdef HAVE_STRFTIME
226 u_char *function_strftime _((u_char *));
227 #endif /* HAVE_STRFTIME */
228
229 /* extra functions by jduck */
230 u_char *function_nsize _((u_char *));
231 u_char *function_ndate _((u_char *));
232 u_char *function_ntime _((u_char *));
233 u_char *function_etime _((u_char *));
234 u_char *function_pipe_to_ansi _((u_char *));
235 u_char *function_sed _((u_char *));
236 u_char *function_fromuser _((u_char *));
237 u_char *function_fromhost _((u_char *));
238 u_char *function_banmask _((u_char *));
239
240 typedef struct
241 {
242 u_char *name;
243 u_char *(*func) _((u_char *));
244 }
245 BuiltInFunctions;
246
247 static BuiltInFunctions FAR built_in_functions[] =
248 {
249 {UP("LEFT"), function_left},
250 {UP("RIGHT"), function_right},
251 {UP("MID"), function_mid},
252 {UP("RAND"), function_rand},
253 {UP("SRAND"), function_srand},
254 {UP("TIME"), function_time},
255 /* TDIFF from ircII 4.4 is the same as Ninja's ETIME */
256 {UP("TDIFF"), function_etime},
257 {UP("STIME"), function_stime},
258 {UP("INDEX"), function_index},
259 {UP("RINDEX"), function_rindex},
260 {UP("MATCH"), function_match},
261 {UP("RMATCH"), function_rmatch},
262 {UP("USERHOST"), function_userhost},
263 {UP("STRIP"), function_strip},
264 {UP("ENCODE"), function_encode},
265 {UP("DECODE"), function_decode},
266 {UP("ISCHANNEL"), function_ischannel},
267 {UP("ISCHANOP"), function_ischanop},
268 #ifdef HAVE_CRYPT
269 {UP("CRYPT"), function_crypt},
270 #endif /* HAVE_CRYPT */
271 {UP("HASVOICE"), function_hasvoice},
272 {UP("DCCLIST"), function_dcclist},
273 {UP("CHATPEERS"), function_chatpeers},
274 {UP("WORD"), function_word},
275 {UP("WINNUM"), function_winnum},
276 {UP("WINNAM"), function_winnam},
277 {UP("WINVIS"), function_winvisible},
278 {UP("WINROWS"), function_winrows},
279 {UP("WINCOLS"), function_wincols},
280 {UP("WINSERVER"), function_winserver},
281 {UP("WINSERVERGROUP"), function_winservergroup},
282 {UP("CONNECT"), function_connect},
283 {UP("LISTEN"), function_listen},
284 {UP("TOUPPER"), function_toupper},
285 {UP("TOLOWER"), function_tolower},
286 {UP("MYCHANNELS"), function_channels},
287 {UP("MYSERVERS"), function_servers},
288 {UP("SERVERTYPE"), function_servertype},
289 {UP("CURPOS"), function_curpos},
290 {UP("ONCHANNEL"), function_onchannel},
291 {UP("PID"), function_pid},
292 {UP("PPID"), function_ppid},
293 {UP("CHANUSERS"), function_chanusers},
294 #ifdef HAVE_STRFTIME
295 {UP("STRFTIME"), function_strftime},
296 #endif /* HAVE_STRFTIME */
297 {UP("IDLE"), function_idle},
298 {UP("QUERYNICK"), function_querynick},
299 /* these extensions by jduck */
300 {UP("FROMUSER"), function_fromuser},
301 {UP("FROMHOST"), function_fromhost},
302 {UP("NSIZE"), function_nsize},
303 {UP("NDATE"), function_ndate},
304 {UP("NTIME"), function_ntime},
305 {UP("ETIME"), function_etime},
306 {UP("P2A"), function_pipe_to_ansi},
307 {UP("SED"), function_sed},
308 {UP("BANMASK"), function_banmask},
309 {UP(0), NULL}
310 };
311
312 /* alias_illegals: characters that are illegal in alias names */
313 u_char alias_illegals[] = " #+-*/\\()={}[]<>!@$%^~`,?;:|'\"";
314
315 static Alias *alias_list[] = {
316 (Alias *) 0,
317 (Alias *) 0
318 };
319
320 /* alias_string: the thing that gets replaced by the $"..." construct */
321 static u_char *alias_string = (u_char *)0;
322
323 static int eval_args;
324
325 /* function_stack and function_stkptr - hold the return values from functions */
326 static u_char *FAR function_stack[128] = {
327 (u_char *) 0
328 };
329 static int function_stkptr = 0;
330
331 /*
332 * find_alias: looks up name in in alias list. Returns the Alias entry if
333 * found, or null if not found. If do_unlink is set, the found entry is
334 * removed from the list as well. If match is null, only perfect matches
335 * will return anything. Otherwise, the number of matches will be returned.
336 */
337 static Alias *
find_alias(list,name,do_unlink,match)338 find_alias(list, name, do_unlink, match)
339 Alias **list;
340 u_char *name;
341 int do_unlink;
342 int *match;
343 {
344 Alias *tmp, *last = (Alias *) 0;
345 int cmp;
346 size_t len;
347 int (*cmp_func) _((u_char *, u_char *, size_t));
348
349 if (match)
350 {
351 *match = 0;
352 cmp_func = my_strnicmp;
353 }
354 else
355 cmp_func = (int (*)_((u_char *, u_char *, size_t)))my_stricmp;
356 if (name)
357 {
358 len = my_strlen(name);
359 for (tmp = *list; tmp; tmp = tmp->next)
360 {
361 if ((cmp = cmp_func(name, tmp->name, len)) == 0)
362 {
363 if (do_unlink)
364 {
365 if (last)
366 last->next = tmp->next;
367 else
368 *list = tmp->next;
369 }
370 if (match)
371 {
372 (*match)++;
373 if (my_strlen(tmp->name) == len)
374 {
375 *match = 0;
376 return (tmp);
377 }
378 }
379 else
380 return (tmp);
381 }
382 else if (cmp < 0)
383 break;
384 last = tmp;
385 }
386 }
387 if (match && (*match == 1))
388 return (last);
389 else
390 return ((Alias *) 0);
391 }
392
393 /*
394 * insert_alias: adds the given alias to the alias list. The alias list is
395 * alphabetized by name
396 */
397 static void
insert_alias(list,nalias)398 insert_alias(list, nalias)
399 Alias **list;
400 Alias *nalias;
401 {
402 Alias *tmp, *last, *foo;
403
404 last = (Alias *) 0;
405 for (tmp = *list; tmp; tmp = tmp->next)
406 {
407 if (my_strcmp(nalias->name, tmp->name) < 0)
408 break;
409 last = tmp;
410 }
411 if (last)
412 {
413 foo = last->next;
414 last->next = nalias;
415 nalias->next = foo;
416 }
417 else
418 {
419 nalias->next = *list;
420 *list = nalias;
421 }
422 }
423
424 /*
425 * add_alias: given the alias name and "stuff" that makes up the alias,
426 * add_alias() first checks to see if the alias name is already in use... if
427 * so, the old alias is replaced with the new one. If the alias is not
428 * already in use, it is added.
429 */
430 void
add_alias(type,name,stuff)431 add_alias(type, name, stuff)
432 int type;
433 u_char *name, *stuff;
434 {
435 Alias *tmp;
436 u_char *ptr;
437
438 upper(name);
439 if (type == COMMAND_ALIAS)
440 put_info("Alias \t%s added", name);
441 else
442 {
443 if (!my_strcmp(name, "FUNCTION_RETURN"))
444 {
445 if (function_stack[function_stkptr])
446 dma_Free(&function_stack[function_stkptr]);
447 dma_strcpy(&function_stack[function_stkptr], stuff);
448 return;
449 }
450 if ((ptr = sindex(name, alias_illegals)) != NULL)
451 {
452 put_error("Assign names may not contain '%c'", *ptr);
453 return;
454 }
455 put_info("Assign %s added", name);
456 }
457 if ((tmp = find_alias(&(alias_list[type]), name, 1, (int *)0)) ==
458 (Alias *) 0)
459 {
460 tmp = (Alias *) dma_Malloc(sizeof(Alias));
461 if (tmp == (Alias *) 0)
462 {
463 put_error("Couldn't allocate memory for new alias!");
464 return;
465 }
466 tmp->name = (u_char *)0;
467 tmp->stuff = (u_char *)0;
468 }
469 dma_strcpy(&(tmp->name), name);
470 dma_strcpy(&(tmp->stuff), stuff);
471 tmp->mark = 0;
472 tmp->global = loading_global;
473 insert_alias(&(alias_list[type]), tmp);
474 }
475
476 /* alias_arg: a special version of next_arg for aliases */
477 static u_char *
alias_arg(str,pos)478 alias_arg(str, pos)
479 u_char **str;
480 u_int *pos;
481 {
482 u_char *ptr;
483
484 if (!*str)
485 return (u_char *)0;
486 *pos = 0;
487 ptr = *str;
488 while (' ' == *ptr)
489 {
490 ptr++;
491 (*pos)++;
492 }
493 if (*ptr == '\0')
494 {
495 *str = empty_string;
496 return (u_char *)0;
497 }
498 if ((*str = sindex(ptr, UP(" "))) != NULL)
499 *((*str)++) = '\0';
500 else
501 *str = empty_string;
502 return (ptr);
503 }
504
505 /* word_count: returns the number of words in the given string */
506 extern int
507 word_count(str)
508 u_char *str;
509 {
510 int cnt = 0;
511 u_char *ptr;
512
513 while (1)
514 {
515 if ((ptr = sindex(str, UP("^ "))) != NULL)
516 {
517 cnt++;
518 if ((str = sindex(ptr, UP(" "))) == (u_char *)0)
519 return (cnt);
520 }
521 else
522 return (cnt);
523 }
524 }
525
526 static u_char *
built_in_alias(c)527 built_in_alias(c)
528 int c;
529 {
530 BuiltIns *tmp;
531 u_char *ret = (u_char *)0;
532
533 for (tmp = built_in; tmp->name; tmp++)
534 if ((u_char)c == tmp->name)
535 {
536 dma_strcpy(&ret, tmp->func());
537 break;
538 }
539 return (ret);
540 }
541
542 /*
543 * find_inline: This simply looks up the given str. It first checks to see
544 * if its a user variable and returns it if so. If not, it checks to see if
545 * it's an IRC variable and returns it if so. If not, it checks to see if
546 * its and environment variable and returns it if so. If not, it returns
547 * null. It mallocs the returned string
548 */
549 static u_char *
find_inline(str)550 find_inline(str)
551 u_char *str;
552 {
553 Alias *nalias;
554 u_char *ret = NULL;
555 u_char *tmp;
556
557 if ((nalias = find_alias(&(alias_list[VAR_ALIAS]), str, 0, (int *)NULL))
558 != NULL)
559 {
560 dma_strcpy(&ret, nalias->stuff);
561 return (ret);
562 }
563 if ((my_strlen(str) == 1) && (ret = built_in_alias(*str)))
564 return (ret);
565 if ((ret = make_string_var(str)) != NULL)
566 return (ret);
567 #ifdef DAEMON_UID
568 if (getuid() == DAEMON_UID)
569 dma_strcpy(&ret, (getuid() != DAEMON_UID) && (tmp = my_getenv(str)) ?
570 tmp : empty_string);
571 #else
572 dma_strcpy(&ret, (tmp = my_getenv(str)) ? tmp : empty_string);
573 #endif
574 return (ret);
575 }
576
577 static u_char *
call_function(name,f_args,args,args_flag)578 call_function(name, f_args, args, args_flag)
579 u_char *name, *f_args, *args;
580 int *args_flag;
581 {
582 u_char *tmp;
583 u_char *result = (u_char *) 0;
584 u_char *sub_buffer = (u_char *) 0;
585 int builtnum;
586 u_char *debug_copy = (u_char *) 0;
587 u_char *cmd = (u_char *) 0;
588
589 dma_strcpy(&cmd, name);
590 upper(cmd);
591 tmp = expand_alias((u_char *) 0, f_args, args, args_flag, NULL);
592 if (get_int_var(DEBUG_VAR) & DEBUG_FUNCTIONS)
593 dma_strcpy(&debug_copy, tmp);
594 for (builtnum = 0; built_in_functions[builtnum].name != NULL &&
595 my_strcmp(built_in_functions[builtnum].name, cmd); builtnum++)
596 ;
597 dma_Free(&cmd);
598 if (built_in_functions[builtnum].name)
599 result = built_in_functions[builtnum].func(tmp);
600 else
601 {
602 sub_buffer = dma_Malloc(my_strlen(name) + my_strlen(tmp) + 2);
603 my_strcpy(sub_buffer, name);
604 my_strcat(sub_buffer, " ");
605 my_strcat(sub_buffer, tmp);
606 function_stack[++function_stkptr] = (u_char *) 0;
607 parse_command(sub_buffer, 0, empty_string);
608 dma_Free(&sub_buffer);
609 eval_args = 1;
610 result = function_stack[function_stkptr];
611 function_stack[function_stkptr] = (u_char *) 0;
612 if (!result)
613 dma_strcpy(&result, empty_string);
614 function_stkptr--;
615 }
616 if (debug_copy)
617 {
618 put_error("Function %s(%s) returned %s", name, debug_copy, result);
619 dma_Free(&debug_copy);
620 }
621 dma_Free(&tmp);
622 return (result);
623 }
624
625 /* Given a pointer to an operator, find the last operator in the string */
626 static u_char *
lastop(ptr)627 lastop(ptr)
628 u_char *ptr;
629 {
630 while (ptr[1] && index("!=<>&^|#+/-*", ptr[1]))
631 ptr++;
632 return ptr;
633 }
634
635 #define NU_EXPR 0
636 #define NU_CONJ NU_EXPR
637 #define NU_ASSN 1
638 #define NU_COMP 2
639 #define NU_ADD 3
640 #define NU_MULT 4
641 #define NU_UNIT 5
642 #define NU_TERT 6
643 #define NU_BITW 8
644
645 static u_char *
next_unit(str,args,arg_flag,stage)646 next_unit(str, args, arg_flag, stage)
647 u_char *str, *args;
648 int *arg_flag, stage;
649 {
650 u_char *ptr, *ptr2, *right;
651 int got_sloshed = 0;
652 u_char *lastc;
653 u_char tmp[40];
654 u_char *result1 = (u_char *) 0, *result2 = (u_char *) 0;
655 long value1 = 0, value2, value3;
656 u_char op;
657 int display;
658 u_char *ArrayIndex, *EndIndex;
659
660 while (isspace(*str))
661 ++str;
662 if (!*str)
663 {
664 dma_strcpy(&result1, empty_string);
665 return result1;
666 }
667 lastc = str + my_strlen(str) - 1;
668 while (isspace(*lastc))
669 *lastc-- = '\0';
670 if (stage == NU_UNIT && *lastc == ')' && *str == '(')
671 {
672 str++, *lastc-- = '\0';
673 return next_unit(str, args, arg_flag, NU_EXPR);
674 }
675 if (!*str)
676 {
677 dma_strcpy(&result1, empty_string);
678 return result1;
679 }
680 for (ptr = str; *ptr; ptr++)
681 {
682 if (got_sloshed) /* Help! I'm drunk! */
683 {
684 got_sloshed = 0;
685 continue;
686 }
687 switch (*ptr)
688 {
689 case '\\':
690 got_sloshed = 1;
691 continue;
692 case '(':
693 if (stage != NU_UNIT || ptr == str)
694 {
695 if (!(ptr2 = MatchingBracket(ptr + 1, (int)'(', (int)')')))
696 ptr = ptr + my_strlen(ptr) - 1;
697 else
698 ptr = ptr2;
699 break;
700 }
701 *ptr++ = '\0';
702 right = ptr;
703 ptr = MatchingBracket(right, (int)LEFT_PAREN, (int)RIGHT_PAREN);
704 if (ptr)
705 *ptr++ = '\0';
706 result1 = call_function(str, right, args, arg_flag);
707 if (ptr && *ptr)
708 {
709 dma_strcat(&result1, ptr);
710 result2 = next_unit(result1, args, arg_flag, stage);
711 dma_Free(&result1);
712 result1 = result2;
713 }
714 return result1;
715 case '[':
716 if (stage != NU_UNIT)
717 {
718 if (!(ptr2 = MatchingBracket(ptr + 1, (int)'[', (int)']')))
719 ptr = ptr + my_strlen(ptr) - 1;
720 else
721 ptr = ptr2;
722 break;
723 }
724 *ptr++ = '\0';
725 right = ptr;
726 ptr = MatchingBracket(right, (int)LEFT_BRACKET, (int)RIGHT_BRACKET);
727 if (ptr)
728 *ptr++ = '\0';
729 result1 = expand_alias((u_char *) 0, right, args, arg_flag, NULL);
730 if (*str)
731 {
732 result2 = dma_Malloc(my_strlen(str) +
733 (result1 ? my_strlen(result1) : 0) +
734 (ptr ? my_strlen(ptr) : 0) + 2);
735 my_strcpy(result2, str); /* safe, malloc'd */
736 my_strcat(result2, "."); /* safe, malloc'd */
737 my_strcat(result2, result1); /* safe, malloc'd */
738 dma_Free(&result1);
739 if (ptr && *ptr)
740 {
741 my_strcat(result2, ptr); /* safe, malloc'd */
742 result1 = next_unit(result2, args, arg_flag, stage);
743 }
744 else
745 {
746 result1 = find_inline(result2);
747 if (!result1)
748 dma_strcpy(&result1, empty_string);
749 }
750 dma_Free(&result2);
751 }
752 else if (ptr && *ptr)
753 {
754 dma_strcat(&result1, ptr);
755 result2 = next_unit(result1, args, arg_flag, stage);
756 dma_Free(&result1);
757 result1 = result2;
758 }
759 return result1;
760 case '-':
761 case '+':
762 if (*(ptr + 1) == *(ptr)) /* index operator */
763 {
764 u_char *tptr;
765
766 *ptr++ = '\0';
767 if (ptr == str + 1) /* Its a prefix */
768 {
769 tptr = str + 2;
770 }
771 else /* Its a postfix */
772 {
773 tptr = str;
774 }
775 result1 = find_inline(tptr);
776 if (!result1)
777 dma_strcpy(&result1, zero);
778
779 { /* This isnt supposed to be
780 attached to the if, so
781 dont "fix" it. */
782 int r;
783 r = my_atoi(result1);
784 if (*ptr == '+')
785 r++;
786 else
787 r--;
788 sprintf(CP(tmp), "%d", r); /* safe, sizeof(tmp) == 40 */
789 display = window_display;
790 window_display = 0;
791 add_alias(VAR_ALIAS, tptr, tmp);
792 window_display = display;
793 }
794 /* A kludge? Cheating? Maybe.... */
795 if (ptr == str + 1)
796 {
797 *(ptr - 1) = ' ';
798 *ptr = ' ';
799 }
800 else
801 {
802 if (*ptr == '+')
803 *(ptr - 1) = '-';
804 else
805 *(ptr - 1) = '+';
806 *ptr = '1';
807 }
808 ptr = str;
809 dma_Free(&result1);
810 break;
811 }
812 if (ptr == str) /* It's unary..... do nothing */
813 break;
814 if (stage != NU_ADD)
815 {
816 ptr = lastop(ptr);
817 break;
818 }
819 op = *ptr;
820 *ptr++ = '\0';
821 result1 = next_unit(str, args, arg_flag, stage);
822 result2 = next_unit(ptr, args, arg_flag, stage);
823 value1 = my_atol(result1);
824 value2 = my_atol(result2);
825 dma_Free(&result1);
826 dma_Free(&result2);
827 if (op == '-')
828 value3 = value1 - value2;
829 else
830 value3 = value1 + value2;
831 sprintf(CP(tmp), "%ld", value3); /* safe */
832 dma_strcpy(&result1, tmp);
833 return result1;
834 case '/':
835 case '*':
836 case '%':
837 if (stage != NU_MULT)
838 {
839 ptr = lastop(ptr);
840 break;
841 }
842 op = *ptr;
843 *ptr++ = '\0';
844 result1 = next_unit(str, args, arg_flag, stage);
845 result2 = next_unit(ptr, args, arg_flag, stage);
846 value1 = my_atol(result1);
847 value2 = my_atol(result2);
848 dma_Free(&result1);
849 dma_Free(&result2);
850 if (op == '/')
851 {
852 if (value2)
853 value3 = value1 / value2;
854 else
855 {
856 value3 = 0;
857 put_error("Division by zero");
858 }
859 }
860 else if (op == '*')
861 value3 = value1 * value2;
862 else
863 {
864 if (value2)
865 value3 = value1 % value2;
866 else
867 {
868 value3 = 0;
869 put_error("Mod by zero");
870 }
871 }
872 sprintf(CP(tmp), "%ld", value3); /* safe */
873 dma_strcpy(&result1, tmp);
874 return result1;
875 case '#':
876 if (stage != NU_ADD || ptr[1] != '#')
877 {
878 ptr = lastop(ptr);
879 break;
880 }
881 *ptr = '\0';
882 ptr += 2;
883 result1 = next_unit(str, args, arg_flag, stage);
884 result2 = next_unit(ptr, args, arg_flag, stage);
885 dma_strcat(&result1, result2);
886 dma_Free(&result2);
887 return result1;
888 /* Reworked - Jeremy Nelson, Feb 1994
889 * & or && should both be supported, each with different
890 * stages, same with || and ^^. Also, they should be
891 * short-circuit as well.
892 */
893 case '&':
894 if (ptr[0] == ptr[1])
895 {
896 if (stage != NU_CONJ)
897 {
898 ptr = lastop(ptr);
899 break;
900 }
901 *ptr = '\0';
902 ptr += 2;
903 result1 = next_unit(str, args, arg_flag, stage);
904 value1 = my_atol(result1);
905 if (value1)
906 {
907 result2 = next_unit(ptr, args, arg_flag, stage);
908 value2 = my_atol(result2);
909 value3 = value1 && value2;
910 }
911 else
912 value3 = 0;
913 dma_Free(&result1);
914 dma_Free(&result2);
915 tmp[0] = '0' + (value3 ? 1 : 0);
916 tmp[1] = '\0';
917 dma_strcpy(&result1, tmp);
918 return result1;
919 }
920 else
921 {
922 if (stage != NU_BITW)
923 {
924 ptr = lastop(ptr);
925 break;
926 }
927 *ptr = '\0';
928 ptr += 1;
929 result1 = next_unit(str, args, arg_flag, stage);
930 result2 = next_unit(ptr, args, arg_flag, stage);
931 value1 = my_atol(result1);
932 value2 = my_atol(result2);
933 dma_Free(&result1);
934 dma_Free(&result2);
935 value3 = value1 & value2;
936 sprintf(CP(tmp), "%ld", value3); /* safe */
937 dma_strcpy(&result1, tmp);
938 return result1;
939 }
940 case '|':
941 if (ptr[0] == ptr[1])
942 {
943 if (stage != NU_CONJ)
944 {
945 ptr = lastop(ptr);
946 break;
947 }
948 *ptr = '\0';
949 ptr += 2;
950 result1 = next_unit(str, args, arg_flag, stage);
951 value1 = my_atol(result1);
952 if (!value1)
953 {
954 result2 = next_unit(ptr, args, arg_flag, stage);
955 value2 = my_atol(result2);
956 value3 = value1 || value2;
957 }
958 else
959 value3 = 1;
960 dma_Free(&result1);
961 dma_Free(&result2);
962 tmp[0] = '0' + (value3 ? 1 : 0);
963 tmp[1] = '\0';
964 dma_strcpy(&result1, tmp);
965 return result1;
966 }
967 else
968 {
969 if (stage != NU_BITW)
970 {
971 ptr = lastop(ptr);
972 break;
973 }
974 *ptr = '\0';
975 ptr += 1;
976 result1 = next_unit(str, args, arg_flag, stage);
977 result2 = next_unit(ptr, args, arg_flag, stage);
978 value1 = my_atol(result1);
979 value2 = my_atol(result2);
980 dma_Free(&result1);
981 dma_Free(&result2);
982 value3 = value1 | value2;
983 sprintf(CP(tmp), "%ld", value3); /* safe */
984 dma_strcpy(&result1, tmp);
985 return result1;
986 }
987 case '^':
988 if (ptr[0] == ptr[1])
989 {
990 if (stage != NU_CONJ)
991 {
992 ptr = lastop(ptr);
993 break;
994 }
995 *ptr = '\0';
996 ptr += 2;
997 result1 = next_unit(str, args, arg_flag, stage);
998 result2 = next_unit(ptr, args, arg_flag, stage);
999 value1 = my_atol(result1);
1000 value2 = my_atol(result2);
1001 value1 = value1 ? 1 : 0;
1002 value2 = value2 ? 1 : 0;
1003 value3 = value1 ^ value2;
1004 dma_Free(&result1);
1005 dma_Free(&result2);
1006 tmp[0] = '0' + (value3 ? 1 : 0);
1007 tmp[1] = '\0';
1008 dma_strcpy(&result1, tmp);
1009 return result1;
1010 }
1011 else
1012 {
1013 if (stage != NU_BITW)
1014 {
1015 ptr = lastop(ptr);
1016 break;
1017 }
1018 *ptr = '\0';
1019 ptr += 1;
1020 result1 = next_unit(str, args, arg_flag, stage);
1021 result2 = next_unit(ptr, args, arg_flag, stage);
1022 value1 = my_atol(result1);
1023 value2 = my_atol(result2);
1024 dma_Free(&result1);
1025 dma_Free(&result2);
1026 value3 = value1 ^ value2;
1027 sprintf(CP(tmp), "%ld", value3); /* safe */
1028 dma_strcpy(&result1, tmp);
1029 return result1;
1030 }
1031 case '?':
1032 if (stage != NU_TERT)
1033 {
1034 ptr = lastop(ptr);
1035 break;
1036 }
1037 *ptr++ = '\0';
1038 result1 = next_unit(str, args, arg_flag, stage);
1039 ptr2 = my_index(ptr, ':');
1040 *ptr2++ = '\0';
1041 right = result1;
1042 value1 = parse_number(&right);
1043 if ((value1 == -1) && (*right == (u_char)0))
1044 value1 = 0;
1045 if (value1 == 0)
1046 while (isspace(*right))
1047 *(right++) = '\0';
1048 if (value1 || *right)
1049 result2 = next_unit(ptr, args, arg_flag, stage);
1050 else
1051 result2 = next_unit(ptr2, args, arg_flag, stage);
1052 *(ptr2 - 1) = ':';
1053 dma_Free(&result1);
1054 return result2;
1055 case '=':
1056 if (ptr[1] != '=')
1057 {
1058 if (stage != NU_ASSN)
1059 {
1060 ptr = lastop(ptr);
1061 break;
1062 }
1063 *ptr++ = '\0';
1064 result1 = expand_alias((u_char *) 0, str,
1065 args, arg_flag, NULL);
1066 result2 = next_unit(ptr, args, arg_flag, stage);
1067 display = window_display;
1068 window_display = 0;
1069 lastc = result1 + my_strlen(result1) - 1;
1070 while (lastc > result1 && *lastc == ' ')
1071 *lastc-- = '\0';
1072 for (ptr = result1; *ptr == ' '; ptr++);
1073 while ((ArrayIndex = my_index(ptr, '[')) != NULL)
1074 {
1075 *ArrayIndex++ = '.';
1076 if ((EndIndex = MatchingBracket(ArrayIndex,
1077 (int)LEFT_BRACKET,
1078 (int)RIGHT_BRACKET))
1079 != NULL)
1080 {
1081 *EndIndex++ = '\0';
1082 my_strcat(ptr, EndIndex);
1083 }
1084 else
1085 break;
1086 }
1087 if (*ptr)
1088 add_alias(VAR_ALIAS, ptr, result2);
1089 else
1090 put_error("Invalid assignment expression");
1091 window_display = display;
1092 dma_Free(&result1);
1093 return result2;
1094 }
1095 if (stage != NU_COMP)
1096 {
1097 ptr = lastop(ptr);
1098 break;
1099 }
1100 *ptr = '\0';
1101 ptr += 2;
1102 result1 = next_unit(str, args, arg_flag, stage);
1103 result2 = next_unit(ptr, args, arg_flag, stage);
1104 if (!my_stricmp(result1, result2))
1105 dma_strcpy(&result1, one);
1106 else
1107 dma_strcpy(&result1, zero);
1108 dma_Free(&result2);
1109 return result1;
1110 case '>':
1111 case '<':
1112 if (stage != NU_COMP)
1113 {
1114 ptr = lastop(ptr);
1115 break;
1116 }
1117 op = *ptr;
1118 if (ptr[1] == '=')
1119 value3 = 1, *ptr++ = '\0';
1120 else
1121 value3 = 0;
1122 *ptr++ = '\0';
1123 result1 = next_unit(str, args, arg_flag, stage);
1124 result2 = next_unit(ptr, args, arg_flag, stage);
1125 if (isdigit(*result1) && isdigit(*result2))
1126 {
1127 value1 = my_atol(result1);
1128 value2 = my_atol(result2);
1129 value1 = (value1 == value2) ? 0 : ((value1 <
1130 value2) ? -1 : 1);
1131 }
1132 else
1133 value1 = my_stricmp(result1, result2);
1134 if (value1)
1135 {
1136 value2 = (value1 > 0) ? 1 : 0;
1137 if (op == '<')
1138 value2 = 1 - value2;
1139 }
1140 else
1141 value2 = value3;
1142 dma_Free(&result2);
1143 sprintf(CP(tmp), "%ld", value2); /* safe */
1144 dma_strcpy(&result1, tmp);
1145 return result1;
1146 case '~':
1147 if (ptr == str)
1148 {
1149 if (stage != NU_BITW)
1150 break;
1151 result1 = next_unit(str + 1, args, arg_flag, stage);
1152 if (isdigit(*result1))
1153 {
1154 value1 = my_atol(result1);
1155 value2 = ~value1;
1156 }
1157 else
1158 value2 = 0;
1159 sprintf(CP(tmp), "%ld", value2); /* safe */
1160 dma_strcpy(&result1, tmp);
1161 return result1;
1162 }
1163 else
1164 {
1165 ptr = lastop(ptr);
1166 break;
1167 }
1168 case '!':
1169 if (ptr == str)
1170 {
1171 if (stage != NU_UNIT)
1172 break;
1173 result1 = next_unit(str + 1, args, arg_flag, stage);
1174 if (isdigit(*result1))
1175 {
1176 value1 = my_atol(result1);
1177 value2 = value1 ? 0 : 1;
1178 }
1179 else
1180 {
1181 value2 = ((*result1) ? 0 : 1);
1182 }
1183 sprintf(CP(tmp), "%ld", value2); /* safe */
1184 dma_strcpy(&result1, tmp);
1185 return result1;
1186 }
1187 if (stage != NU_COMP || ptr[1] != '=')
1188 {
1189 ptr = lastop(ptr);
1190 break;
1191 }
1192 *ptr = '\0';
1193 ptr += 2;
1194 result1 = next_unit(str, args, arg_flag, stage);
1195 result2 = next_unit(ptr, args, arg_flag, stage);
1196 if (!my_stricmp(result1, result2))
1197 dma_strcpy(&result1, zero);
1198 else
1199 dma_strcpy(&result1, one);
1200 dma_Free(&result2);
1201 return result1;
1202 case ',':
1203 /*
1204 * this utterly kludge code is needed (?) to get
1205 * around bugs introduced from hop's patches to
1206 * alias.c. the $, variable stopped working
1207 * because of this. -mrg, july 94.
1208 */
1209 if (ptr == str || (ptr > str && ptr[-1] == '$'))
1210 break;
1211 if (stage != NU_EXPR)
1212 {
1213 ptr = lastop(ptr);
1214 break;
1215 }
1216 *ptr++ = '\0';
1217 result1 = next_unit(str, args, arg_flag, stage);
1218 result2 = next_unit(ptr, args, arg_flag, stage);
1219 dma_Free(&result1);
1220 return result2;
1221 }
1222 }
1223 if (stage != NU_UNIT)
1224 return next_unit(str, args, arg_flag, stage + 1);
1225 if (isdigit(*str) || *str == '+' || *str == '-')
1226 dma_strcpy(&result1, str);
1227 else
1228 {
1229 if (*str == '#' || *str == '@')
1230 op = *str++;
1231 else
1232 op = '\0';
1233 result1 = find_inline(str);
1234 if (!result1)
1235 dma_strcpy(&result1, empty_string);
1236 if (op)
1237 {
1238 if (op == '#')
1239 value1 = word_count(result1);
1240 else if (op == '@')
1241 value1 = my_strlen(result1);
1242 sprintf(CP(tmp), "%ld", value1); /* safe */
1243 dma_strcpy(&result1, tmp);
1244 }
1245 }
1246 return result1;
1247 }
1248
1249 /*
1250 * parse_inline: This evaluates user-variable expression. I'll talk more
1251 * about this at some future date. The ^ function and some fixes by
1252 * troy@cbme.unsw.EDU.AU (Troy Rollo)
1253 */
1254 u_char *
parse_inline(str,args,args_flag)1255 parse_inline(str, args, args_flag)
1256 u_char *str;
1257 u_char *args;
1258 int *args_flag;
1259 {
1260 return next_unit(str, args, args_flag, NU_EXPR);
1261 }
1262
1263 /*
1264 * arg_number: Returns the argument 'num' from 'str', or, if 'num' is
1265 * negative, returns from argument 'num' to the end of 'str'. You might be
1266 * wondering what's going on down there... here goes. First we copy 'str' to
1267 * malloced space. Then, using next_arg(), we strip out each argument ,
1268 * putting them in arg_list, and putting their position in the original
1269 * string in arg_list_pos. Anyway, once parsing is done, the arguments are
1270 * returned directly from the arg_list array... or in the case of negative
1271 * 'num', the arg_list_pos is used to return the postion of the rest of the
1272 * args in the original string... got it? Anyway, the bad points of the
1273 * routine: 1) Always parses out everything, even if only one arg is used.
1274 * 2) The malloced stuff remains around until arg_number is called with a
1275 * different string. Even then, some malloced stuff remains around. This can
1276 * be fixed.
1277 */
1278
1279 #define LAST_ARG 8000
1280
1281 static u_char *
arg_number(lower_lim,upper_lim,str)1282 arg_number(lower_lim, upper_lim, str)
1283 int lower_lim, upper_lim;
1284 u_char *str;
1285 {
1286 u_char *ptr, *arg, c;
1287 int use_full = 0;
1288 unsigned int pos, start_pos;
1289 static u_char *last_args = (u_char *) 0;
1290 static u_char *last_range = (u_char *) 0;
1291 static u_char **arg_list = (u_char **) 0;
1292 static unsigned int *arg_list_pos = (unsigned int *)0;
1293 static unsigned int *arg_list_end_pos = (unsigned int *)0;
1294 static int arg_list_size;
1295
1296 if (eval_args)
1297 {
1298 int arg_list_limit;
1299
1300 eval_args = 0;
1301 dma_Free(&arg_list);
1302 dma_Free(&arg_list_pos);
1303 dma_Free(&arg_list_end_pos);
1304 arg_list_size = 0;
1305 arg_list_limit = 10;
1306 arg_list = (u_char **) dma_Malloc(sizeof(u_char *) * arg_list_limit);
1307 arg_list_pos = (unsigned int *)dma_Malloc(sizeof(unsigned int)
1308 * arg_list_limit);
1309 arg_list_end_pos = (unsigned int *)dma_Malloc(sizeof(unsigned
1310 int) *
1311 arg_list_limit);
1312 dma_strcpy(&last_args, str);
1313 ptr = last_args;
1314 pos = 0;
1315 while ((arg = alias_arg(&ptr, &start_pos)) != NULL)
1316 {
1317 arg_list_pos[arg_list_size] = pos;
1318 pos += start_pos + my_strlen(arg);
1319 arg_list_end_pos[arg_list_size] = pos++;
1320 arg_list[arg_list_size++] = arg;
1321 if (arg_list_size == arg_list_limit)
1322 {
1323 arg_list_limit += 10;
1324 arg_list =
1325 (u_char **) dma_ReAlloc((u_char *) arg_list,
1326 sizeof(u_char *) *
1327 arg_list_limit);
1328 arg_list_pos =
1329 (unsigned int *)dma_ReAlloc(UP(arg_list_pos),
1330 sizeof(unsigned int) *
1331 arg_list_limit);
1332 arg_list_end_pos =
1333 (unsigned int *)dma_ReAlloc(UP(arg_list_end_pos),
1334 sizeof(unsigned int) *
1335 arg_list_limit);
1336 }
1337 }
1338 }
1339 if (upper_lim == LAST_ARG && lower_lim == LAST_ARG)
1340 upper_lim = lower_lim = arg_list_size - 1;
1341 if (arg_list_size == 0)
1342 return (empty_string);
1343 if ((upper_lim >= arg_list_size) || (upper_lim < 0))
1344 {
1345 use_full = 1;
1346 upper_lim = arg_list_size - 1;
1347 }
1348 if (upper_lim < lower_lim)
1349 return (empty_string);
1350 if (lower_lim >= arg_list_size)
1351 lower_lim = arg_list_size - 1;
1352 else if (lower_lim < 0)
1353 lower_lim = 0;
1354 if ((use_full == 0) && (lower_lim == upper_lim))
1355 return (arg_list[lower_lim]);
1356 c = *(str + arg_list_end_pos[upper_lim]);
1357 *(str + arg_list_end_pos[upper_lim]) = (u_char) 0;
1358 dma_strcpy(&last_range, str + arg_list_pos[lower_lim]);
1359 *(str + arg_list_end_pos[upper_lim]) = c;
1360 return (last_range);
1361 }
1362
1363 /*
1364 * parse_number: returns the next number found in a string and moves the
1365 * string pointer beyond that point in the string. Here's some examples:
1366 *
1367 * "123harhar" returns 123 and str as "harhar"
1368 *
1369 * while:
1370 *
1371 * "hoohar" returns -1 and str as "hoohar"
1372 */
1373 extern int
1374 parse_number(str)
1375 u_char **str;
1376 {
1377 int ret;
1378 u_char *ptr;
1379
1380 ptr = *str;
1381 if (isdigit(*ptr))
1382 {
1383 ret = my_atoi(ptr);
1384 for (; isdigit(*ptr); ptr++);
1385 *str = ptr;
1386 }
1387 else
1388 ret = -1;
1389 return (ret);
1390 }
1391
1392 static void
do_alias_string()1393 do_alias_string()
1394 {
1395 dma_strcpy(&alias_string, get_input());
1396 irc_io_loop = 0;
1397 }
1398
1399 /*
1400 * expander_addition: This handles string width formatting for irc variables
1401 * when [] is specified.
1402 */
1403 static void
expander_addition(buff,add,length,quote_em)1404 expander_addition(buff, add, length, quote_em)
1405 #ifndef USE_OLD_ALIAS_ALLOC
1406 u_char **buff,
1407 #else /* USE_OLD_ALIAS_ALLOC */
1408 u_char *buff,
1409 #endif
1410 /* USE_OLD_ALIAS_ALLOC */
1411 *add;
1412 int length;
1413 u_char *quote_em;
1414 {
1415 u_char format[40], buffer[BIG_BUFFER_SIZE], *ptr;
1416
1417 if (length)
1418 {
1419 snprintf(CP(format), sizeof(format)-1, "%%%d.%ds", -length, (length < 0 ? -length :
1420 length));
1421 format[sizeof(format)-1] = '\0';
1422 snprintf(CP(buffer), sizeof(buffer)-1, CP(format), add);
1423 buffer[sizeof(buffer)-1] = '\0';
1424 add = buffer;
1425 }
1426 if (quote_em)
1427 {
1428 ptr = double_quote(add, quote_em);
1429 #ifndef USE_OLD_ALIAS_ALLOC
1430 dma_strcat(buff, ptr);
1431 #else /* USE_OLD_ALIAS_ALLOC */
1432 strmcat(buff, ptr, BIG_BUFFER_SIZE);
1433 #endif /* USE_OLD_ALIAS_ALLOC */
1434 dma_Free(&ptr);
1435 }
1436 #ifndef USE_OLD_ALIAS_ALLOC
1437 else if (add && *add)
1438 dma_strcat(buff, add);
1439 #else /* USE_OLD_ALIAS_ALLOC */
1440 else if (buff)
1441 strmcat(buff, add, BIG_BUFFER_SIZE);
1442 #endif /* USE_OLD_ALIAS_ALLOC */
1443 }
1444
1445 /* MatchingBracket returns the next unescaped bracket of the given type */
1446 u_char *
MatchingBracket(string,left,right)1447 MatchingBracket(string, left, right)
1448 u_char *string;
1449 int left;
1450 int right;
1451 {
1452 int bracket_count = 1;
1453
1454 while (*string && bracket_count)
1455 {
1456 if (*string == (u_char) left)
1457 bracket_count++;
1458 else if (*string == (u_char) right)
1459 {
1460 if (!--bracket_count)
1461 return string;
1462 }
1463 else if (*string == '\\' && string[1])
1464 string++;
1465 string++;
1466 }
1467 return (u_char *) 0;
1468 }
1469
1470 /*
1471 * alias_special_char: Here we determin what to do with the character after
1472 * the $ in a line of text. The special characters are described more fulling
1473 * in the help/ALIAS file. But they are all handled here. Paremeters are the
1474 * name of the alias (if applicable) to prevent deadly recursion, a
1475 * destination buffer (that we are malloc_str*ing) to which things are appended,
1476 * a ptr to the string (the first character of which is the special
1477 * character, the args to the alias, and a character indication what
1478 * characters in the string should be quoted with a backslash). It returns a
1479 * pointer to the character right after the converted alias.
1480 The args_flag is set to 1 if any of the $n, $n-, $n-m, $-m, $*, or $() is used
1481 in the alias. Otherwise it is left unchanged.
1482 */
1483 /*ARGSUSED*/ static u_char *
alias_special_char(name,lbuf,ptr,args,quote_em,args_flag)1484 alias_special_char(name, lbuf, ptr, args, quote_em, args_flag)
1485 u_char *name;
1486 #ifndef USE_OLD_ALIAS_ALLOC
1487 u_char **lbuf;
1488 #else /* USE_OLD_ALIAS_ALLOC */
1489 u_char *lbuf;
1490 #endif /* USE_OLD_ALIAS_ALLOC */
1491 u_char *ptr;
1492 u_char *args;
1493 u_char *quote_em;
1494 int *args_flag;
1495 {
1496 u_char *tmp, c;
1497 int is_upper, is_lower, length;
1498
1499 length = 0;
1500 if ((c = *ptr) == LEFT_BRACKET)
1501 {
1502 ptr++;
1503 if ((tmp = my_index(ptr, RIGHT_BRACKET)) != NULL)
1504 {
1505 *(tmp++) = (u_char) 0;
1506 length = my_atoi(ptr);
1507 #ifdef USE_OLD_ALIAS_ALLOC
1508 /* XXX hack to avoid core dumps */
1509 if (length > ((BIG_BUFFER_SIZE * 5) / 3))
1510 length = ((BIG_BUFFER_SIZE * 5) / 3);
1511 #endif /* USE_OLD_ALIAS_ALLOC */
1512 ptr = tmp;
1513 c = *ptr;
1514 }
1515 else
1516 {
1517 put_error("Missing %c", RIGHT_BRACKET);
1518 return (ptr);
1519 }
1520 }
1521 tmp = ptr + 1;
1522 switch (c)
1523 {
1524 case LEFT_PAREN:
1525 {
1526 #ifndef USE_OLD_ALIAS_ALLOC
1527 u_char *sub_buffer = (u_char *) 0;
1528 #else /* USE_OLD_ALIAS_ALLOC */
1529 u_char sub_buffer[BIG_BUFFER_SIZE + 1];
1530 #endif /* USE_OLD_ALIAS_ALLOC */
1531
1532 if ((ptr = MatchingBracket(tmp, (int)LEFT_PAREN,
1533 (int)RIGHT_PAREN))
1534 || (ptr = my_index(tmp, RIGHT_PAREN)))
1535 *(ptr++) = (u_char) 0;
1536 tmp = expand_alias((u_char *) 0, tmp, args, args_flag, NULL);
1537 #ifndef USE_OLD_ALIAS_ALLOC
1538 dma_strcpy(&sub_buffer, empty_string);
1539 alias_special_char((u_char *) 0, &sub_buffer, tmp,
1540 #else /* USE_OLD_ALIAS_ALLOC */
1541 *sub_buffer = (u_char) 0;
1542 alias_special_char((u_char *) 0, sub_buffer, tmp,
1543 #endif /* USE_OLD_ALIAS_ALLOC */
1544 args, quote_em, args_flag);
1545 expander_addition(lbuf, sub_buffer, length, quote_em);
1546 #ifndef USE_OLD_ALIAS_ALLOC
1547 dma_Free(&sub_buffer);
1548 #endif /* not USE_OLD_ALIAS_ALLOC */
1549 dma_Free(&tmp);
1550 *args_flag = 1;
1551 }
1552 return (ptr);
1553 case '!':
1554 if ((ptr = my_index(tmp, '!')) != NULL)
1555 *(ptr++) = (u_char) 0;
1556 if ((tmp = do_history(tmp, empty_string)) != NULL)
1557 {
1558 expander_addition(lbuf, tmp, length, quote_em);
1559 dma_Free(&tmp);
1560 }
1561 return (ptr);
1562 case LEFT_BRACE:
1563 if ((ptr = my_index(tmp, RIGHT_BRACE)) != NULL)
1564 *(ptr++) = (u_char) 0;
1565 if ((tmp = parse_inline(tmp, args, args_flag)) != NULL)
1566 {
1567 expander_addition(lbuf, tmp, length, quote_em);
1568 dma_Free(&tmp);
1569 }
1570 return (ptr);
1571 case DOUBLE_QUOTE:
1572 if ((ptr = my_index(tmp, DOUBLE_QUOTE)) != NULL)
1573 *(ptr++) = (u_char) 0;
1574 alias_string = (u_char *) 0;
1575 /* XXX - the cast in the following is an ugly hack! */
1576 if (irc_io
1577 (tmp, (void (*)_((u_int, u_char *)))do_alias_string, use_input,
1578 1))
1579 {
1580 put_error("Illegal recursive edit");
1581 break;
1582 }
1583 expander_addition(lbuf, alias_string, length, quote_em);
1584 dma_Free(&alias_string);
1585 return (ptr);
1586 case '*':
1587 expander_addition(lbuf, args, length, quote_em);
1588 *args_flag = 1;
1589 return (ptr + 1);
1590 default:
1591 if (isdigit(c) || (c == '-') || c == '~')
1592 {
1593 *args_flag = 1;
1594 if (*ptr == '~')
1595 {
1596 is_lower = is_upper = LAST_ARG;
1597 ptr++;
1598 }
1599 else
1600 {
1601 is_lower = parse_number(&ptr);
1602 if (*ptr == '-')
1603 {
1604 ptr++;
1605 is_upper = parse_number(&ptr);
1606 }
1607 else
1608 is_upper = is_lower;
1609 }
1610 expander_addition(lbuf, arg_number(is_lower, is_upper,
1611 args), length, quote_em);
1612 return (ptr ? ptr : empty_string);
1613 }
1614 else
1615 {
1616 u_char *rest, c2 = (u_char) 0;
1617
1618 /*
1619 * Why use ptr+1? Cause try to maintain backward compatability
1620 * can be a pain in the butt. Basically, we don't want any of
1621 * the illegal characters in the alias, except that things like
1622 * $* and $, were around first, so they must remain legal. So
1623 * we skip the first char after the $. Does this make sense?
1624 */
1625 /* special case for $ */
1626 if (*ptr == '$')
1627 {
1628 rest = ptr + 1;
1629 c2 = *rest;
1630 *rest = (u_char) 0;
1631 }
1632 else if ((rest = sindex(ptr + 1, alias_illegals)) != NULL)
1633 {
1634 if (isalpha(*ptr) || *ptr == '_')
1635 while ((*rest == LEFT_BRACKET ||
1636 *rest == LEFT_PAREN) &&
1637 (tmp = MatchingBracket(rest + 1,
1638 (int)*rest,
1639 (int)(*rest ==
1640 LEFT_BRACKET) ?
1641 RIGHT_BRACKET :
1642 RIGHT_PAREN)))
1643 rest = tmp + 1;
1644 c2 = *rest;
1645 *rest = (u_char) 0;
1646 }
1647 if ((tmp = parse_inline(ptr, args, args_flag)) != NULL)
1648 {
1649 expander_addition(lbuf, tmp, length, quote_em);
1650 dma_Free(&tmp);
1651 }
1652 if (rest)
1653 *rest = c2;
1654 return (rest);
1655 }
1656 }
1657 return NULL;
1658 }
1659
1660 /*
1661 * expand_alias: Expands inline variables in the given string and returns the
1662 * expanded string in a new string which is malloced by expand_alias().
1663 *
1664 * Also unescapes anything that was quoted with a backslash
1665 *
1666 * Behaviour is modified by the following:
1667 * Anything between brackets (...) {...} is left unmodified.
1668 * If more_text is supplied, the text is broken up at
1669 * semi-colons and returned one at a time. The unprocessed
1670 * portion is written back into more_text.
1671 * Backslash escapes are unescaped.
1672 */
1673
1674 u_char *
expand_alias(name,string,args,args_flag,more_text)1675 expand_alias(name, string, args, args_flag, more_text)
1676 u_char *name, *string, *args;
1677 int *args_flag;
1678 u_char **more_text;
1679 {
1680 #ifndef USE_OLD_ALIAS_ALLOC
1681 u_char *lbuf = (u_char *) 0,
1682 #else /* USE_OLD_ALIAS_ALLOC */
1683 u_char lbuf[BIG_BUFFER_SIZE + 1],
1684 #endif
1685 /* USE_OLD_ALIAS_ALLOC */
1686 *ptr, *stuff = (u_char *) 0, *free_stuff;
1687 u_char *quote_em, *quote_str = (u_char *) 0;
1688 u_char ch;
1689 int quote_cnt = 0;
1690 int is_quote = 0;
1691 #ifndef USE_OLD_ALIAS_ALLOC
1692 void (*str_cat) _((u_char **, u_char *));
1693 #else /* USE_OLD_ALIAS_ALLOC */
1694 int (*str_cat) _((u_char *, u_char *, size_t));
1695 #endif /* USE_OLD_ALIAS_ALLOC */
1696
1697 if (*string == '@' && more_text)
1698 {
1699 #ifndef USE_OLD_ALIAS_ALLOC
1700 str_cat = dma_strcat;
1701 #else /* USE_OLD_ALIAS_ALLOC */
1702 str_cat = strmcat;
1703 #endif /* USE_OLD_ALIAS_ALLOC */
1704 *args_flag = 1; /* Stop the @ command from auto appending */
1705 }
1706 else
1707 #ifndef USE_OLD_ALIAS_ALLOC
1708 str_cat = dma_strcat_ue;
1709 #else /* USE_OLD_ALIAS_ALLOC */
1710 str_cat = strmcat_ue;
1711 #endif /* USE_OLD_ALIAS_ALLOC */
1712 dma_strcpy(&stuff, string);
1713 free_stuff = stuff;
1714 #ifndef USE_OLD_ALIAS_ALLOC
1715 dma_strcpy(&lbuf, empty_string);
1716 #else /* USE_OLD_ALIAS_ALLOC */
1717 *lbuf = (u_char) 0;
1718 #endif /* USE_OLD_ALIAS_ALLOC */
1719 eval_args = 1;
1720 ptr = stuff;
1721 if (more_text)
1722 *more_text = NULL;
1723 while (ptr && *ptr)
1724 {
1725 if (is_quote)
1726 {
1727 is_quote = 0;
1728 ++ptr;
1729 continue;
1730 }
1731 switch (*ptr)
1732 {
1733 case '$':
1734 /*
1735 * The test here ensures that if we are in the expression
1736 * evaluation command, we don't expand $. In this case we
1737 * are only coming here to do command separation at ';'s.
1738 * If more_text is not defined, and the first character is
1739 * '@', we have come here from [] in an expression.
1740 */
1741 if (more_text && *string == '@')
1742 {
1743 ptr++;
1744 break;
1745 }
1746 *(ptr++) = (u_char) 0;
1747 #ifndef USE_OLD_ALIAS_ALLOC
1748 (*str_cat) (&lbuf, stuff);
1749 #else /* USE_OLD_ALIAS_ALLOC */
1750 (*str_cat) (lbuf, stuff, BIG_BUFFER_SIZE);
1751 #endif /* USE_OLD_ALIAS_ALLOC */
1752 while (*ptr == '^')
1753 {
1754 ptr++;
1755 if (quote_str)
1756 quote_str = (u_char *)
1757 dma_ReAlloc(quote_str,
1758 sizeof(u_char) * (quote_cnt + 2));
1759 else
1760 quote_str = (u_char *)
1761 dma_Malloc(sizeof(u_char) * (quote_cnt + 2));
1762 quote_str[quote_cnt++] = *(ptr++);
1763 quote_str[quote_cnt] = (u_char) 0;
1764 }
1765 quote_em = quote_str;
1766 #ifndef USE_OLD_ALIAS_ALLOC
1767 stuff = alias_special_char(name, &lbuf, ptr, args,
1768 #else /* USE_OLD_ALIAS_ALLOC */
1769 stuff = alias_special_char(name, lbuf, ptr, args,
1770 #endif /* USE_OLD_ALIAS_ALLOC */
1771 quote_em, args_flag);
1772 if (stuff)
1773 dma_Free("e_str);
1774 quote_cnt = 0;
1775 ptr = stuff;
1776 break;
1777 case ';':
1778 if (!more_text)
1779 {
1780 ptr++;
1781 break;
1782 }
1783 *more_text = string + (ptr - free_stuff) + 1;
1784 *ptr = '\0'; /* To terminate the loop */
1785 break;
1786 case LEFT_PAREN:
1787 case LEFT_BRACE:
1788 ch = *ptr;
1789 *ptr = '\0';
1790 #ifndef USE_OLD_ALIAS_ALLOC
1791 (*str_cat) (&lbuf, stuff);
1792 #else /* USE_OLD_ALIAS_ALLOC */
1793 (*str_cat) (lbuf, stuff, BIG_BUFFER_SIZE);
1794 #endif /* USE_OLD_ALIAS_ALLOC */
1795 stuff = ptr;
1796 *args_flag = 1;
1797 if (!(ptr = MatchingBracket(stuff + 1, (int)ch,
1798 (int)(ch == LEFT_PAREN) ?
1799 RIGHT_PAREN : RIGHT_BRACE)))
1800 {
1801 put_error("Unmatched %c", ch);
1802 ptr = stuff + my_strlen(stuff + 1) + 1;
1803 }
1804 else
1805 ptr++;
1806 *stuff = ch;
1807 ch = *ptr;
1808 *ptr = '\0';
1809 #ifndef USE_OLD_ALIAS_ALLOC
1810 dma_strcat(&lbuf, stuff);
1811 #else /* USE_OLD_ALIAS_ALLOC */
1812 strmcat(lbuf, stuff, BIG_BUFFER_SIZE);
1813 #endif /* USE_OLD_ALIAS_ALLOC */
1814 stuff = ptr;
1815 *ptr = ch;
1816 break;
1817 case '\\':
1818 is_quote = 1;
1819 ptr++;
1820 break;
1821 default:
1822 ptr++;
1823 break;
1824 }
1825 }
1826 if (stuff)
1827 #ifndef USE_OLD_ALIAS_ALLOC
1828 (*str_cat) (&lbuf, stuff);
1829 #else /* USE_OLD_ALIAS_ALLOC */
1830 (*str_cat) (lbuf, stuff, BIG_BUFFER_SIZE);
1831 #endif /* USE_OLD_ALIAS_ALLOC */
1832 ptr = (u_char *) 0;
1833 dma_Free(&free_stuff);
1834 #ifndef USE_OLD_ALIAS_ALLOC
1835 ptr = lbuf;
1836 #else /* USE_OLD_ALIAS_ALLOC */
1837 dma_strcpy(&ptr, lbuf);
1838 #endif /* USE_OLD_ALIAS_ALLOC */
1839 if (get_int_var(DEBUG_VAR) & DEBUG_EXPANSIONS)
1840 put_error("Expanded [%s] to [%s]", string, ptr);
1841 return (ptr);
1842 }
1843
1844 /*
1845 * get_alias: returns the alias matching 'name' as the function value. 'args'
1846 * are expanded as needed, etc. If no matching alias is found, null is
1847 * returned, cnt is 0, and full_name is null. If one matching alias is
1848 * found, it is retuned, with cnt set to 1 and full_name set to the full name
1849 * of the alias. If more than 1 match are found, null is returned, cnt is
1850 * set to the number of matches, and fullname is null. NOTE: get_alias()
1851 * mallocs the space for the full_name, but returns the actual value of the
1852 * alias if found!
1853 */
1854 u_char *
get_alias(type,name,cnt,full_name)1855 get_alias(type, name, cnt, full_name)
1856 int type;
1857 u_char *name, **full_name;
1858 int *cnt;
1859 {
1860 Alias *tmp;
1861
1862 *full_name = (u_char *) 0;
1863 if ((name == (u_char *) 0) || (*name == (u_char) 0))
1864 {
1865 *cnt = 0;
1866 return ((u_char *) 0);
1867 }
1868 if ((tmp = find_alias(&(alias_list[type]), name, 0, cnt)) != NULL)
1869 {
1870 if (*cnt < 2)
1871 {
1872 dma_strcpy(full_name, tmp->name);
1873 return (tmp->stuff);
1874 }
1875 }
1876 return ((u_char *) 0);
1877 }
1878
1879 /*
1880 * match_alias: this returns a list of alias names that match the given name.
1881 * This is used for command completion etc. Note that the returned array is
1882 * malloced in this routine. Returns null if no matches are found
1883 */
1884 u_char **
match_alias(name,cnt,type)1885 match_alias(name, cnt, type)
1886 u_char *name;
1887 int *cnt;
1888 int type;
1889 {
1890 Alias *tmp;
1891 u_char **matches = (u_char **) 0;
1892 int matches_size = 5;
1893 size_t len;
1894 u_char *last_match = (u_char *) 0;
1895 u_char *dot;
1896
1897 len = my_strlen(name);
1898 *cnt = 0;
1899 matches = (u_char **) dma_Malloc(sizeof(u_char *) * matches_size);
1900 for (tmp = alias_list[type]; tmp; tmp = tmp->next)
1901 {
1902 if (my_strncmp(name, tmp->name, len) == 0)
1903 {
1904 if ((dot = my_index(tmp->name + len, '.')) != NULL)
1905 {
1906 if (type == COMMAND_ALIAS)
1907 continue;
1908 else
1909 {
1910 *dot = '\0';
1911 if (last_match && !my_strcmp(last_match, tmp->name))
1912 {
1913 *dot = '.';
1914 continue;
1915 }
1916 }
1917 }
1918 matches[*cnt] = (u_char *) 0;
1919 dma_strcpy(&(matches[*cnt]), tmp->name);
1920 last_match = matches[*cnt];
1921 if (dot)
1922 *dot = '.';
1923 if (++(*cnt) == matches_size)
1924 {
1925 matches_size += 5;
1926 matches =
1927 (u_char **) dma_ReAlloc(UP(matches),
1928 sizeof(u_char *) * matches_size);
1929 }
1930 }
1931 else if (*cnt)
1932 break;
1933 }
1934 if (*cnt)
1935 {
1936 matches =
1937 (u_char **) dma_ReAlloc(UP(matches),
1938 sizeof(u_char *) * (*cnt + 1));
1939 matches[*cnt] = (u_char *) 0;
1940 }
1941 else
1942 dma_Free(&matches);
1943 return (matches);
1944 }
1945
1946 /* delete_alias: The alias name is removed from the alias list. */
1947 void
delete_alias(type,name)1948 delete_alias(type, name)
1949 int type;
1950 u_char *name;
1951 {
1952 Alias *tmp;
1953
1954 upper(name);
1955 if ((tmp = find_alias(&(alias_list[type]), name, 1, (int *)NULL)) != NULL)
1956 {
1957 dma_Free(&(tmp->name));
1958 dma_Free(&(tmp->stuff));
1959 dma_Free(&tmp);
1960 if (type == COMMAND_ALIAS)
1961 put_info("Alias %s removed", name);
1962 else
1963 put_info("Assign %s removed", name);
1964 }
1965 else
1966 put_info("No such alias: %s", name);
1967 }
1968
1969 /*
1970 * list_aliases: Lists all aliases matching 'name'. If name is null, all
1971 * aliases are listed
1972 */
1973 void
list_aliases(type,name)1974 list_aliases(type, name)
1975 int type;
1976 u_char *name;
1977 {
1978 Alias *tmp;
1979 size_t len;
1980 int lastlog_level;
1981 size_t DotLoc, LastDotLoc = 0;
1982 u_char *LastStructName = NULL;
1983 u_char *s;
1984
1985 lastlog_level = message_from_level(LOG_CRAP);
1986 if (type == COMMAND_ALIAS)
1987 put_info("Aliases:");
1988 else
1989 put_info("Assigns:");
1990 if (name)
1991 {
1992 upper(name);
1993 len = my_strlen(name);
1994 }
1995 else
1996 len = 0;
1997 for (tmp = alias_list[type]; tmp; tmp = tmp->next)
1998 {
1999 if (!name || !my_strncmp(tmp->name, name, len))
2000 {
2001 s = my_index(tmp->name + len, '.');
2002 if (!s)
2003 put_info("\t%s\t%s", tmp->name, tmp->stuff);
2004 else
2005 {
2006 DotLoc = s - tmp->name;
2007 if (!LastStructName || (DotLoc != LastDotLoc)
2008 || my_strncmp(tmp->name, LastStructName, DotLoc))
2009 {
2010 put_info("\t%*.*s\t<Structure>", DotLoc, DotLoc, tmp->name);
2011 LastStructName = tmp->name;
2012 LastDotLoc = DotLoc;
2013 }
2014 }
2015 }
2016 }
2017 (void)message_from_level(lastlog_level);
2018 }
2019
2020 /*
2021 * mark_alias: sets the mark field of the given alias to 'flag', and returns
2022 * the previous value of the mark. If the name is not found, -1 is returned.
2023 * This is used to prevent recursive aliases by marking and unmarking
2024 * aliases, and not reusing an alias that has previously been marked. I'll
2025 * explain later
2026 */
2027 int
mark_alias(name,flag)2028 mark_alias(name, flag)
2029 u_char *name;
2030 int flag;
2031 {
2032 int old_mark;
2033 Alias *tmp;
2034 int match;
2035
2036 if ((tmp = find_alias(&(alias_list[COMMAND_ALIAS]), name, 0, &match))
2037 != NULL)
2038 {
2039 if (match < 2)
2040 {
2041 old_mark = tmp->mark;
2042 /* New handling of recursion */
2043 if (flag)
2044 {
2045 int i;
2046 /* Count recursion */
2047
2048 tmp->mark = tmp->mark + flag;
2049 if ((i = get_int_var(MAX_RECURSIONS_VAR)) > 1)
2050 {
2051 if (tmp->mark > i)
2052 {
2053 tmp->mark = 0;
2054 return (1); /* MAX exceeded. */
2055 }
2056 else
2057 return (0);
2058 /* In recursion but it's ok */
2059 }
2060 else
2061 {
2062 if (tmp->mark > 1)
2063 {
2064 tmp->mark = 0;
2065 return (1);
2066 /* max of 1 here.. exceeded */
2067 }
2068 else
2069 return (0);
2070 /* In recursion but it's ok */
2071 }
2072 }
2073 else
2074 /* Not in recursion at all */
2075 {
2076 tmp->mark = 0;
2077 return (old_mark);
2078 /* This one gets ignored anyway */
2079 }
2080 }
2081 }
2082 return (-1);
2083 }
2084
2085 /*
2086 * execute_alias: After an alias has been identified and expanded, it is sent
2087 * here for proper execution. This routine mainly prevents recursive
2088 * aliasing. The name is the full name of the alias, and the alias is
2089 * already expanded alias (both of these parameters are returned by
2090 * get_alias())
2091 */
2092 void
execute_alias(alias_name,ealias,args)2093 execute_alias(alias_name, ealias, args)
2094 u_char *alias_name, *ealias, *args;
2095 {
2096 if (mark_alias(alias_name, 1))
2097 put_error("Maximum recursion count exceeded in: %s", alias_name);
2098 else
2099 {
2100 parse_line(alias_name, ealias, args, 0, 1, 0);
2101 mark_alias(alias_name, 0);
2102 }
2103 }
2104
2105 /*
2106 * save_aliases: This will write all of the aliases to the FILE pointer fp in
2107 * such a way that they can be read back in using LOAD or the -l switch
2108 */
2109 void
save_aliases(fp,do_all)2110 save_aliases(fp, do_all)
2111 FILE *fp;
2112 int do_all;
2113 {
2114 Alias *tmp;
2115
2116 for (tmp = alias_list[VAR_ALIAS]; tmp; tmp = tmp->next)
2117 if (!tmp->global ||do_all)
2118 fprintf(fp, "ASSIGN %s %s\n", tmp->name, tmp->stuff);
2119 for (tmp = alias_list[COMMAND_ALIAS]; tmp; tmp = tmp->next)
2120 if (!tmp->global ||do_all)
2121 fprintf(fp, "ALIAS %s %s\n", tmp->name, tmp->stuff);
2122 }
2123
2124 /* The Built-In Alias expando functions */
2125 static u_char *
alias_line()2126 alias_line()
2127 {
2128 return (get_input());
2129 }
2130
2131 static u_char *
alias_buffer()2132 alias_buffer()
2133 {
2134 return cut_buffer;
2135 }
2136
2137 static u_char *
alias_time()2138 alias_time()
2139 {
2140 static u_char timestr[32];
2141
2142 memset(timestr, 0, sizeof(timestr));
2143 return update_clock(timestr, sizeof(timestr)-1, GET_TIME);
2144 }
2145
2146 static u_char *
alias_dollar()2147 alias_dollar()
2148 {
2149 return (UP("$"));
2150 }
2151
2152 static u_char *
alias_detected()2153 alias_detected()
2154 {
2155 return (last_notify_nick);
2156 }
2157
2158 static u_char *
alias_nick()2159 alias_nick()
2160 {
2161 return (get_server_nickname(curr_scr_win->server));
2162 }
2163
2164 static u_char *
alias_away()2165 alias_away()
2166 {
2167 return ((from_server >= 0) ? server_list[from_server].away : empty_string);
2168 }
2169
2170 static u_char *
alias_sent_nick()2171 alias_sent_nick()
2172 {
2173 return (sent_nick) ? sent_nick : empty_string;
2174 }
2175
2176 static u_char *
alias_recv_nick()2177 alias_recv_nick()
2178 {
2179 return (recv_nick) ? recv_nick : empty_string;
2180 }
2181
2182 static u_char *
alias_msg_body()2183 alias_msg_body()
2184 {
2185 return (sent_body) ? sent_body : empty_string;
2186 }
2187
2188 static u_char *
alias_joined_nick()2189 alias_joined_nick()
2190 {
2191 return (joined_nick) ? joined_nick : empty_string;
2192 }
2193
2194 static u_char *
alias_public_nick()2195 alias_public_nick()
2196 {
2197 return (public_nick) ? public_nick : empty_string;
2198 }
2199
2200 static u_char *
alias_channel()2201 alias_channel()
2202 {
2203 u_char *tmp;
2204
2205 return ((tmp = get_channel_by_refnum(0)) ? tmp : zero);
2206 }
2207
2208 static u_char *
alias_server()2209 alias_server()
2210 {
2211 if (parsing_server_index != -1)
2212 return get_server_itsname(parsing_server_index);
2213 if (get_window_server(0) != -1)
2214 return get_server_itsname(get_window_server(0));
2215 return empty_string;
2216 }
2217
2218 static u_char *
alias_query_nick()2219 alias_query_nick()
2220 {
2221 u_char *tmp;
2222
2223 return ((tmp = query_nick())? tmp : empty_string);
2224 }
2225
2226 static u_char *
alias_target()2227 alias_target()
2228 {
2229 u_char *tmp;
2230
2231 return ((tmp = get_target_by_refnum(0)) ? tmp : empty_string);
2232 }
2233
2234 static u_char *
alias_invite()2235 alias_invite()
2236 {
2237 return ((invite_channel) ? invite_channel : empty_string);
2238 }
2239
2240 static u_char *
alias_cmdchar()2241 alias_cmdchar()
2242 {
2243 static u_char thing[2];
2244 u_char *cmdchars;
2245
2246 if ((cmdchars = get_string_var(CMDCHARS_VAR)) == (u_char *) 0)
2247 cmdchars = UP(DEFAULT_CMDCHARS);
2248 thing[0] = cmdchars[0];
2249 thing[1] = (u_char) 0;
2250 return (thing);
2251 }
2252
2253 static u_char *
alias_oper()2254 alias_oper()
2255 {
2256 return get_server_operator(from_server) ?
2257 get_string_var(STATUS_OPER_VAR) : empty_string;
2258 }
2259
2260 static u_char *
alias_chanop()2261 alias_chanop()
2262 {
2263 u_char *tmp;
2264
2265 tmp = get_channel_by_refnum(0);
2266 if (tmp && is_chanop(tmp, get_server_nickname(from_server)))
2267 return UP("@");
2268 return empty_string;
2269 }
2270
2271 static u_char *
alias_modes()2272 alias_modes()
2273 {
2274 u_char *tmp;
2275
2276 tmp = get_channel_by_refnum(0);
2277 if (tmp)
2278 return get_channel_mode(tmp, from_server);
2279 else
2280 return empty_string;
2281 }
2282
2283 static u_char *
alias_version()2284 alias_version()
2285 {
2286 static u_char tmp[64];
2287
2288 snprintf(tmp, sizeof(tmp)-1, "Ninja IRC v%s", irc_version);
2289 tmp[sizeof(tmp)-1] = '\0';
2290 return tmp;
2291 }
2292
2293 static u_char *
alias_currdir()2294 alias_currdir()
2295 {
2296 static u_char dirbuf[1024];
2297
2298 getcwd(CP(dirbuf), sizeof(dirbuf)-1);
2299 dirbuf[sizeof(dirbuf)-1] = '\0';
2300 return dirbuf;
2301 }
2302
2303 static u_char *
alias_current_numeric()2304 alias_current_numeric()
2305 {
2306 static u_char number[8];
2307
2308 snprintf(CP(number), sizeof(number)-1, "%03d", -current_numeric);
2309 number[sizeof(number)-1] = '\0';
2310 return number;
2311 }
2312
2313 static u_char *
alias_server_version()2314 alias_server_version()
2315 {
2316 if (curr_scr_win->server < 0 || curr_scr_win->server >= number_of_servers)
2317 return empty_string;
2318 return server_list[curr_scr_win->server].version_string;
2319 }
2320
2321 /* the folowing alias_*() functions added by jduck */
2322 static u_char *
alias_hostname()2323 alias_hostname()
2324 {
2325 return (hostname);
2326 }
2327
2328 /*
2329 * alias: the /ALIAS command. Calls the correct alias function depending on
2330 * the args
2331 */
2332 void
alias(command,args,subargs)2333 alias(command, args, subargs)
2334 u_char *command, *args, *subargs;
2335 {
2336 u_char *name, *rest;
2337 int type;
2338 u_char *ArrayIndex;
2339 u_char *EndIndex;
2340
2341 type = *command - 48; /*
2342 * A trick! Yes, well, what the hell. Note
2343 * the the command part of ALIAS is "0" and
2344 * the command part of ASSIGN is "1" in the
2345 * command array list
2346 */
2347 if ((name = next_arg(args, &rest)) != NULL)
2348 {
2349 while ((ArrayIndex = my_index(name, '[')) != NULL)
2350 {
2351 *ArrayIndex++ = '.';
2352 if ((EndIndex = MatchingBracket(ArrayIndex,
2353 (int)LEFT_BRACKET,
2354 (int)RIGHT_BRACKET)) != NULL)
2355 {
2356 *EndIndex++ = '\0';
2357 my_strcat(name, EndIndex);
2358 }
2359 else
2360 break;
2361 }
2362 if (*rest)
2363 {
2364 if (*rest == LEFT_BRACE)
2365 {
2366 u_char *ptr;
2367
2368 ptr = MatchingBracket(++rest,
2369 (int)LEFT_BRACE, (int)RIGHT_BRACE);
2370 if (!ptr)
2371 put_error("Unmatched brace in ALIAS or ASSIGN");
2372 else if (ptr[1])
2373 {
2374 put_error("Junk after closing brace in ALIAS or ASSIGN");
2375 }
2376 else
2377 {
2378 *ptr = '\0';
2379 add_alias(type, name, rest);
2380 }
2381 }
2382 else
2383 add_alias(type, name, rest);
2384 }
2385 else
2386 {
2387 if (*name == '-')
2388 {
2389 if (*(name + 1))
2390 delete_alias(type, name + 1);
2391 else
2392 put_info("You must specify an alias to be removed");
2393 }
2394 else
2395 list_aliases(type, name);
2396 }
2397 }
2398 else
2399 list_aliases(type, (u_char *) 0);
2400 }
2401
2402 u_char *
function_left(input)2403 function_left(input)
2404 u_char *input;
2405 {
2406 u_char *result = (u_char *) 0;
2407 u_char *count;
2408 int cvalue;
2409
2410 count = next_arg(input, &input);
2411 if (count)
2412 cvalue = my_atoi(count);
2413 else
2414 cvalue = 0;
2415 if ((int)my_strlen(input) > cvalue)
2416 input[cvalue] = '\0';
2417 dma_strcpy(&result, input);
2418 return (result);
2419 }
2420
2421 u_char *
function_right(input)2422 function_right(input)
2423 u_char *input;
2424 {
2425 u_char *result = (u_char *) 0;
2426 u_char *count;
2427 int cvalue;
2428 int len;
2429
2430 count = next_arg(input, &input);
2431 if (count)
2432 cvalue = my_atoi(count);
2433 else
2434 cvalue = 0;
2435 if ((len = (int)my_strlen(input)) > cvalue)
2436 input += len - cvalue;
2437 dma_strcpy(&result, input);
2438 return (result);
2439 }
2440
2441 u_char *
function_mid(input)2442 function_mid(input)
2443 u_char *input;
2444 {
2445 u_char *result = (u_char *) 0;
2446 u_char *mid_index;
2447 int ivalue;
2448 u_char *count;
2449 int cvalue;
2450
2451 mid_index = next_arg(input, &input);
2452 if (mid_index)
2453 ivalue = my_atoi(mid_index);
2454 else
2455 ivalue = 0;
2456 count = next_arg(input, &input);
2457 if (count)
2458 cvalue = my_atoi(count);
2459 else
2460 cvalue = 0;
2461 if ((int)my_strlen(input) > ivalue)
2462 input += ivalue;
2463 else
2464 *input = '\0';
2465 if ((int)my_strlen(input) > cvalue)
2466 input[cvalue] = '\0';
2467 dma_strcpy(&result, input);
2468 return (result);
2469 }
2470
2471 /* patch from Sarayan to make $rand() better */
2472
2473 #define RAND_A 16807L
2474 #define RAND_M 2147483647L
2475 #define RAND_Q 127773L
2476 #define RAND_R 2836L
2477
2478 static long
randm(l)2479 randm(l)
2480 long l;
2481 {
2482 static u_long z = 0;
2483 long t;
2484
2485 #ifndef __MSDOS__
2486 if (!z)
2487 z = (u_long) getuid();
2488 #endif /* __MSDOS__ */
2489 if (!l)
2490 {
2491 t = RAND_A * (z % RAND_Q) - RAND_R * (z / RAND_Q);
2492 if (t > 0)
2493 z = t;
2494 else
2495 z = t + RAND_M;
2496 return (z >> 8) | ((z & 255) << 23);
2497 }
2498 else
2499 {
2500 if (l < 0)
2501 #ifdef __MSDOS__
2502 z = 0;
2503 #else
2504 z = (u_long) getuid();
2505 #endif /* __MSDOS__ */
2506 else
2507 z = l;
2508 return 0;
2509 }
2510 }
2511
2512 u_char *
function_rand(input)2513 function_rand(input)
2514 u_char *input;
2515 {
2516 u_char *result = (u_char *) 0;
2517 u_char tmp[40];
2518 long tempin;
2519
2520 #ifdef _Windows
2521 sprintf(CP(tmp), "%ld", random(my_atol(input)));
2522 #else
2523 sprintf(CP(tmp), "%ld",
2524 (tempin = my_atol(input)) ? randm(0L) % tempin : 0);
2525 #endif /* _Windows */
2526 dma_strcpy(&result, tmp);
2527 return (result);
2528 }
2529
2530 u_char *
function_srand(input)2531 function_srand(input)
2532 u_char *input;
2533 {
2534 u_char *result = (u_char *) 0;
2535
2536 if (input && *input)
2537 (void)randm(my_atol(input));
2538 else
2539 (void)randm((long)time(NULL));
2540 dma_strcpy(&result, empty_string);
2541 return (result);
2542 }
2543
function_time(input)2544 /*ARGSUSED*/ u_char * function_time(input)
2545 u_char *
2546 input;
2547 {
2548 u_char *result = (u_char *) 0;
2549 time_t ltime;
2550 u_char tmp[40];
2551
2552 (void)time(<ime);
2553 sprintf(CP(tmp), "%ld", (long)ltime);
2554 dma_strcpy(&result, tmp);
2555 return (result);
2556 }
2557
2558 u_char *
function_stime(input)2559 function_stime(input)
2560 u_char *input;
2561 {
2562 u_char *result = (u_char *) 0;
2563 time_t ltime;
2564
2565 ltime = my_atol(input);
2566 dma_strcpy(&result, UP(ctime(<ime)));
2567 result[my_strlen(result) - 1] = (u_char) 0;
2568 return (result);
2569 }
2570
2571 u_char *
function_index(input)2572 function_index(input)
2573 u_char *input;
2574 {
2575 u_char *result = (u_char *) 0;
2576 u_char *schars;
2577 u_char *iloc;
2578 int ival;
2579 u_char tmp[40];
2580
2581 schars = next_arg(input, &input);
2582 iloc = (schars) ? sindex(input, schars) : NULL;
2583 ival = (iloc) ? iloc - input : -1;
2584 sprintf(CP(tmp), "%d", ival);
2585 dma_strcpy(&result, tmp);
2586 return (result);
2587 }
2588
2589 u_char *
function_rindex(input)2590 function_rindex(input)
2591 u_char *input;
2592 {
2593 u_char *result = (u_char *) 0;
2594 u_char *schars;
2595 u_char *iloc;
2596 int ival;
2597 u_char tmp[40];
2598
2599 schars = next_arg(input, &input);
2600 iloc = (schars) ? srindex(input, schars) : NULL;
2601 ival = (iloc) ? iloc - input : -1;
2602 sprintf(CP(tmp), "%d", ival);
2603 dma_strcpy(&result, tmp);
2604 return (result);
2605 }
2606
2607 u_char *
function_match(input)2608 function_match(input)
2609 u_char *input;
2610 {
2611 u_char *result = (u_char *) 0;
2612 u_char *pattern;
2613 u_char *word;
2614 int current_match;
2615 int best_match = 0;
2616 int match = 0;
2617 int match_index = 0;
2618 u_char tmp[40];
2619
2620 if ((pattern = next_arg(input, &input)) != NULL)
2621 {
2622 while ((word = next_arg(input, &input)) != NULL)
2623 {
2624 match_index++;
2625 if ((current_match = wild_match(pattern, word)) > best_match)
2626 {
2627 match = match_index;
2628 best_match = current_match;
2629 }
2630 }
2631 }
2632 sprintf(CP(tmp), "%d", match);
2633 dma_strcpy(&result, tmp);
2634 return (result);
2635 }
2636
2637 u_char *
function_rmatch(input)2638 function_rmatch(input)
2639 u_char *input;
2640 {
2641 u_char *result = (u_char *) 0;
2642 u_char *pattern;
2643 u_char *word;
2644 int current_match;
2645 int best_match = 0;
2646 int match = 0;
2647 int rmatch_index = 0;
2648 u_char tmp[40];
2649
2650 if ((pattern = next_arg(input, &input)) != NULL)
2651 {
2652 while ((word = next_arg(input, &input)) != NULL)
2653 {
2654 rmatch_index++;
2655 if ((current_match = wild_match(word, pattern)) > best_match)
2656 {
2657 match = rmatch_index;
2658 best_match = current_match;
2659 }
2660 }
2661 }
2662 sprintf(CP(tmp), "%d", match);
2663 dma_strcpy(&result, tmp);
2664 return (result);
2665 }
2666
2667 /*ARGSUSED */
2668 u_char *
function_userhost(input)2669 function_userhost(input)
2670 u_char *input;
2671 {
2672 u_char *result = (u_char *) 0;
2673
2674 dma_strcpy(&result, FromUserHost ? FromUserHost : empty_string);
2675 return result;
2676 }
2677
2678 u_char *
function_strip(input)2679 function_strip(input)
2680 u_char *input;
2681 {
2682 u_char tmpbuf[128], *result;
2683 u_char *retval = (u_char *) 0;
2684 u_char *chars;
2685 u_char *cp, *dp;
2686 size_t len = 0;
2687
2688 if ((chars = next_arg(input, &input)) && input)
2689 {
2690 len = my_strlen(input);
2691 if (len > 127)
2692 result = (u_char *) dma_Malloc(len + 1);
2693 else
2694 result = tmpbuf;
2695
2696 for (cp = input, dp = result; *cp; cp++)
2697 {
2698 if (!my_index(chars, *cp))
2699 *dp++ = *cp;
2700 }
2701 *dp = '\0';
2702 }
2703 dma_strcpy(&retval, result);
2704 if (len > 127)
2705 dma_Free(&result); /* we could use this copy, but it might be extra-long */
2706 return (retval);
2707 }
2708
2709 u_char *
function_encode(input)2710 function_encode(input)
2711 u_char *input;
2712 {
2713 u_char *result;
2714 u_char *c;
2715 int i = 0;
2716
2717 result = (u_char *) dma_Malloc(my_strlen(input) * 2 + 1);
2718 for (c = input; *c; c++)
2719 {
2720 result[i++] = (*c >> 4) + 0x41;
2721 result[i++] = (*c & 0x0f) + 0x41;
2722 }
2723 result[i] = '\0';
2724 return (result);
2725 }
2726
2727 u_char *
function_decode(input)2728 function_decode(input)
2729 u_char *input;
2730 {
2731 u_char *result;
2732 u_char *c;
2733 u_char d, e;
2734 int i = 0;
2735
2736 c = input;
2737 result = (u_char *) dma_Malloc(my_strlen(input) / 2 + 2);
2738 while ((d = *c) && (e = *(c + 1)))
2739 {
2740 result[i] = ((d - 0x41) << 4) | (e - 0x41);
2741 c += 2;
2742 i++;
2743 }
2744 result[i] = '\0';
2745 return (result);
2746 }
2747
2748 u_char *
function_ischannel(input)2749 function_ischannel(input)
2750 u_char *input;
2751 {
2752 u_char *result = (u_char *) 0;
2753
2754 dma_strcpy(&result, is_channel(input) ? one : zero);
2755 return (result);
2756 }
2757
2758 u_char *
function_ischanop(input)2759 function_ischanop(input)
2760 u_char *input;
2761 {
2762 u_char *result = (u_char *) 0;
2763 u_char *nick;
2764 u_char *channel = NULL;
2765
2766 if (!(nick = next_arg(input, &channel)))
2767 dma_strcpy(&result, zero);
2768 else
2769 dma_strcpy(&result, is_chanop(channel, nick) ? one : zero);
2770 return result;
2771 }
2772
2773 #ifdef HAVE_CRYPT
2774 u_char *
function_crypt(input)2775 function_crypt(input)
2776 u_char *input;
2777 {
2778 u_char *result = (u_char *) 0;
2779 u_char *salt;
2780 u_char *key = NULL;
2781
2782 if (!(salt = next_arg(input, &key)))
2783 dma_strcpy(&result, zero);
2784 else
2785 dma_strcpy(&result, UP(crypt(key, salt)));
2786 return (result);
2787 }
2788 #endif /* HAVE_CRYPT */
2789
2790 u_char *
function_hasvoice(input)2791 function_hasvoice(input)
2792 u_char *input;
2793 {
2794 u_char *result = (u_char *) 0;
2795 u_char *nick;
2796 u_char *channel = NULL;
2797
2798 if (!(nick = next_arg(input, &channel)))
2799 dma_strcpy(&result, zero);
2800 else
2801 dma_strcpy(&result, has_voice(channel, nick) ? one : zero);
2802 return (result);
2803 }
2804
2805 u_char *
function_dcclist(nick)2806 function_dcclist(nick)
2807 u_char *nick;
2808 {
2809 u_char *result;
2810 DCC_list *Client;
2811 size_t len = 0;
2812 int i;
2813
2814 if (!nick)
2815 {
2816 dma_strcpy(&result, zero);
2817 return (result);
2818 }
2819
2820 for (i = 0, Client = ClientList; Client != NULL; Client = Client->next)
2821 if (!my_stricmp(nick, Client->user))
2822 len += 3;
2823
2824 result = (u_char *) dma_Malloc(len + 1);
2825
2826 for (i = 0, Client = ClientList; Client != NULL; Client = Client->next)
2827 if (!my_stricmp(nick, Client->user))
2828 {
2829 int b = Client->flags;
2830 int a = (b & DCC_TYPES);
2831
2832 result[i++] = (a == DCC_CHAT) ? 'C' /* CHAT */
2833 : (a == DCC_FILEOFFER) ? 'S' /* SEND */
2834 : (a == DCC_FILEREAD) ? 'G' /* GET */
2835 : (a == DCC_TALK) ? 'T' /* TALK */
2836 : (a == DCC_SUMMON) ? 'U' /* SUMMON */
2837 : (a == DCC_RAW_LISTEN) ? 'L' /* RAW_LISTEN */
2838 : (a == DCC_RAW) ? 'R' /* RAW */
2839 : 'x';
2840
2841 result[i++] = (b & DCC_DELETE) ? 'C' /* CLOSED */
2842 : (b & DCC_ACTIVE) ? 'A' /* ACTIVE */
2843 : (b & DCC_WAIT) ? 'W' /* WAITING */
2844 : (b & DCC_OFFER) ? 'O' /* OFFERED */
2845 : 'x';
2846
2847 result[i++] = ' ';
2848 }
2849
2850 result[i] = '\0';
2851
2852 return (result);
2853 }
2854
2855 u_char *
function_chatpeers(dummy)2856 function_chatpeers(dummy)
2857 u_char *dummy;
2858 {
2859 u_char *result;
2860 DCC_list *Client;
2861 int notfirst = 0;
2862 size_t len = 0;
2863
2864 /* calculate size */
2865 for (Client = ClientList; Client != NULL; Client = Client->next)
2866 if ((Client->flags & (DCC_CHAT | DCC_ACTIVE)) ==
2867 (DCC_CHAT | DCC_ACTIVE))
2868 len += (my_strlen(Client->user) + 1);
2869 result = (u_char *) dma_Malloc(len);
2870 *result = '\0';
2871
2872 for (Client = ClientList; Client != NULL; Client = Client->next)
2873 if ((Client->flags & (DCC_CHAT | DCC_ACTIVE)) ==
2874 (DCC_CHAT | DCC_ACTIVE))
2875 {
2876 if (notfirst)
2877 my_strcat(result, ",");
2878 else
2879 notfirst = 1;
2880 my_strcat(result, Client->user);
2881 }
2882
2883 return (result);
2884 }
2885
2886 u_char *
function_word(input)2887 function_word(input)
2888 u_char *input;
2889 {
2890 u_char *result = (u_char *) 0;
2891 u_char *count;
2892 int cvalue;
2893 u_char *word;
2894
2895 count = next_arg(input, &input);
2896 if (count)
2897 cvalue = my_atoi(count);
2898 else
2899 cvalue = 0;
2900 if (cvalue < 0)
2901 dma_strcpy(&result, empty_string);
2902 else
2903 {
2904 for (word = next_arg(input, &input); word && cvalue--;
2905 word = next_arg(input, &input))
2906 ;
2907 dma_strcpy(&result, (word) ? word : empty_string);
2908 }
2909 return (result);
2910 }
2911
2912 u_char *
function_querynick(input)2913 function_querynick(input)
2914 u_char *input;
2915 {
2916 u_char *result = (u_char *) 0;
2917 Window *win;
2918
2919 if (input && isdigit(*input))
2920 win = get_window_by_refnum((u_int) my_atoi(input));
2921 else
2922 win = curr_scr_win;
2923 dma_strcpy(&result, win ? win->query_nick : UP("-1"));
2924 return (result);
2925 }
2926
2927 u_char *
function_winserver(input)2928 function_winserver(input)
2929 u_char *input;
2930 {
2931 u_char *result = (u_char *) 0;
2932 u_char tmp[10];
2933 Window *win;
2934
2935 if (input && isdigit(*input))
2936 win = get_window_by_refnum((u_int) my_atoi(input));
2937 else
2938 win = curr_scr_win;
2939 sprintf(CP(tmp), "%d", win ? win->server : -1);
2940 dma_strcpy(&result, tmp);
2941 return (result);
2942 }
2943
2944 u_char *
function_winservergroup(input)2945 function_winservergroup(input)
2946 u_char *input;
2947 {
2948 u_char *result = (u_char *) 0;
2949 u_char tmp[10];
2950 Window *win;
2951
2952 if (input && isdigit(*input))
2953 win = get_window_by_refnum((u_int) my_atoi(input));
2954 else
2955 win = curr_scr_win;
2956 // sprintf(CP(tmp), "%d", win ? win->server_group : -1);
2957 sprintf(CP(tmp), "%d", -1);
2958 dma_strcpy(&result, tmp);
2959 return (result);
2960 }
2961
2962 u_char *
function_winvisible(input)2963 function_winvisible(input)
2964 u_char *input;
2965 {
2966 u_char *result = (u_char *) 0;
2967 u_char tmp[10];
2968 Window *win;
2969
2970 if (input && isdigit(*input))
2971 win = get_window_by_refnum((u_int) my_atoi(input));
2972 else
2973 win = curr_scr_win;
2974 sprintf(CP(tmp), "%d", win ? win->visible : -1);
2975 dma_strcpy(&result, tmp);
2976 return (result);
2977 }
2978
2979 u_char *
function_winnum(input)2980 function_winnum(input)
2981 u_char *input;
2982 {
2983 u_char *result = (u_char *) 0;
2984 u_char tmp[10];
2985
2986 sprintf(CP(tmp), "%d", curr_scr_win ? (int)curr_scr_win->refnum : -1);
2987 dma_strcpy(&result, tmp);
2988 return (result);
2989 }
2990
2991 u_char *
function_winnam(input)2992 function_winnam(input)
2993 u_char *input;
2994 {
2995 u_char *result = (u_char *) 0;
2996 Window *win;
2997
2998 if (input && isdigit(*input))
2999 win = get_window_by_refnum((u_int) my_atoi(input));
3000 else
3001 win = curr_scr_win;
3002 dma_strcpy(&result, (win && win->name) ? win->name : empty_string);
3003 return (result);
3004 }
3005
3006 /*
3007 * returns the current window's display (len) size counting for double
3008 * status bars, etc.. -Toasty
3009 */
3010 u_char *
function_winrows(input)3011 function_winrows(input)
3012 u_char *input;
3013 {
3014 u_char *result = (u_char *) 0;
3015
3016 if (curr_scr_win)
3017 {
3018 u_char tmp[10];
3019
3020 sprintf(CP(tmp), "%d", curr_scr_win->display_size);
3021 dma_strcpy(&result, tmp);
3022 }
3023 else
3024 dma_strcpy(&result, UP("-1"));
3025 return (result);
3026 }
3027
3028 /*
3029 * returns the current screen's (since all windows have the same
3030 * column/width) column value -Toasty
3031 */
3032 u_char *
function_wincols(input)3033 function_wincols(input)
3034 u_char *input;
3035 {
3036 u_char *result = (u_char *) 0;
3037
3038 if (curr_scr_win)
3039 {
3040 u_char tmp[10];
3041
3042 sprintf(CP(tmp), "%d", current_screen->co);
3043 dma_strcpy(&result, tmp);
3044 }
3045 else
3046 dma_strcpy(&result, UP("-1"));
3047 return (result);
3048 }
3049
3050 u_char *
function_connect(input)3051 function_connect(input)
3052 u_char *input;
3053 {
3054 u_char *result = (u_char *) 0;
3055 u_char *host;
3056
3057 #ifdef DAEMON_UID
3058 if (getuid() == DAEMON_UID)
3059 put_it("You are not permitted to use CONNECT()");
3060 else
3061 #endif /* DAEMON_ID */
3062 if ((host = next_arg(input, &input)) != NULL)
3063 result = dcc_raw_connect(host, (u_int) my_atoi(input));
3064 return (result);
3065 }
3066
3067 u_char *
function_listen(input)3068 function_listen(input)
3069 u_char *input;
3070 {
3071 u_char *result = (u_char *) 0;
3072
3073 #ifdef DAEMON_UID
3074 if (getuid() == DAEMON_UID)
3075 dma_strcpy(&result, zero);
3076 else
3077 #endif /* DAEMON_ID */
3078 result = dcc_raw_listen((u_int) my_atoi(input));
3079 return (result);
3080 }
3081
3082 u_char *
function_toupper(input)3083 function_toupper(input)
3084 u_char *input;
3085 {
3086 u_char *new = (u_char *) 0, *ptr;
3087
3088 if (!input)
3089 return empty_string;
3090 dma_strcpy(&new, input);
3091 for (ptr = new; *ptr; ptr++)
3092 *ptr = islower(*ptr) ? toupper(*ptr) : *ptr;
3093 return new;
3094 }
3095
3096 u_char *
function_tolower(input)3097 function_tolower(input)
3098 u_char *input;
3099 {
3100 u_char *new = (u_char *) 0, *ptr;
3101
3102 if (!input)
3103 return empty_string;
3104 dma_strcpy(&new, input);
3105 for (ptr = new; *ptr; ptr++)
3106 *ptr = (isupper(*ptr)) ? tolower(*ptr) : *ptr;
3107 return new;
3108 }
3109
3110 u_char *
function_curpos(input)3111 function_curpos(input)
3112 u_char *input;
3113 {
3114 u_char *new = (u_char *) 0, pos[4];
3115
3116 sprintf(CP(pos), "%d", current_screen->buffer_pos);
3117 dma_strcpy(&new, pos);
3118 return new;
3119 }
3120
3121 u_char *
function_channels(input)3122 function_channels(input)
3123 u_char *input;
3124 {
3125 Window *window;
3126
3127 if (input)
3128 window = isdigit(*input) ? get_window_by_refnum((u_int) my_atoi(input))
3129 : curr_scr_win;
3130 else
3131 window = curr_scr_win;
3132
3133 return create_channel_list(window);
3134 }
3135
3136 u_char *
function_servers(input)3137 function_servers(input)
3138 u_char *input;
3139 {
3140 return create_server_list();
3141 }
3142
3143 u_char *
function_servertype(input)3144 function_servertype(input)
3145 u_char *input;
3146 {
3147 int server;
3148 u_char *s = NULL;
3149 u_char *result = NULL;
3150
3151 if (from_server < 0)
3152 server = primary_server;
3153 else
3154 server = from_server;
3155 if (server < 0 || server >= number_of_servers)
3156 s = empty_string;
3157 else
3158 switch (server_list[server].version)
3159 {
3160 case Server2_5:
3161 s = UP("IRC2.5");
3162 break;
3163 case Server2_6:
3164 s = UP("IRC2.6");
3165 break;
3166 case Server2_7:
3167 s = UP("IRC2.7");
3168 break;
3169 case Server2_8:
3170 s = UP("IRC2.8");
3171 break;
3172 case Server2_9:
3173 s = UP("IRC2.9");
3174 break;
3175 case Server2_10:
3176 s = UP("IRC2.10");
3177 break;
3178 case Server2_11:
3179 s = UP("IRC2.11");
3180 break;
3181 }
3182
3183 dma_strcpy(&result, s);
3184 return (result);
3185 }
3186
3187 u_char *
function_onchannel(input)3188 function_onchannel(input)
3189 u_char *input;
3190 {
3191 u_char *result = (u_char *) 0;
3192 u_char *nick;
3193 u_char *channel = NULL;
3194
3195 if (from_server < 0 || !(nick = next_arg(input, &channel)))
3196 dma_strcpy(&result, zero);
3197 else
3198 dma_strcpy(&result,
3199 is_on_channel(channel, from_server, nick) ? one : zero);
3200 return (result);
3201 }
3202
3203 u_char *
function_pid(input)3204 function_pid(input)
3205 u_char *input;
3206 {
3207 u_char *result = (u_char *) 0;
3208 u_char lbuf[32]; /* plenty big enough for %d */
3209
3210 sprintf(CP(lbuf), "%d", (int)getpid());
3211 dma_strcpy(&result, lbuf);
3212 return (result);
3213 }
3214
3215 u_char *
function_ppid(input)3216 function_ppid(input)
3217 u_char *input;
3218 {
3219 u_char *result = (u_char *) 0;
3220 u_char lbuf[32]; /* plenty big enough for %d */
3221
3222 sprintf(CP(lbuf), "%d", (int)getppid());
3223 dma_strcpy(&result, lbuf);
3224 return (result);
3225 }
3226
3227 u_char *
function_chanusers(input)3228 function_chanusers(input)
3229 u_char *input;
3230 {
3231 Channel *chan;
3232 Nick *nicks;
3233 u_char *result = (u_char *) 0;
3234 int len = 0;
3235 int notfirst = 0;
3236
3237 /* can't find channel? never mind */
3238 chan = lookup_channel(input, from_server, CHAN_NOUNLINK);
3239 if (chan == (Channel *)NULL)
3240 return (u_char *) 0;
3241
3242 /* allocate necessary memory */
3243 /* XXX: len = chan->ncount */
3244 for (nicks = chan->nicks; nicks; nicks = nicks->next)
3245 len += (my_strlen(nicks->nick) + 1);
3246 result = (u_char *) dma_Malloc(len + 1);
3247
3248 /* put the nicks in.. */
3249 for (nicks = chan->nicks; nicks; nicks = nicks->next)
3250 {
3251 if (notfirst)
3252 my_strcat(result, " ");
3253 else
3254 notfirst = 1;
3255 my_strcat(result, nicks->nick);
3256 }
3257 return (result);
3258 }
3259
3260 /*
3261 * strftime() patch from hari (markc@arbld.unimelb.edu.au)
3262 */
3263 #ifdef HAVE_STRFTIME
3264 u_char *
function_strftime(input)3265 function_strftime(input)
3266 u_char *input;
3267 {
3268 u_char result[128];
3269 time_t ltime;
3270 u_char *fmt = (u_char *) 0;
3271
3272 ltime = my_atol(input);
3273 fmt = input;
3274 /* skip the time field */
3275 while (isdigit(*fmt))
3276 ++fmt;
3277 if (*fmt && *++fmt)
3278 {
3279 struct tm *tm;
3280
3281 tm = localtime(<ime);
3282 if (strftime(CP(result), 128, CP(fmt), tm))
3283 {
3284 u_char *s = NULL;
3285
3286 dma_strcpy(&s, result);
3287 return s;
3288 }
3289 }
3290 return (u_char *) 0;
3291 }
3292 #endif
3293
3294 /*
3295 * idle() patch from scottr (scott.reynolds@plexus.com)
3296 */
3297 u_char *
function_idle(input)3298 function_idle(input)
3299 u_char *input;
3300 {
3301 u_char *result = (u_char *) 0;
3302 u_char lbuf[20];
3303
3304 snprintf(CP(lbuf), sizeof(lbuf)-1, "%ld", (long)(time(0) - idle_time));
3305 lbuf[sizeof(lbuf)-1] = '\0';
3306 dma_strcpy(&result, lbuf);
3307 return (result);
3308 }
3309
3310
3311 /* the function_*() routines below were added by jduck */
3312 u_char *
function_fromuser(input)3313 function_fromuser(input)
3314 u_char *input;
3315 {
3316 u_char *result = NULL;
3317
3318 dma_strcpy(&result, FromUser ? FromUser : empty_string);
3319 return result;
3320 }
3321
3322 u_char *
function_fromhost(input)3323 function_fromhost(input)
3324 u_char *input;
3325 {
3326 u_char *result = NULL;
3327
3328 dma_strcpy(&result, FromHost ? FromHost : empty_string);
3329 return result;
3330 }
3331
3332 /*
3333 * $nsize() converts bytes into ascii text representation of size
3334 * relative to it's magnitude (2.3MB 231.2K etc)
3335 */
3336 u_char *
function_nsize(input)3337 function_nsize(input)
3338 u_char *input;
3339 {
3340 u_char *result = NULL;
3341
3342 dma_strcpy(&result, ninja_size(my_atol(input)));
3343 return (result);
3344 }
3345
3346 u_char *
function_ndate(input)3347 function_ndate(input)
3348 u_char *input;
3349 {
3350 u_char *result = NULL;
3351 time_t tval;
3352
3353 tval = my_atol(input);
3354 dma_strcpy(&result, ninja_date(&tval));
3355 return result;
3356 }
3357
3358 u_char *
function_ntime(input)3359 function_ntime(input)
3360 u_char *input;
3361 {
3362 u_char *result = NULL;
3363 time_t tval;
3364
3365 tval = my_atol(input);
3366 dma_strcpy(&result, ninja_ctime(&tval));
3367 return result;
3368 }
3369
3370 u_char *
function_etime(input)3371 function_etime(input)
3372 u_char *input;
3373 {
3374 u_char *result = NULL;
3375
3376 dma_strcpy(&result, ninja_etime(my_atol(input)));
3377 return result;
3378 }
3379
3380 /*
3381 * pipe_to_ansi()
3382 */
3383 u_char *
function_pipe_to_ansi(input)3384 function_pipe_to_ansi(input)
3385 u_char *input;
3386 {
3387 u_char *result = NULL;
3388
3389 dma_strcpy(&result, pipe_to_ansi(input));
3390 return result;
3391 }
3392
3393 /* Search and replace function --
3394 Usage: $sed(command/search/replace/data)
3395 Commands:
3396 r - treat data as a variable name and
3397 return the replaced data to the variable
3398 g - Replace all instances, not just the first one
3399 The delimiter may be any character that is not a command (typically /)
3400 The delimiter MUST be the first character after the command
3401 Returns empty string on error
3402 */
3403 u_char *
function_sed(u_char * word)3404 function_sed(u_char *word)
3405 {
3406 int variable = 0, global = 0, searchlen;
3407 unsigned int display = window_display;
3408 u_char delimiter;
3409 u_char *replace = NULL;
3410 u_char *pointer = NULL;
3411 u_char *search = NULL;
3412 u_char *data = NULL;
3413 u_char *value = NULL;
3414 u_char *result = NULL;
3415 u_char *svalue;
3416 Alias *tmp;
3417
3418 while (((*word == 'r') && (variable = 1)) || ((*word == 'g') && (global = 1)))
3419 word++;
3420 if (!(word && *word))
3421 return empty_string;
3422 delimiter = *word;
3423 search = word + 1;
3424 if (!(replace = strchr(search, delimiter)))
3425 return empty_string;
3426 *replace++ = '\0';
3427 if (!(data = strchr(replace, delimiter)))
3428 return empty_string;
3429 *data++ = '\0';
3430 if (variable)
3431 {
3432 if ((tmp = find_alias(&(alias_list[VAR_ALIAS]), data, 1, (int *)0)))
3433 dma_strcpy(&value, tmp->stuff);
3434 }
3435 else
3436 dma_strcpy(&value, data);
3437 if (!value || !*value)
3438 {
3439 if (value)
3440 dma_Free(&value);
3441 return empty_string;
3442 }
3443 svalue = value;
3444 pointer = value;
3445 searchlen = my_strlen(search) - 1;
3446 if (searchlen < 0)
3447 searchlen = 0;
3448 if (global)
3449 {
3450 while ((pointer = strstr(pointer, search)))
3451 {
3452 pointer[0] = pointer[searchlen] = 0;
3453 pointer += searchlen + 1;
3454 dma_strcat(&result, value);
3455 dma_strcat(&result, replace);
3456 value = pointer;
3457 if (!*pointer)
3458 break;
3459 }
3460 }
3461 else
3462 {
3463 if ((pointer = strstr(pointer, search)))
3464 {
3465 pointer[0] = pointer[searchlen] = 0;
3466 pointer += searchlen + 1;
3467 dma_strcat(&result, value);
3468 dma_strcat(&result, replace);
3469 value = pointer;
3470 }
3471 }
3472 dma_strcat(&result, value);
3473 if (variable)
3474 {
3475 window_display = 0;
3476 add_alias(VAR_ALIAS, data, result);
3477 window_display = display;
3478 }
3479 dma_Free(&svalue);
3480 return (result);
3481 }
3482
3483
3484 /*
3485 * ban mask scripting interface..
3486 */
3487 u_char *
function_banmask(input)3488 function_banmask(input)
3489 u_char *input;
3490 {
3491 u_char *result = NULL;
3492
3493 if (input)
3494 dma_strcpy(&result, cluster(input));
3495 else
3496 dma_strcpy(&result, empty_string);
3497 return result;
3498 }
3499