/*
 *
 *  Connection Manager
 *
 *  Copyright (C) 2007-2013  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

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <execinfo.h>
#include <dlfcn.h>
#include <fcntl.h>

#include "connman.h"

static const char *program_exec;
static const char *program_path;

#define MAX_FRAME_DEPTH   99
#define CRASH_DUMP_FILE   "/tmp/connmand.log"

#ifdef BUILD_CONFIG_RELEASE
#define kLogMask          (LOG_UPTO(LOG_INFO))
#else
#define kLogMask          (LOG_UPTO(LOG_DEBUG))
#endif

#if CONNMAN_DEBUG
unsigned int trace_depth = 0;
static const char * trace_tabs = "\t\t\t\t" "\t\t\t\t" "\t\t\t\t" "\t\t\t\t" "\t\t\t\t";
char trace_tabbuf[24] = { 0 };

void connman_create_indent(unsigned int depth, char *buffer)
{
	if (buffer == NULL)
		return;

	if (depth > 22) {
		depth = 22;
	}

	if (depth == 0) {
		buffer[0] = 0;
	} else {
		strncpy(buffer, trace_tabs, depth);
		buffer[depth] = 0;
	}
}
#endif

void connman_assert_handler(const char *name, const char *predicate, const char *message, const char *file, unsigned int line, void *value, int terminate)
{
	connman_debug("assertion: %s%s%s, %s file: %s, line: %d: value: %p\n",
		name != NULL ? name : "",
		name != NULL ? ": " : "",
		predicate,
		message != NULL ? message : "",
		file,
		line,
		value);

	if (terminate) {
		abort();
	}
}

/**
 * connman_info:
 * @format: format string
 * @Varargs: list of arguments
 *
 * Output general information
 */
void connman_info(const char *format, ...)
{
	va_list ap;

	va_start(ap, format);

	vsyslog(LOG_INFO, format, ap);

	va_end(ap);
}

/**
 * connman_warn:
 * @format: format string
 * @Varargs: list of arguments
 *
 * Output warning messages
 */
void connman_warn(const char *format, ...)
{
	va_list ap;

	va_start(ap, format);

	vsyslog(LOG_WARNING, format, ap);

	va_end(ap);
}

/**
 * connman_error:
 * @format: format string
 * @varargs: list of arguments
 *
 * Output error messages
 */
void connman_error(const char *format, ...)
{
	va_list ap;

	va_start(ap, format);

	vsyslog(LOG_ERR, format, ap);

	va_end(ap);
}

/**
 * connman_debug:
 * @format: format string
 * @varargs: list of arguments
 *
 * Output debug message
 */
void connman_debug(const char *format, ...)
{
	va_list ap;

	va_start(ap, format);

	vsyslog(LOG_DEBUG, format, ap);

	va_end(ap);
}

static void print_backtrace(unsigned int offset)
{
	void *frames[MAX_FRAME_DEPTH];
	size_t n_ptrs;
	unsigned int i;
	int outfd[2], infd[2];
	int pathlen;
	pid_t pid;

	if (!program_exec)
		return;

	pathlen = strlen(program_path);

#ifndef USE_ADDR2LINE

	int fd = open(CRASH_DUMP_FILE, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);

	if(fd != -1)
	{
		n_ptrs = backtrace(frames, G_N_ELEMENTS(frames));
		backtrace_symbols_fd(frames, n_ptrs, fd);
	}

	_exit(EXIT_FAILURE);

#else
	if (n_ptrs < offset)
		return;

	if (pipe(outfd) < 0)
		return;

	if (pipe(infd) < 0) {
		close(outfd[0]);
		close(outfd[1]);
		return;
	}

	pid = fork();
	if (pid < 0) {
		close(outfd[0]);
		close(outfd[1]);
		close(infd[0]);
		close(infd[1]);
		return;
	}

	if (pid == 0) {
		close(outfd[1]);
		close(infd[0]);

		dup2(outfd[0], STDIN_FILENO);
		dup2(infd[1], STDOUT_FILENO);

		execlp("addr2line", "-C", "-f", "-e", program_exec, NULL);

		exit(EXIT_FAILURE);
	}

	close(outfd[0]);
	close(infd[1]);

	connman_error("++++++++ backtrace ++++++++");

	for (i = offset; i < n_ptrs - 1; i++) {
		Dl_info info;
		char addr[20], buf[PATH_MAX * 2];
		int len, written;
		char *ptr, *pos;

		dladdr(frames[i], &info);

		len = snprintf(addr, sizeof(addr), "%p\n", frames[i]);
		if (len < 0)
			break;

		if (outfd[1] >= 0)
		{
			written = write(outfd[1], addr, len);
			if (written < 0)
				break;

			len = read(infd[0], buf, sizeof(buf) - 1);
			if (len < 0)
				break;
			else if (len == 0)
			{
				// if we got nothing, that means we got EOF, which means the read end was closed
				// so close the FD and set it to invalid so we know to not to bother with further
				// symbolication
				close(outfd[1]);
				outfd[1] = -1;
			}
		}
		else
		{
			len = 0;
		}

		buf[len] = '\0';

		pos = strchr(buf, '\n');
		if (pos != NULL)
		{
		    *pos++ = '\0';
		}

		if ((len == 0) || (strcmp(buf, "??") == 0)) {
			connman_error("#%-2u %p in %s", i - offset,
						frames[i], info.dli_fname);
			continue;
		}

		ptr = strchr(pos, '\n');
		*ptr++ = '\0';

		if (strncmp(pos, program_path, pathlen) == 0)
			pos += pathlen + 1;

		connman_error("#%-2u %p in %s() at %s", i - offset,
						frames[i], buf, pos);
	}

	connman_error("+++++++++++++++++++++++++++");

	kill(pid, SIGTERM);

	if (outfd[1] >= 0)
	{
		close(outfd[1]);
	}
	close(infd[0]);
#endif
}

static void signal_handler(int signo)
{
	connman_error("Aborting (signal %d) [%s]", signo, program_exec);

	print_backtrace(2);

	exit(EXIT_FAILURE);
}

static void signal_setup(sighandler_t handler)
{
	struct sigaction sa;
	sigset_t mask;

	sigemptyset(&mask);
	sa.sa_handler = handler;
	sa.sa_mask = mask;
	sa.sa_flags = 0;
	sigaction(SIGBUS, &sa, NULL);
	sigaction(SIGILL, &sa, NULL);
	sigaction(SIGFPE, &sa, NULL);
	sigaction(SIGSEGV, &sa, NULL);
	sigaction(SIGABRT, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);
}

extern struct connman_debug_desc __start___debug[];
extern struct connman_debug_desc __stop___debug[];

static gchar **enabled = NULL;

static bool is_enabled(struct connman_debug_desc *desc)
{
	int i;

	if (!enabled)
		return false;

	for (i = 0; enabled[i]; i++) {
		if (desc->name && g_pattern_match_simple(enabled[i],
							desc->name))
			return true;
		if (desc->file && g_pattern_match_simple(enabled[i],
							desc->file))
			return true;
	}

	return false;
}

void __connman_log_enable(struct connman_debug_desc *start,
					struct connman_debug_desc *stop)
{
	struct connman_debug_desc *desc;
	const char *name = NULL, *file = NULL;

	if (!start || !stop)
		return;

	for (desc = start; desc < stop; desc++) {
		if (desc->flags & CONNMAN_DEBUG_FLAG_ALIAS) {
			file = desc->file;
			name = desc->name;
			continue;
		}

		if (file || name) {
			if (g_strcmp0(desc->file, file) == 0) {
				if (!desc->name)
					desc->name = name;
			} else
				file = NULL;
		}

		if (is_enabled(desc))
			desc->flags |= CONNMAN_DEBUG_FLAG_PRINT;
	}
}

int __connman_log_init(const char *program, const char *debug,
		gboolean detach, gboolean backtrace,
		const char *program_name, const char *program_version)
{
	static char path[PATH_MAX];
	int option = LOG_NDELAY | LOG_PID;

	program_exec = program;
	program_path = getcwd(path, sizeof(path));

	if (debug)
		enabled = g_strsplit_set(debug, ":, ", 0);

	__connman_log_enable(__start___debug, __stop___debug);

	if (!detach)
		option |= LOG_PERROR;

	if (backtrace)
		signal_setup(signal_handler);

	setlogmask(kLogMask);
	openlog(basename(program), option, LOG_DAEMON);

	syslog(LOG_INFO, "%s version %s", program_name, program_version);

	return 0;
}

void __connman_log_cleanup(gboolean backtrace)
{
	syslog(LOG_INFO, "Exit");

	closelog();

	if (backtrace)
		signal_setup(SIG_DFL);

	g_strfreev(enabled);
}
