blob: be691b2aa88322c2692e3b8c54eeb3114f5c5620 [file] [log] [blame]
/*
*
* AT chat library with GLib integration
*
* Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <glib.h>
#include "gatutil.h"
void g_at_util_debug_chat(gboolean in, const char *str, gsize len,
GAtDebugFunc debugf, gpointer user_data)
{
char type = in ? '<' : '>';
gsize escaped = 2; /* Enough for '<', ' ' */
char *escaped_str;
const char *esc = "<ESC>";
gsize esc_size = strlen(esc);
const char *ctrlz = "<CtrlZ>";
gsize ctrlz_size = strlen(ctrlz);
gsize i;
if (debugf == NULL || !len)
return;
for (i = 0; i < len; i++) {
char c = str[i];
if (g_ascii_isprint(c))
escaped += 1;
else if (c == '\r' || c == '\t' || c == '\n')
escaped += 2;
else if (c == 26)
escaped += ctrlz_size;
else if (c == 25)
escaped += esc_size;
else
escaped += 4;
}
escaped_str = g_try_malloc(escaped + 1);
if (escaped_str == NULL)
return;
escaped_str[0] = type;
escaped_str[1] = ' ';
memset(escaped_str + 2, '\0', escaped - 1);
for (escaped = 2, i = 0; i < len; i++) {
unsigned char c = str[i];
switch (c) {
case '\r':
escaped_str[escaped++] = '\\';
escaped_str[escaped++] = 'r';
break;
case '\t':
escaped_str[escaped++] = '\\';
escaped_str[escaped++] = 't';
break;
case '\n':
escaped_str[escaped++] = '\\';
escaped_str[escaped++] = 'n';
break;
case 26:
memcpy(escaped_str + escaped, ctrlz, ctrlz_size);
escaped += ctrlz_size;
break;
case 25:
memcpy(escaped_str + escaped, esc, esc_size);
escaped += esc_size;
break;
default:
if (g_ascii_isprint(c))
escaped_str[escaped++] = c;
else {
escaped_str[escaped++] = '\\';
escaped_str[escaped++] = '0' + ((c >> 6) & 07);
escaped_str[escaped++] = '0' + ((c >> 3) & 07);
escaped_str[escaped++] = '0' + (c & 07);
}
}
}
debugf(escaped_str, user_data);
g_free(escaped_str);
}
void g_at_util_debug_dump(gboolean in, const unsigned char *buf, gsize len,
GAtDebugFunc debugf, gpointer user_data)
{
char type = in ? '<' : '>';
GString *str;
gsize i;
if (debugf == NULL || !len)
return;
str = g_string_sized_new(1 + (len * 2));
if (str == NULL)
return;
g_string_append_c(str, type);
for (i = 0; i < len; i++)
g_string_append_printf(str, " %02x", buf[i]);
debugf(str->str, user_data);
g_string_free(str, TRUE);
}
void g_at_util_debug_hexdump(gboolean in, const unsigned char *buf, gsize len,
GAtDebugFunc debugf, gpointer user_data)
{
static const char hexdigits[] = "0123456789abcdef";
char str[68];
gsize i;
if (debugf == NULL || !len)
return;
str[0] = in ? '<' : '>';
for (i = 0; i < len; i++) {
str[((i % 16) * 3) + 1] = ' ';
str[((i % 16) * 3) + 2] = hexdigits[buf[i] >> 4];
str[((i % 16) * 3) + 3] = hexdigits[buf[i] & 0xf];
str[(i % 16) + 51] = g_ascii_isprint(buf[i]) ? buf[i] : '.';
if ((i + 1) % 16 == 0) {
str[49] = ' ';
str[50] = ' ';
str[67] = '\0';
debugf(str, user_data);
str[0] = ' ';
}
}
if (i % 16 > 0) {
gsize j;
for (j = (i % 16); j < 16; j++) {
str[(j * 3) + 1] = ' ';
str[(j * 3) + 2] = ' ';
str[(j * 3) + 3] = ' ';
str[j + 51] = ' ';
}
str[49] = ' ';
str[50] = ' ';
str[67] = '\0';
debugf(str, user_data);
}
}
gboolean g_at_util_setup_io(GIOChannel *io, GIOFlags flags)
{
GIOFlags io_flags;
if (g_io_channel_set_encoding(io, NULL, NULL) != G_IO_STATUS_NORMAL)
return FALSE;
g_io_channel_set_buffered(io, FALSE);
if (flags & G_IO_FLAG_SET_MASK) {
io_flags = g_io_channel_get_flags(io);
io_flags |= (flags & G_IO_FLAG_SET_MASK);
if (g_io_channel_set_flags(io, io_flags, NULL) !=
G_IO_STATUS_NORMAL)
return FALSE;
}
g_io_channel_set_close_on_unref(io, TRUE);
return TRUE;
}