Ejemplo n.º 1
0
/*
 * Callback function invoked via smtp_start_session()
 */
static const char *message_cb(void **buf, int *len, void *arg)
{
    message_status_t *ms = (message_status_t*) arg;

    if (NULL == *buf) {
        *buf = malloc(8192);
    }
    if (NULL == len) {
        ms->sent_flag = SENT_NONE;
        return NULL;
    }

    /* Free the previous string */
    if (NULL != ms->prev_string) {
        free(ms->prev_string);
        ms->prev_string = NULL;
    }

    switch (ms->sent_flag) {
    case SENT_NONE:
        /* Send a blank line to signify the end of the header */
        ms->sent_flag = SENT_HEADER;
        ms->prev_string = NULL;
        *len = 2;
        return "\r\n";

    case SENT_HEADER:
        if (NULL != mca_plog_smtp_component.body_prefix) {
            ms->sent_flag = SENT_BODY_PREFIX;
            ms->prev_string = crnl(mca_plog_smtp_component.body_prefix);
            *len = strlen(ms->prev_string);
            return ms->prev_string;
        }

    case SENT_BODY_PREFIX:
        ms->sent_flag = SENT_BODY;
        ms->prev_string = crnl(ms->msg);
        *len = strlen(ms->prev_string);
        return ms->prev_string;

    case SENT_BODY:
        if (NULL != mca_plog_smtp_component.body_suffix) {
            ms->sent_flag = SENT_BODY_SUFFIX;
            ms->prev_string = crnl(mca_plog_smtp_component.body_suffix);
            *len = strlen(ms->prev_string);
            return ms->prev_string;
        }

    case SENT_BODY_SUFFIX:
    case SENT_ALL:
    default:
        ms->sent_flag = SENT_ALL;
        *len = 0;
        return NULL;
    }
}
Ejemplo n.º 2
0
static void write_normal(const char *buf, int size)
{
	if (size == 0)
		return;

	while (size > 0)
	{
		if (console->at_right_margin && console->wraparound_mode)
			crnl();
		/* Write to line end at most */
		int line_remain = min(size, console->width - console->x);
		if (console->insert_mode && console->x + line_remain < console->width)
			scroll(console->x, console->width - 1, console->y, console->y, line_remain, 0);
		DWORD bytes_written;
		WriteConsoleA(console->out, buf, line_remain, &bytes_written, NULL);
		console->x += line_remain;
		if (console->x == console->width)
		{
			console->x--;
			console->at_right_margin = 1;
		}
		buf += line_remain;
		size -= line_remain;
	}
}
Ejemplo n.º 3
0
static void control_escape(char ch)
{
	switch (ch)
	{
	case '[':
		for (int i = 0; i < CONSOLE_MAX_PARAMS; i++)
			console->params[i] = 0;
		console->param_count = 0;
		console->private_mode = 0;
		console->processor = control_escape_csi;
		break;

	case ']':
		console->params[0] = 0;
		console->string_len = -1;
		console->processor = control_escape_osc;
		break;

	case 'D': /* IND */
		nl();
		console->processor = NULL;
		break;

	case 'E': /* NEL */
		crnl();
		console->processor = NULL;
		break;

	case 'M': /* RI */
		if (console->y == console->scroll_top)
			scroll_down(1);
		else
			set_pos(console->x, console->y - 1);
		console->processor = NULL;
		break;

	case '(':
		console->processor = control_escape_set_default_character_set;
		break;

	case ')':
		console->processor = control_escape_set_alternate_character_set;
		break;

	case '#':
		console->processor = control_escape_sharp;
		break;

	default:
		log_error("control_escape(): Unhandled character %c\n", ch);
		console->processor = NULL;
	}
}
Ejemplo n.º 4
0
static size_t console_write(struct file *f, const char *buf, size_t count)
{
	struct console_file *console_file = (struct console_file *)f;

	console_lock();
	console_retrieve_state();
	#define OUTPUT() \
		if (last != -1) \
		{ \
			write_normal(buf + last, i - last); \
			last = -1; \
		}
	size_t last = -1;
	size_t i;
	for (i = 0; i < count; i++)
	{
		char ch = buf[i];
		if (ch == 0x1B) /* Escape */
		{
			OUTPUT();
			console->processor = control_escape;
		}
		else if (ch == '\t')
		{
			OUTPUT();
			int x = (console->x + 8) & ~7;
			if (x < console->width)
				set_pos(x, console->y);
			else
				set_pos(console->width - 1, console->y);
		}
		else if (ch == '\b')
		{
			OUTPUT();
			backspace(FALSE);
		}
		else if (ch == '\r')
		{
			OUTPUT();
			if (console->termios.c_oflag & OCRNL)
				nl();
			else
				cr();
		}
		else if (ch == '\n' || ch == '\v' || ch == '\f')
		{
			OUTPUT();
			if (console->termios.c_oflag & ONLCR)
				crnl();
			else
				nl();
		}
		else if (ch == 0x0E || ch == 0x0F)
		{
			/* Shift In and Shift Out */
			OUTPUT();
		}
		else if (console->processor)
			console->processor(ch);
		else if (ch < 0x20)
		{
			OUTPUT();
			log_error("Unhandled control character '\\x%x'\n", ch);
		}
		else if (last == -1)
			last = i;
	}
	OUTPUT();
	/* This will make the caret immediately visible */
	set_pos(console->x, console->y);
	console_unlock();
#if 0
	char str[4096];
	memcpy(str, buf, count);
	str[count] = '\n';
	str[count + 1] = 0;
	log_debug(str);
#endif
	return count;
}
Ejemplo n.º 5
0
static size_t console_read(struct file *f, char *buf, size_t count)
{
	struct console_file *console_file = (struct console_file *)f;

	console_lock();
	console_retrieve_state();

	size_t bytes_read = 0;
	while (console->input_buffer_head != console->input_buffer_tail && count > 0)
	{
		count--;
		buf[bytes_read++] = console->input_buffer[console->input_buffer_tail];
		console->input_buffer_tail = (console->input_buffer_tail + 1) % MAX_INPUT;
	}
	if (console->termios.c_lflag & ICANON)
	{
		char line[MAX_CANON + 1]; /* One more for storing CR or LF */
		size_t len = 0;
		while (count > 0)
		{
			INPUT_RECORD ir;
			DWORD read;
			ReadConsoleInputA(console->in, &ir, 1, &read);
			if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown)
			{
				switch (ir.Event.KeyEvent.wVirtualKeyCode)
				{
				case VK_RETURN:
				{
					if (!(console->termios.c_iflag & IGNCR))
						line[len++] = console->termios.c_iflag & ICRNL ? '\n' : '\r';
					size_t r = min(count, len);
					memcpy(buf + bytes_read, line, r);
					bytes_read += r;
					count -= r;
					if (r < len)
					{
						/* Some bytes not fit, add to input buffer */
						console_add_input(line + r, len - r);
					}
					if (console->termios.c_lflag & ECHO)
						crnl();
					goto read_done;
				}

				case VK_BACK:
				{
					if (len > 0)
					{
						len--;
						if (console->termios.c_lflag & ECHO)
							backspace(TRUE);
					}
				}
				default:
				{
					char ch = ir.Event.KeyEvent.uChar.AsciiChar;
					if (ch >= 0x20)
					{
						if (len < MAX_CANON)
						{
							line[len++] = ch;
							if (console->termios.c_lflag & ECHO)
								write_normal(&ch, 1);
						}
					}
				}
				}
			}
		}
	}
	else /* Non canonical mode */
	{
		int vtime = console->termios.c_cc[VTIME];
		int vmin = console->termios.c_cc[VMIN];
		while (count > 0)
		{
			if (bytes_read > 0 && bytes_read >= vmin)
				break;
			/* If vmin > 0 and vtime == 0, it is a blocking read, otherwise we need to poll first */
			if (vtime > 0 || (vmin == 0 && vtime == 0))
			{
				if (WaitForSingleObject(console->in, vtime * 100) == WAIT_TIMEOUT)
					break;
			}
			INPUT_RECORD ir;
			DWORD read;
			ReadConsoleInputA(console->in, &ir, 1, &read);
			if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown)
			{
				switch (ir.Event.KeyEvent.wVirtualKeyCode)
				{
				case VK_UP:
					console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOA" : "\x1B[A", 3);
					break;

				case VK_DOWN:
					console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOB" : "\x1B[B", 3);
					break;

				case VK_RIGHT:
					console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOC" : "\x1B[C", 3);
					break;

				case VK_LEFT:
					console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOD" : "\x1B[D", 3);
					break;

				case VK_HOME:
					console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOH" : "\x1B[H", 3);
					break;

				case VK_END:
					console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOF" : "\x1B[F", 3);
					break;

				case VK_INSERT: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[2~", 4); break;
				case VK_DELETE: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[3~", 4); break;
				case VK_PRIOR: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[5~", 4); break;
				case VK_NEXT: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[6~", 4); break;

				case VK_F1: console_buffer_add_string(buf, &bytes_read, &count, "\x1BOP", 3); break;
				case VK_F2: console_buffer_add_string(buf, &bytes_read, &count, "\x1BOQ", 3); break;
				case VK_F3: console_buffer_add_string(buf, &bytes_read, &count, "\x1BOR", 3); break;
				case VK_F4: console_buffer_add_string(buf, &bytes_read, &count, "\x1BOS", 3); break;
				case VK_F5: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[15~", 5); break;
				case VK_F6: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[17~", 5); break;
				case VK_F7: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[18~", 5); break;
				case VK_F8: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[19~", 5); break;
				case VK_F9: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[20~", 5); break;
				case VK_F10: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[21~", 5); break;
				case VK_F11: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[23~", 5); break;
				case VK_F12: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[24~", 5); break;
				case VK_F13: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[25~", 5); break;
				case VK_F14: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[26~", 5); break;
				case VK_F15: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[28~", 5); break;
				case VK_F16: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[29~", 5); break;
				case VK_F17: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[31~", 5); break;
				case VK_F18: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[32~", 5); break;
				case VK_F19: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[33~", 5); break;
				case VK_F20: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[34~", 5); break;

				default:
				{
					char ch = ir.Event.KeyEvent.uChar.AsciiChar;
					if (ch == '\r' && console->termios.c_iflag & IGNCR)
						break;
					if (ch == '\r' && console->termios.c_iflag & ICRNL)
						ch = '\n';
					else if (ch == '\n' && console->termios.c_iflag & ICRNL)
						ch = '\r';
					if (ch > 0)
					{
						count--;
						buf[bytes_read++] = ch;
						if (console->termios.c_lflag & ECHO)
							write_normal(&ch, 1);
					}
				}
				}
			}
			else
			{
				/* TODO: Other types of input */
			}
		}
	}
read_done:
	/* This will make the caret immediately visible */
	set_pos(console->x, console->y);
	console_unlock();
	return bytes_read;
}
Ejemplo n.º 6
0
static void write_normal(const char *buf, int size)
{
	if (size == 0)
		return;

	charset_func charset = console->charset == 0? console->g0_charset: console->g1_charset;
	WCHAR data[1024];
	int len = 0, displen = 0;
	int i = 0;
	while (i < size)
	{
		if (console->at_right_margin && console->wraparound_mode)
			crnl();
		/* Write to line end at most */
		int line_remain = min(size - i, console->width - console->x);
		len = 0;
		displen = 0;
		int seqlen = -1;
		while (displen < line_remain && i < size)
		{
			console->utf8_buf[console->utf8_buf_size++] = buf[i++];
			if (console->utf8_buf_size == 1)
				seqlen = utf8_get_sequence_len(console->utf8_buf[0]);
			if (seqlen < 0)
				console->utf8_buf_size = 0;
			if (seqlen == console->utf8_buf_size)
			{
				uint32_t codepoint = utf8_decode(console->utf8_buf);
				if (codepoint >= 0 && codepoint <= 0x10FFFF)
				{
					/* TODO: Handle non BMP characters (not supported by conhost) */
					int l = wcwidth(codepoint);
					if (l > 0)
					{
						if (displen + l > line_remain && console->wraparound_mode)
						{
							i--;
							console->utf8_buf_size--;
							break;
						}
						displen += l;
						data[len++] = charset(codepoint);
					}
				}
				console->utf8_buf_size = 0;
			}
		}

		if (console->insert_mode && console->x + displen < console->width)
			scroll(console->x, console->width - 1, console->y, console->y, displen, 0);
		
		DWORD chars_written;
		WriteConsoleW(console->out, data, len, &chars_written, NULL);
		console->x += displen;
		if (console->x == console->width)
		{
			console->x--;
			console->at_right_margin = 1;
		}
	}
}