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 
DO_COMMAND(do_showme)31 DO_COMMAND(do_showme)
32 {
33 	char *out, *tmp;
34 	int prompt;
35 
36 	out = str_alloc_stack(0);
37 	tmp = str_alloc_stack(0);
38 
39 	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
40 
41 	prompt = is_suffix(arg1, "\\") && !is_suffix(arg1, "\\\\");
42 
43 	substitute(ses, arg1, tmp, SUB_VAR|SUB_FUN);
44 	substitute(ses, tmp, arg1, SUB_COL|SUB_ESC);
45 
46 	arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
47 	arg = sub_arg_in_braces(ses, arg, arg3, GET_ONE, SUB_VAR|SUB_FUN);
48 
49 	do_one_line(arg1, ses);
50 
51 	if (ses->gagline > 0)
52 	{
53 		ses->gagline--;
54 
55 		show_debug(ses, LIST_GAG, "#DEBUG GAG {%d} {%s}", ses->gagline + 1, arg1);
56 
57 		return ses;
58 	}
59 
60 	if (*arg2)
61 	{
62 		split_show(ses, arg1, arg2, arg3);
63 
64 		return ses;
65 	}
66 
67 	str_cpy_printf(&out, "%s%s%s", COLOR_TEXT, arg1, COLOR_TEXT);
68 
69 	tintin_puts3(ses, out, prompt);
70 
71 	return ses;
72 }
73 
DO_COMMAND(do_echo)74 DO_COMMAND(do_echo)
75 {
76 	char *result, *out;
77 	int prompt;
78 
79 	result = arg2;
80 
81 	out = str_alloc_stack(0);
82 
83 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
84 
85 	format_string(ses, arg1, arg, result);
86 
87 	arg = get_arg_in_braces(ses, result, arg1, GET_ALL);
88 
89 	prompt = is_suffix(arg1, "\\") && !is_suffix(arg1, "\\\\");
90 
91 	substitute(ses, arg1, arg1, SUB_COL|SUB_ESC);
92 
93 	arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
94 	arg = sub_arg_in_braces(ses, arg, arg3, GET_ONE, SUB_VAR|SUB_FUN);
95 
96 	if (*arg2)
97 	{
98 		split_show(ses, arg1, arg2, arg3);
99 
100 		return ses;
101 	}
102 
103 	str_cpy_printf(&out, "%s%s%s", COLOR_TEXT, arg1, COLOR_TEXT);
104 
105 	tintin_puts3(ses, out, prompt);
106 
107 	return ses;
108 }
109 
show_message(struct session * ses,int index,char * format,...)110 void show_message(struct session *ses, int index, char *format, ...)
111 {
112 	struct listroot *root;
113 	char *buffer;
114 	va_list args;
115 
116 	push_call("show_message(%p,%p,%p)",ses,index,format);
117 
118 	root = ses->list[index];
119 
120 	if (gtd->level->verbose || gtd->level->debug)
121 	{
122 		goto display;
123 	}
124 
125 	if (HAS_BIT(root->flags, LIST_FLAG_DEBUG))
126 	{
127 		goto display;
128 	}
129 
130 	if (!HAS_BIT(root->flags, LIST_FLAG_MESSAGE))
131 	{
132 		goto end;
133 	}
134 
135 	if (gtd->level->input)
136 	{
137 		goto end;
138 	}
139 
140 	display:
141 
142 	va_start(args, format);
143 
144 	if (vasprintf(&buffer, format, args) == -1)
145 	{
146 		syserr_printf(ses, "show_message: vasprintf1:");
147 
148 		pop_call();
149 		return;
150 	}
151 
152 	va_end(args);
153 
154 	tintin_puts2(ses, buffer);
155 
156 	free(buffer);
157 
158 	pop_call();
159 	return;
160 
161 	end:
162 
163 	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
164 	{
165 		if (ses->log->file)
166 		{
167 			va_start(args, format);
168 
169 			if (vasprintf(&buffer, format, args) == -1)
170 			{
171 				syserr_printf(ses, "print_lines: vasprintf2:");
172 
173 				pop_call();
174 				return;
175 			}
176 			va_end(args);
177 
178 			logit(ses, buffer, ses->log->file, LOG_FLAG_LINEFEED);
179 
180 			free(buffer);
181 		}
182 	}
183 
184 	pop_call();
185 	return;
186 }
187 
show_error(struct session * ses,int index,char * format,...)188 void show_error(struct session *ses, int index, char *format, ...)
189 {
190 	struct listroot *root;
191 	char *buffer;
192 	va_list args;
193 
194 	push_call("show_error(%p,%p,%p)",ses,index,format);
195 
196 	va_start(args, format);
197 	if (vasprintf(&buffer, format, args) == -1)
198 	{
199 		syserr_printf(ses, "show_error: vasprintf:");
200 
201 		pop_call();
202 		return;
203 	}
204 	va_end(args);
205 
206 	check_all_events(ses, SUB_SEC|EVENT_FLAG_SYSTEM, 0, 1, "RECEIVED ERROR", buffer);
207 
208 	if (gtd->level->verbose || gtd->level->debug)
209 	{
210 		tintin_puts2(ses, buffer);
211 
212 		goto end;
213 	}
214 
215 	root = ses->list[index];
216 
217 	if (HAS_BIT(root->flags, LIST_FLAG_DEBUG))
218 	{
219 		tintin_puts2(ses, buffer);
220 
221 		goto end;
222 	}
223 
224 	if (HAS_BIT(root->flags, LIST_FLAG_MESSAGE))
225 	{
226 		tintin_puts2(ses, buffer);
227 
228 		goto end;
229 	}
230 
231 	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
232 	{
233 		if (ses->log->file)
234 		{
235 			logit(ses, buffer, ses->log->file, LOG_FLAG_LINEFEED);
236 		}
237 	}
238 
239 	end:
240 
241 	free(buffer);
242 
243 	pop_call();
244 	return;
245 }
246 
show_debug(struct session * ses,int index,char * format,...)247 void show_debug(struct session *ses, int index, char *format, ...)
248 {
249 	struct listroot *root;
250 	char buf[STRING_SIZE];
251 	va_list args;
252 
253 	push_call("show_debug(%p,%p,%p)",ses,index,format);
254 
255 	root = ses->list[index];
256 
257 	if (gtd->level->debug == 0 && !HAS_BIT(root->flags, LIST_FLAG_DEBUG) && !HAS_BIT(root->flags, LIST_FLAG_LOG))
258 	{
259 		pop_call();
260 		return;
261 	}
262 
263 	va_start(args, format);
264 
265 	vsprintf(buf, format, args);
266 
267 	va_end(args);
268 
269 	if (gtd->level->debug || HAS_BIT(root->flags, LIST_FLAG_DEBUG))
270 	{
271 		gtd->level->verbose++;
272 
273 		tintin_puts2(ses, buf);
274 
275 		gtd->level->verbose--;
276 
277 		pop_call();
278 		return;
279 	}
280 
281 	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
282 	{
283 		if (ses->log->file)
284 		{
285 			logit(ses, buf, ses->log->file, LOG_FLAG_LINEFEED);
286 		}
287 	}
288 	pop_call();
289 	return;
290 }
291 
show_info(struct session * ses,int index,char * format,...)292 void show_info(struct session *ses, int index, char *format, ...)
293 {
294 	struct listroot *root;
295 	char buf[STRING_SIZE];
296 	va_list args;
297 
298 	push_call("show_info(%p,%p,%p)",ses,index,format);
299 
300 	root = ses->list[index];
301 
302 	if (gtd->level->info == 0 && !HAS_BIT(root->flags, LIST_FLAG_INFO))
303 	{
304 		pop_call();
305 		return;
306 	}
307 
308 	va_start(args, format);
309 
310 	vsprintf(buf, format, args);
311 
312 	va_end(args);
313 
314 	gtd->level->verbose++;
315 
316 	tintin_puts(ses, buf);
317 
318 	gtd->level->verbose--;
319 
320 	pop_call();
321 	return;
322 }
323 
print_lines(struct session * ses,int flags,char * format,...)324 void print_lines(struct session *ses, int flags, char *format, ...)
325 {
326 	char *buffer, *str_buf;
327 	va_list args;
328 
329 	push_call("print_lines(%p,%d,%p,...)",ses,flags,format);
330 
331 	va_start(args, format);
332 
333 	if (vasprintf(&buffer, format, args) == -1)
334 	{
335 		syserr_printf(ses, "print_lines: vasprintf:");
336 
337 		pop_call();
338 		return;
339 	}
340 
341 	va_end(args);
342 
343 	if (flags)
344 	{
345 		str_buf = str_alloc_stack(strlen(buffer) * 2);
346 
347 		substitute(ses, buffer, str_buf, flags);
348 
349 		show_lines(ses, str_buf);
350 	}
351 	else
352 	{
353 		show_lines(ses, buffer);
354 	}
355 
356 	free(buffer);
357 
358 	pop_call();
359 	return;
360 }
361 
show_lines(struct session * ses,char * str)362 void show_lines(struct session *ses, char *str)
363 {
364 	char *ptf;
365 
366 	push_call("show_lines(%p,%p,...)",ses,str);
367 
368 	while (*str)
369 	{
370 		ptf = strchr(str, '\n');
371 
372 		if (ptf == NULL)
373 		{
374 			break;
375 		}
376 		*ptf++ = 0;
377 
378 		tintin_puts3(ses, str, FALSE);
379 
380 		str = ptf;
381 	}
382 	pop_call();
383 	return;
384 }
385 
386 
tintin_header(struct session * ses,int width,char * format,...)387 void tintin_header(struct session *ses, int width, char *format, ...)
388 {
389 	char arg[BUFFER_SIZE], buf[BUFFER_SIZE];
390 	va_list args;
391 	int cols;
392 
393 	push_call("tintin_header(%p,%p)",ses,format);
394 
395 	va_start(args, format);
396 	vsprintf(arg, format, args);
397 	va_end(args);
398 
399 	if (width)
400 	{
401 		cols = UMIN(width, get_scroll_cols(ses));
402 	}
403 	else
404 	{
405 		cols = get_scroll_cols(ses);
406 	}
407 
408 	if (cols < 2)
409 	{
410 		pop_call();
411 		return;
412 	}
413 
414 	if ((int) strlen(arg) > cols - 2)
415 	{
416 		arg[cols - 2] = 0;
417 	}
418 
419 	if (HAS_BIT(ses->config_flags, CONFIG_FLAG_SCREENREADER))
420 	{
421 		memset(buf, ' ', cols);
422 	}
423 	else
424 	{
425 		memset(buf, '#', cols);
426 	}
427 
428 	memcpy(&buf[(cols - strlen(arg)) / 2], arg, strlen(arg));
429 
430 	buf[cols] = 0;
431 
432 	tintin_puts2(ses, buf);
433 
434 	pop_call();
435 	return;
436 }
437 
tintin_printf2(struct session * ses,char * format,...)438 void tintin_printf2(struct session *ses, char *format, ...)
439 {
440 	char *buffer;
441 	va_list args;
442 
443 	push_call("tintin_printf2(%p,%p,...)",ses,format);
444 
445 	va_start(args, format);
446 	if (vasprintf(&buffer, format, args) == -1)
447 	{
448 		syserr_printf(ses, "tintin_printf2: vasprintf:");
449 
450 		pop_call();
451 		return;
452 	}
453 	va_end(args);
454 
455 	tintin_puts2(ses, buffer);
456 
457 	free(buffer);
458 
459 	pop_call();
460 	return;
461 }
462 
tintin_printf(struct session * ses,char * format,...)463 void tintin_printf(struct session *ses, char *format, ...)
464 {
465 	char buffer[BUFFER_SIZE];
466 	va_list args;
467 
468 	va_start(args, format);
469 	vsprintf(buffer, format, args);
470 	va_end(args);
471 
472 	tintin_puts(ses, buffer);
473 }
474 
475 /*
476 	Show string and fire triggers
477 */
478 
tintin_puts(struct session * ses,char * string)479 void tintin_puts(struct session *ses, char *string)
480 {
481 	if (ses == NULL)
482 	{
483 		ses = gtd->ses;
484 	}
485 
486 	do_one_line(string, ses);
487 
488 	if (ses->gagline)
489 	{
490 		ses->gagline--;
491 
492 		gtd->level->ignore++;
493 
494 		show_debug(ses, LIST_GAG, "#DEBUG GAG {%d} {%s}", ses->gagline + 1, string);
495 
496 		gtd->level->ignore--;
497 	}
498 	else
499 	{
500 		tintin_puts2(ses, string);
501 	}
502 }
503 
504 /*
505 	show string and don't fire triggers
506 */
507 
tintin_puts2(struct session * ses,char * string)508 void tintin_puts2(struct session *ses, char *string)
509 {
510 	char *output;
511 
512 	push_call("tintin_puts2(%p,%p)",ses,string);
513 
514 	output = str_alloc_stack(0);
515 
516 	str_cpy_printf(&output, "%s%s%s", COLOR_TEXT, string, COLOR_TEXT);
517 
518 	tintin_puts3(ses, output, FALSE);
519 
520 	pop_call();
521 	return;
522 }
523 
524 
525 
526 /*
527 	show string, no triggers, no color reset
528 */
529 
tintin_puts3(struct session * ses,char * string,int prompt)530 void tintin_puts3(struct session *ses, char *string, int prompt)
531 {
532 	char *output;
533 
534 	push_call("tintin_puts3(%p,%p,%d)",ses,string,prompt);
535 
536 	if (ses == NULL)
537 	{
538 		ses = gtd->ses;
539 	}
540 
541 	if (ses->line_capturefile)
542 	{
543 		if (ses->line_captureindex == 1)
544 		{
545 			set_nest_node_ses(ses, ses->line_capturefile, "{%d}{%s}", ses->line_captureindex++, string);
546 		}
547 		else
548 		{
549 			add_nest_node_ses(ses, ses->line_capturefile, "{%d}{%s}", ses->line_captureindex++, string);
550 		}
551 	}
552 
553 	if (gtd->level->quiet && gtd->level->verbose == 0)
554 	{
555 		pop_call();
556 		return;
557 	}
558 
559 	output = str_alloc_stack(0);
560 
561 	if (strip_vt102_strlen(ses, ses->more_output) != 0)
562 	{
563 		str_cpy_printf(&output, "\n%s", string);
564 	}
565 	else
566 	{
567 		str_cpy(&output, string);
568 	}
569 
570 	add_line_buffer(ses, output, prompt);
571 
572 	if (ses == gtd->ses)
573 	{
574 		if (!HAS_BIT(ses->flags, SES_FLAG_READMUD) && IS_SPLIT(ses))
575 		{
576 			save_pos(ses);
577 
578 			goto_pos(ses, ses->split->bot_row, ses->split->top_col);
579 		}
580 
581 		print_line(ses, &output, prompt);
582 
583 		if (!HAS_BIT(ses->flags, SES_FLAG_READMUD) && IS_SPLIT(ses))
584 		{
585 			restore_pos(ses);
586 		}
587 	}
588 
589 	pop_call();
590 	return;
591 }
592 
593