1 /******************************************************************************
2 *   This file is part of TinTin++                                             *
3 *                                                                             *
4 *   Copyright 2004-2019 Igor van den Hoven                                    *
5 *                                                                             *
6 *   TinTin++ is free software; you can redistribute it and/or modify          *
7 *   it under the terms of the GNU General Public License as published by      *
8 *   the Free Software Foundation; either version 3 of the License, or         *
9 *   (at your option) any later version.                                       *
10 *                                                                             *
11 *   This program is distributed in the hope that it will be useful,           *
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
14 *   GNU General Public License for more details.                              *
15 *                                                                             *
16 *                                                                             *
17 *   You should have received a copy of the GNU General Public License         *
18 *   along with TinTin++.  If not, see https://www.gnu.org/licenses.           *
19 ******************************************************************************/
20 
21 /******************************************************************************
22 *                (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t                 *
23 *                                                                             *
24 *                         coded by Peter Unold 1992                           *
25 *                     recoded by Igor van den Hoven 2005                      *
26 ******************************************************************************/
27 
28 #include "tintin.h"
29 
30 // whether str1 is an abbreviation of str2
31 
32 int case_table[256] =
33 {
34 	  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,
35 	 16,  17,  18,  19,  20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,
36 	 95,  33,  34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,
37 	 48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
38 	 64,
39 	 65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
40 	 91,  92,  93,  94,
41 	 95,  96,
42 	 65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
43 	123, 124, 125, 126, 127,
44 	128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
45 	144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
46 	160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
47 	176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
48 	192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
49 	208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
50 	224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
51 	240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
52 };
53 
is_abbrev(char * str1,char * str2)54 int is_abbrev(char *str1, char *str2)
55 {
56 	char buf[NUMBER_SIZE], *str3;
57 
58 	str3 = buf;
59 
60 	if (*str1 == 0)
61 	{
62 		return FALSE;
63 	}
64 
65 	if (*str2 == 0)
66 	{
67 		tintin_printf2(gtd->ses, "\e[1;31mis_abbrev(%s,%s)", str1, str2);
68 
69 		dump_stack();
70 
71 		return FALSE;
72 	}
73 
74 	while (TRUE)
75 	{
76 		if (*str1 == 0)
77 		{
78 			*str3 = 0;
79 
80 			strcpy(gtd->is_result, buf);
81 
82 			return TRUE;
83 		}
84 
85 		if (case_table[(int) *str1] != case_table[(int) *str2])
86 		{
87 			return FALSE;
88 		}
89 		str1++;
90 
91 		*str3++ = *str2++;
92 	}
93 }
94 
is_member(char * str1,char * str2)95 int is_member(char *str1, char *str2)
96 {
97 	char *pt1, *pt2;
98 
99 	if (*str1 == 0)
100 	{
101 		return FALSE;
102 	}
103 
104 	if (*str2 == 0)
105 	{
106 		tintin_printf2(gtd->ses, "\e[1;31mis_member(%s,%s)", str1, str2);
107 
108 		dump_stack();
109 
110 		return FALSE;
111 	}
112 
113 	while (*str1)
114 	{
115 		if (case_table[(int) *str1] == case_table[(int) *str2])
116 		{
117 			pt1 = str1;
118 			pt2 = str2;
119 
120 			while (case_table[(int) *pt1] == case_table[(int) *pt2])
121 			{
122 				pt1++;
123 				pt2++;
124 
125 				if (*pt1 == ' ' || *pt1 == 0)
126 				{
127 					return TRUE;
128 				}
129 			}
130 		}
131 
132 		while (*str1 && *str1 != ' ')
133 		{
134 			str1++;
135 		}
136 
137 		if (*str1)
138 		{
139 			str1++;
140 		}
141 	}
142 	return FALSE;
143 }
144 
filename_string(char * input,char * output)145 void filename_string(char *input, char *output)
146 {
147 	while (*input)
148 	{
149 		*output++ = (char) case_table[(int) *input++];
150 	}
151 	*output = 0;
152 }
153 
is_vowel(char * str)154 int is_vowel(char *str)
155 {
156 	switch (case_table[(int) *str])
157 	{
158 		case 'a':
159 		case 'e':
160 		case 'i':
161 		case 'o':
162 		case 'u':
163 			return TRUE;
164 	}
165 	return FALSE;
166 }
167 
168 
parse_input(struct session * ses,char * input)169 struct session *parse_input(struct session *ses, char *input)
170 {
171 	char *line;
172 
173 	push_call("parse_input(%s,%s)",ses->name,input);
174 /*
175 	if (*input == 0)
176 	{
177 		write_mud(ses, input, SUB_EOL);
178 
179 		pop_call();
180 		return ses;
181 	}
182 */
183 	line = str_alloc_stack(0);
184 
185 	if (VERBATIM(ses))
186 	{
187 		sub_arg_all(ses, input, line, 1, SUB_SEC);
188 
189 		if (check_all_aliases(ses, line))
190 		{
191 			ses = script_driver(ses, LIST_ALIAS, line);
192 		}
193 		else if (HAS_BIT(ses->config_flags, CONFIG_FLAG_SPEEDWALK) && is_speedwalk(ses, line))
194 		{
195 			process_speedwalk(ses, line);
196 		}
197 		else
198 		{
199 			write_mud(ses, line, SUB_EOL|SUB_ESC);
200 		}
201 
202 		pop_call();
203 		return ses;
204 	}
205 
206 	if (*input == gtd->verbatim_char)
207 	{
208 		write_mud(ses, input+1, SUB_EOL);
209 
210 		pop_call();
211 		return ses;
212 	}
213 
214 	do
215 	{
216 		input = space_out(input);
217 
218 		input = get_arg_all(ses, input, line, 0);
219 
220 		if (parse_command(ses, line))
221 		{
222 			ses = script_driver(ses, LIST_COMMAND, line);
223 		}
224 		else if (check_all_aliases(ses, line))
225 		{
226 			ses = script_driver(ses, LIST_ALIAS, line);
227 		}
228 		else if (HAS_BIT(ses->config_flags, CONFIG_FLAG_SPEEDWALK) && is_speedwalk(ses, line))
229 		{
230 			process_speedwalk(ses, line);
231 		}
232 		else
233 		{
234 			write_mud(ses, line, SUB_VAR|SUB_FUN|SUB_ESC|SUB_EOL);
235 		}
236 
237 		if (*input == COMMAND_SEPARATOR)
238 		{
239 			input++;
240 		}
241 	}
242 	while (*input);
243 
244 	pop_call();
245 	return ses;
246 }
247 
248 /*
249 	Deal with variables and functions used as commands.
250 */
251 
parse_command(struct session * ses,char * input)252 struct session *parse_command(struct session *ses, char *input)
253 {
254 	char *arg, *arg1;
255 
256 	push_call("parse_command(%p,%p)",ses,input);
257 
258 	arg1 = str_alloc_stack(0);
259 
260 	arg = sub_arg_stop_spaces(ses, input, arg1, GET_ONE, SUB_VAR|SUB_FUN);
261 
262 	if (!strncmp(input, arg1, strlen(arg1)))
263 	{
264 		pop_call();
265 		return NULL;
266 	}
267 
268 	if (*arg)
269 	{
270 		cat_sprintf(arg1, " %s", arg);
271 	}
272 	strcpy(input, arg1);
273 
274 	pop_call();
275 	return ses;
276 }
277 
substitute_speedwalk(struct session * ses,char * input,char * output)278 char *substitute_speedwalk(struct session *ses, char *input, char *output)
279 {
280 	char num[NUMBER_SIZE], name[BUFFER_SIZE], *pti, *ptn, *pto;
281 	int cnt, max;
282 
283 	pti = input;
284 	pto = output;
285 
286 	while (*pti && pto - output < INPUT_SIZE)
287 	{
288 		if (is_space(*pti))
289 		{
290 			return input;
291 		}
292 
293 		if (is_digit(*pti))
294 		{
295 			ptn = num;
296 
297 			while (is_digit(*pti))
298 			{
299 				if (ptn - num < 4)
300 				{
301 					*ptn++ = *pti++;
302 				}
303 				else
304 				{
305 					pti++;
306 				}
307 			}
308 			*ptn = 0;
309 
310 			max = atoi(num);
311 
312 			if (*pti == 0)
313 			{
314 				return input;
315 			}
316 		}
317 		else
318 		{
319 			max = 1;
320 		}
321 
322 		pti = get_arg_stop_digits(ses, pti, name, GET_ONE);
323 
324 		if (*name == 0 || !is_pathdir(ses, name))
325 		{
326 			return input;
327 		}
328 
329 		for (cnt = 0 ; cnt < max ; cnt++)
330 		{
331 			if (output != pto)
332 			{
333 				*pto++ = COMMAND_SEPARATOR;
334 			}
335 			pto += sprintf(pto, "%s", name);
336 		}
337 
338 		if (*pti == COMMAND_SEPARATOR)
339 		{
340 			pti++;
341 		}
342 	}
343 	*pto = 0;
344 
345 	return output;
346 }
347 
is_speedwalk(struct session * ses,char * input)348 int is_speedwalk(struct session *ses, char *input)
349 {
350 	int digit = 0, flag = FALSE;
351 
352 	while (*input)
353 	{
354 		switch (*input)
355 		{
356 			case 'n':
357 			case 'e':
358 			case 's':
359 			case 'w':
360 			case 'u':
361 			case 'd':
362 				if (digit > 3)
363 				{
364 					return FALSE;
365 				}
366 				digit = 0;
367 				flag  = TRUE;
368 				break;
369 
370 			case '0':
371 			case '1':
372 			case '2':
373 			case '3':
374 			case '4':
375 			case '5':
376 			case '6':
377 			case '7':
378 			case '8':
379 			case '9':
380 				digit++;
381 				flag = FALSE;
382 				break;
383 
384 			default:
385 				return FALSE;
386 		}
387 		input++;
388 	}
389 	return flag;
390 }
391 
392 
process_speedwalk(struct session * ses,char * input)393 void process_speedwalk(struct session *ses, char *input)
394 {
395 	char dir[2];
396 	int cnt, i;
397 
398 	for (dir[1] = 0 ; *input ; input++)
399 	{
400 		if (is_digit(*input))
401 		{
402 			sscanf(input, "%d%c", &cnt, dir);
403 
404 			for (i = 0 ; i < cnt ; i++)
405 			{
406 				write_mud(ses, dir, SUB_EOL);
407 			}
408 
409 			while (*input != dir[0])
410 			{
411 				input++;
412 			}
413 		}
414 		else
415 		{
416 			dir[0] = *input;
417 
418 			write_mud(ses, dir, SUB_EOL);
419 		}
420 	}
421 	return;
422 }
423 
424 /*
425 	Deals with all # stuff
426 */
427 
parse_tintin_command(struct session * ses,char * input)428 struct session *parse_tintin_command(struct session *ses, char *input)
429 {
430 	char line[BUFFER_SIZE];
431 	struct session *sesptr;
432 
433 	input = sub_arg_in_braces(ses, input, line, GET_ONE, SUB_VAR|SUB_FUN);
434 
435 	if (is_number(line))
436 	{
437 		int cnt = atoi(line);
438 
439 		input = get_arg_in_braces(ses, input, line, GET_ALL);
440 
441 		while (cnt-- > 0)
442 		{
443 			ses = script_driver(ses, LIST_COMMAND, line);
444 		}
445 		return ses;
446 	}
447 
448 	sesptr = find_session(line);
449 
450 	if (sesptr)
451 	{
452 		if (*input)
453 		{
454 			input = get_arg_in_braces(ses, input, line, GET_ALL);
455 
456 			substitute(ses, line, line, SUB_VAR|SUB_FUN);
457 
458 			script_driver(sesptr, LIST_COMMAND, line);
459 
460 			return ses;
461 		}
462 		else
463 		{
464 			return activate_session(sesptr);
465 		}
466 	}
467 
468 	if (*line == '!')
469 	{
470 		show_error(ses, LIST_COMMAND, "#!%s %s", line + 1, input);
471 
472 		return ses;
473 	}
474 
475 	tintin_printf2(ses, "#ERROR: #UNKNOWN TINTIN-COMMAND '%s'.", line);
476 
477 	check_all_events(ses, SUB_SEC|EVENT_FLAG_SYSTEM, 0, 1, "UNKNOWN COMMAND", line);
478 
479 	return ses;
480 }
481 
482 
cnt_arg_all(struct session * ses,char * string,int flag)483 int cnt_arg_all(struct session *ses, char *string, int flag)
484 {
485 	char *arg, tmp[BUFFER_SIZE];
486 	int cnt;
487 
488 	arg = string;
489 	cnt = 0;
490 
491 	while (*arg)
492 	{
493 		cnt++;
494 
495 		arg = get_arg_in_braces(ses, arg, tmp, flag);
496 
497 		if (*arg == COMMAND_SEPARATOR)
498 		{
499 			arg++;
500 		}
501 	}
502 	return cnt;
503 }
504 
505 /*
506 	get all arguments - only check for unescaped command separators
507 */
508 
get_arg_all(struct session * ses,char * string,char * result,int verbatim)509 char *get_arg_all(struct session *ses, char *string, char *result, int verbatim)
510 {
511 	char *pto, *pti;
512 	int skip, nest = 0;
513 
514 	pti = string;
515 	pto = result;
516 
517 	if (*pti == gtd->verbatim_char)
518 	{
519 		while (*pti)
520 		{
521 			*pto++ = *pti++;
522 		}
523 		*pto = 0;
524 
525 		return pti;
526 	}
527 
528 	while (*pti)
529 	{
530 		if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, pti))
531 		{
532 			*pto++ = *pti++;
533 			*pto++ = *pti++;
534 			continue;
535 		}
536 
537 		skip = find_secure_color_code(pti);
538 
539 		if (skip)
540 		{
541 			while (skip--)
542 			{
543 				*pto++ = *pti++;
544 			}
545 			continue;
546 		}
547 
548 		if (*pti == '\\' && pti[1] == COMMAND_SEPARATOR)
549 		{
550 			*pto++ = *pti++;
551 		}
552 		else if (*pti == COMMAND_SEPARATOR && nest == 0 && !verbatim)
553 		{
554 			break;
555 		}
556 		else if (*pti == DEFAULT_OPEN)
557 		{
558 			nest++;
559 		}
560 		else if (*pti == DEFAULT_CLOSE)
561 		{
562 			nest--;
563 		}
564 		*pto++ = *pti++;
565 
566 		if (pto - result >= BUFFER_SIZE - 3)
567 		{
568 			tintin_printf2(ses, "#ERROR: INPUT BUFFER OVERFLOW.");
569 
570 			pto--;
571 
572 			break;
573 		}
574 	}
575 	*pto = '\0';
576 
577 	return pti;
578 }
579 
sub_arg_all(struct session * ses,char * string,char * result,int verbatim,int sub)580 char *sub_arg_all(struct session *ses, char *string, char *result, int verbatim, int sub)
581 {
582 	char *buffer;
583 
584 	if (*string == 0)
585 	{
586 		*result = 0;
587 
588 		return string;
589 	}
590 
591 	push_call("sub_arg_all(%p,%p,%p,%d,%d)",ses,string,result,verbatim,sub);
592 
593 	buffer = str_alloc_stack(strlen(string));
594 
595 	string = get_arg_all(ses, string, buffer, verbatim);
596 
597 	substitute(ses, buffer, result, sub);
598 
599 	pop_call();
600 	return string;
601 }
602 
603 /*
604 	Braces are stripped in braced arguments leaving all else as is.
605 */
606 
get_arg_in_braces(struct session * ses,char * string,char * result,int flag)607 char *get_arg_in_braces(struct session *ses, char *string, char *result, int flag)
608 {
609 	char *pti, *pto;
610 	int skip, nest = 1;
611 
612 	pti = space_out(string);
613 	pto = result;
614 
615 	if (*pti != DEFAULT_OPEN)
616 	{
617 		if (!HAS_BIT(flag, GET_ALL))
618 		{
619 			pti = get_arg_stop_spaces(ses, pti, result, flag);
620 		}
621 		else
622 		{
623 			pti = get_arg_with_spaces(ses, pti, result, flag);
624 		}
625 		return pti;
626 	}
627 
628 	pti++;
629 
630 	while (*pti)
631 	{
632 		if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, pti))
633 		{
634 			*pto++ = *pti++;
635 			*pto++ = *pti++;
636 			continue;
637 		}
638 
639 		skip = find_secure_color_code(pti);
640 
641 		if (skip)
642 		{
643 			while (skip--)
644 			{
645 				*pto++ = *pti++;
646 			}
647 			continue;
648 		}
649 
650 		if (*pti == DEFAULT_OPEN)
651 		{
652 			nest++;
653 		}
654 		else if (*pti == DEFAULT_CLOSE)
655 		{
656 			nest--;
657 
658 			if (nest == 0)
659 			{
660 				break;
661 			}
662 		}
663 		*pto++ = *pti++;
664 	}
665 
666 	if (*pti == 0)
667 	{
668 		show_error(ses, LIST_COMMAND, "#ERROR: GET BRACED ARGUMENT: UNMATCHED BRACE.");
669 	}
670 	else
671 	{
672 		pti++;
673 	}
674 	*pto = '\0';
675 
676 	return pti;
677 }
678 
sub_arg_in_braces(struct session * ses,char * string,char * result,int flag,int sub)679 char *sub_arg_in_braces(struct session *ses, char *string, char *result, int flag, int sub)
680 {
681 	char *buffer;
682 
683 	if (*string == 0)
684 	{
685 		*result = 0;
686 
687 		return string;
688 	}
689 
690 	push_call("sub_arg_in_braces(%p,%p,%p,%d,%d)",ses,string,result,flag,sub);
691 
692 	buffer = str_alloc_stack(strlen(string) * 2);
693 
694 	string = get_arg_in_braces(ses, string, buffer, flag);
695 
696 	substitute(ses, buffer, result, sub);
697 
698 	pop_call();
699 	return string;
700 }
701 
702 /*
703 	get all arguments
704 */
705 
get_arg_with_spaces(struct session * ses,char * string,char * result,int flag)706 char *get_arg_with_spaces(struct session *ses, char *string, char *result, int flag)
707 {
708 	char *pto, *pti;
709 	int skip, nest = 0;
710 
711 	pti = space_out(string);
712 	pto = result;
713 
714 	while (*pti)
715 	{
716 		if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, pti))
717 		{
718 			*pto++ = *pti++;
719 			*pto++ = *pti++;
720 			continue;
721 		}
722 
723 		skip = find_secure_color_code(pti);
724 
725 		if (skip)
726 		{
727 			while (skip--)
728 			{
729 				*pto++ = *pti++;
730 			}
731 			continue;
732 		}
733 
734 		if (*pti == '\\' && pti[1] == COMMAND_SEPARATOR)
735 		{
736 			*pto++ = *pti++;
737 		}
738 		else if (*pti == COMMAND_SEPARATOR && nest == 0)
739 		{
740 			break;
741 		}
742 		else if (*pti == DEFAULT_OPEN)
743 		{
744 			nest++;
745 		}
746 		else if (*pti == DEFAULT_CLOSE)
747 		{
748 			nest--;
749 		}
750 		*pto++ = *pti++;
751 	}
752 	*pto = '\0';
753 
754 	return pti;
755 }
756 
757 /*
758 	get one arg, stop at spaces
759 */
760 
get_arg_stop_spaces(struct session * ses,char * string,char * result,int flag)761 char *get_arg_stop_spaces(struct session *ses, char *string, char *result, int flag)
762 {
763 	char *pto, *pti;
764 	int skip, nest = 0;
765 
766 	pti = space_out(string);
767 	pto = result;
768 
769 	while (*pti)
770 	{
771 		if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, pti))
772 		{
773 			*pto++ = *pti++;
774 			*pto++ = *pti++;
775 			continue;
776 		}
777 
778 		skip = find_secure_color_code(pti);
779 
780 		if (skip)
781 		{
782 			while (skip--)
783 			{
784 				*pto++ = *pti++;
785 			}
786 			continue;
787 		}
788 
789 
790 		if (*pti == '\\' && pti[1] == COMMAND_SEPARATOR)
791 		{
792 			*pto++ = *pti++;
793 		}
794 		else if (*pti == COMMAND_SEPARATOR && nest == 0)
795 		{
796 			break;
797 		}
798 		else if (is_space(*pti) && nest == 0)
799 		{
800 			pti++;
801 			break;
802 		}
803 		else if (*pti == DEFAULT_OPEN)
804 		{
805 			nest++;
806 		}
807 		else if (*pti == '[' && HAS_BIT(flag, GET_NST))
808 		{
809 			nest++;
810 		}
811 		else if (*pti == DEFAULT_CLOSE)
812 		{
813 			nest--;
814 		}
815 		else if (*pti == ']' && HAS_BIT(flag, GET_NST))
816 		{
817 			nest--;
818 		}
819 		*pto++ = *pti++;
820 	}
821 	*pto = '\0';
822 
823 	return pti;
824 }
825 
sub_arg_stop_spaces(struct session * ses,char * string,char * result,int flag,int sub)826 char *sub_arg_stop_spaces(struct session *ses, char *string, char *result, int flag, int sub)
827 {
828 	char *buffer;
829 
830 	if (*string == 0)
831 	{
832 		*result = 0;
833 
834 		return string;
835 	}
836 
837 	push_call("sub_arg_stop_braces(%p,%p,%p,%d,%d)",ses,string,result,flag,sub);
838 
839 	buffer = str_alloc_stack(strlen(string) * 2);
840 
841 	string = get_arg_stop_spaces(ses, string, buffer, flag);
842 
843 	substitute(ses, buffer, result, sub);
844 
845 	pop_call();
846 	return string;
847 }
848 
849 // Get one arg, stop at numbers, used for speedwalks
850 
get_arg_stop_digits(struct session * ses,char * string,char * result,int flag)851 char *get_arg_stop_digits(struct session *ses, char *string, char *result, int flag)
852 {
853 	char *pto, *pti;
854 	int nest = 0;
855 
856 	pti = space_out(string);
857 	pto = result;
858 
859 	while (*pti)
860 	{
861 		if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, pti))
862 		{
863 			*pto++ = *pti++;
864 			*pto++ = *pti++;
865 			continue;
866 		}
867 
868 		if (*pti == '\\' && pti[1] == COMMAND_SEPARATOR)
869 		{
870 			*pto++ = *pti++;
871 		}
872 		else if (*pti == COMMAND_SEPARATOR && nest == 0)
873 		{
874 			break;
875 		}
876 		else if (is_digit(*pti) && nest == 0)
877 		{
878 			break;
879 		}
880 		else if (*pti == DEFAULT_OPEN)
881 		{
882 			nest++;
883 		}
884 		else if (*pti == '[' && HAS_BIT(flag, GET_NST))
885 		{
886 			nest++;
887 		}
888 		else if (*pti == DEFAULT_CLOSE)
889 		{
890 			nest--;
891 		}
892 		else if (*pti == ']' && HAS_BIT(flag, GET_NST))
893 		{
894 			nest--;
895 		}
896 		*pto++ = *pti++;
897 	}
898 	*pto = '\0';
899 
900 	return pti;
901 }
902 
903 /*
904 	advance ptr to next none-space
905 */
906 
space_out(char * string)907 char *space_out(char *string)
908 {
909 	while (is_space(*string))
910 	{
911 		string++;
912 	}
913 	return string;
914 }
915 
916 /*
917 	For variable handling
918 */
919 
get_arg_to_brackets(struct session * ses,char * string,char * result)920 char *get_arg_to_brackets(struct session *ses, char *string, char *result)
921 {
922 	char *pti, *pto, *ptii, *ptoo;
923 	int nest1 = 0, nest2 = 0, nest3 = 0;
924 
925 	pti = space_out(string);
926 	pto = result;
927 	ptii = ptoo = NULL;
928 
929 	while (*pti)
930 	{
931 		if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, pti))
932 		{
933 			*pto++ = *pti++;
934 			*pto++ = *pti++;
935 			continue;
936 		}
937 
938 		if (*pti == '[')
939 		{
940 			nest2++;
941 
942 			if (nest1 == 0 && ptii == NULL)
943 			{
944 				ptii = pti;
945 				ptoo = pto;
946 			}
947 		}
948 		else if (*pti == ']')
949 		{
950 			if (nest2)
951 			{
952 				nest2--;
953 			}
954 			else
955 			{
956 				nest3 = 1;
957 			}
958 
959 			if (*(pti+1) == 0 && ptii && nest1 == 0 && nest2 == 0 && nest3 == 0)
960 			{
961 				*ptoo = 0;
962 
963 				return ptii;
964 			}
965 		}
966 		else if (*pti == DEFAULT_OPEN)
967 		{
968 			nest1++;
969 		}
970 		else if (*pti == DEFAULT_CLOSE)
971 		{
972 			nest1--;
973 		}
974 		*pto++ = *pti++;
975 	}
976 	*pto = 0;
977 
978 	return pti;
979 }
980 
get_arg_at_brackets(struct session * ses,char * string,char * result)981 char *get_arg_at_brackets(struct session *ses, char *string, char *result)
982 {
983 	char *pti, *pto;
984 	int nest = 0;
985 
986 	pti = string;
987 	pto = result;
988 
989 	if (*pti != '[')
990 	{
991 		*pto = 0;
992 
993 		return pti;
994 	}
995 
996 	while (*pti)
997 	{
998 		if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, pti))
999 		{
1000 			*pto++ = *pti++;
1001 			*pto++ = *pti++;
1002 			continue;
1003 		}
1004 
1005 		if (*pti == '[')
1006 		{
1007 			nest++;
1008 		}
1009 		else if (*pti == ']')
1010 		{
1011 			if (nest)
1012 			{
1013 				nest--;
1014 			}
1015 			else
1016 			{
1017 				break;
1018 			}
1019 		}
1020 		else if (nest == 0)
1021 		{
1022 			break;
1023 		}
1024 		*pto++ = *pti++;
1025 	}
1026 
1027 	if (nest)
1028 	{
1029 		show_error(ses, LIST_COMMAND, "#ERROR: GET BRACKETED VARIABLE: UNMATCHED BRACKET.");
1030 	}
1031 	*pto = 0;
1032 
1033 	return pti;
1034 }
1035 
get_arg_in_brackets(struct session * ses,char * string,char * result)1036 char *get_arg_in_brackets(struct session *ses, char *string, char *result)
1037 {
1038 	char *pti, *pto;
1039 	int nest = 1;
1040 
1041 	pti = string;
1042 	pto = result;
1043 
1044 	if (*pti != '[')
1045 	{
1046 		*pto = 0;
1047 
1048 		return pti;
1049 	}
1050 
1051 	pti++;
1052 
1053 	while (*pti)
1054 	{
1055 		if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, pti))
1056 		{
1057 			*pto++ = *pti++;
1058 			*pto++ = *pti++;
1059 			continue;
1060 		}
1061 
1062 		if (*pti == '[')
1063 		{
1064 			nest++;
1065 		}
1066 		else if (*pti == ']')
1067 		{
1068 			nest--;
1069 
1070 			if (nest == 0)
1071 			{
1072 				break;
1073 			}
1074 		}
1075 		*pto++ = *pti++;
1076 	}
1077 
1078 	if (*pti == 0)
1079 	{
1080 		show_error(ses, LIST_COMMAND, "#ERROR: GET BRACKETED ARGUMENT: UNMATCHED BRACKET.");
1081 	}
1082 	else
1083 	{
1084 		pti++;
1085 	}
1086 	*pto = 0;
1087 
1088 	return pti;
1089 }
1090 
get_char(struct session * ses,char * string,char * result)1091 char *get_char(struct session *ses, char *string, char *result)
1092 {
1093 	char *pti = string;
1094 
1095 	if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, pti))
1096 	{
1097 		pti += sprintf(result, "%c%c", pti[0], pti[1]);
1098 	}
1099 	else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(pti))
1100 	{
1101 		pti += sprintf(result, "%.*s", get_utf8_size(pti), pti);
1102 	}
1103 	else
1104 	{
1105 		pti += sprintf(result, "%c", pti[0]);
1106 	}
1107 
1108 	return pti;
1109 }
1110 
1111 /*
1112 	send command to the mud
1113 */
1114 
write_mud(struct session * ses,char * command,int flags)1115 void write_mud(struct session *ses, char *command, int flags)
1116 {
1117 	char output[BUFFER_SIZE];
1118 	int size;
1119 
1120 	size = substitute(ses, command, output, flags);
1121 
1122 	if (gtd->level->ignore == 0 && HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING))
1123 	{
1124 		if (ses->map == NULL || ses->map->nofollow == 0)
1125 		{
1126 			check_append_path(ses, command, NULL, 0.0, 0, 1);
1127 		}
1128 	}
1129 
1130 	if (gtd->level->ignore == 0 && ses->map && ses->map->in_room && ses->map->nofollow == 0)
1131 	{
1132 		int quiet, follow;
1133 
1134 		quiet = HAS_BIT(ses->map->flags, MAP_FLAG_QUIET);
1135 
1136 		gtd->level->input += quiet;
1137 
1138 		follow = follow_map(ses, command);
1139 
1140 		gtd->level->input -= quiet;
1141 
1142 		if (follow)
1143 		{
1144 			return;
1145 		}
1146 	}
1147 
1148 	write_line_mud(ses, output, size);
1149 }
1150 
1151 
1152 /*
1153 	Check line for triggers
1154 */
1155 
do_one_line(char * line,struct session * ses)1156 void do_one_line(char *line, struct session *ses)
1157 {
1158 	char *strip, *buf;
1159 
1160 	if (gtd->level->ignore)
1161 	{
1162 		return;
1163 	}
1164 
1165 	push_call("do_one_line(%s,%p)",ses->name,line);
1166 
1167 	push_script_stack(ses, LIST_VARIABLE);
1168 
1169 	strip = str_alloc_stack(0);
1170 	buf   = str_alloc_stack(0);
1171 
1172 	strip_vt102_codes(line, strip);
1173 
1174 	if (!HAS_BIT(ses->list[LIST_ACTION]->flags, LIST_FLAG_IGNORE))
1175 	{
1176 		check_all_actions(ses, line, strip, buf);
1177 	}
1178 
1179 	if (!HAS_BIT(ses->list[LIST_PROMPT]->flags, LIST_FLAG_IGNORE))
1180 	{
1181 		check_all_prompts(ses, line, strip);
1182 	}
1183 
1184 	if (!HAS_BIT(ses->list[LIST_GAG]->flags, LIST_FLAG_IGNORE))
1185 	{
1186 		check_all_gags(ses, line, strip);
1187 	}
1188 
1189 	if (!HAS_BIT(ses->list[LIST_SUBSTITUTE]->flags, LIST_FLAG_IGNORE))
1190 	{
1191 		check_all_substitutions(ses, line, strip);
1192 	}
1193 
1194 	if (!HAS_BIT(ses->list[LIST_HIGHLIGHT]->flags, LIST_FLAG_IGNORE))
1195 	{
1196 		check_all_highlights(ses, line, strip);
1197 	}
1198 
1199 	if (HAS_BIT(ses->log->mode, LOG_FLAG_NEXT))
1200 	{
1201 		logit(ses, line, ses->log->next_file, LOG_FLAG_LINEFEED);
1202 
1203 		DEL_BIT(ses->log->mode, LOG_FLAG_NEXT);
1204 	}
1205 
1206 	pop_script_stack();
1207 
1208 	pop_call();
1209 	return;
1210 }
1211