/*
 *  OpenVPN -- An application to securely tunnel IP networks
 *             over a single TCP/UDP port, with support for SSL/TLS-based
 *             session authentication and key exchange,
 *             packet encryption, packet authentication, and
 *             packet compression.
 *
 *  Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
 *
 *  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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#elif defined(_MSC_VER)
#include "config-msvc.h"
#endif

#include "syshead.h"

#include "status.h"
#include "perf.h"
#include "misc.h"
#include "fdmisc.h"

#include "memdbg.h"

/*
 * printf-style interface for outputting status info
 */

static const char *
print_status_mode(unsigned int flags)
{
    switch (flags)
    {
        case STATUS_OUTPUT_WRITE:
            return "WRITE";

        case STATUS_OUTPUT_READ:
            return "READ";

        case STATUS_OUTPUT_READ|STATUS_OUTPUT_WRITE:
            return "READ/WRITE";

        default:
            return "UNDEF";
    }
}

struct status_output *
status_open(const char *filename,
            const int refresh_freq,
            const int msglevel,
            const struct virtual_output *vout,
            const unsigned int flags)
{
    struct status_output *so = NULL;
    if (filename || msglevel >= 0 || vout)
    {
        ALLOC_OBJ_CLEAR(so, struct status_output);
        so->flags = flags;
        so->msglevel = msglevel;
        so->vout = vout;
        so->fd = -1;
        buf_reset(&so->read_buf);
        event_timeout_clear(&so->et);
        if (filename)
        {
            switch (so->flags)
            {
                case STATUS_OUTPUT_WRITE:
                    so->fd = platform_open(filename,
                                           O_CREAT | O_TRUNC | O_WRONLY,
                                           S_IRUSR | S_IWUSR);
                    break;

                case STATUS_OUTPUT_READ:
                    so->fd = platform_open(filename,
                                           O_RDONLY,
                                           S_IRUSR | S_IWUSR);
                    break;

                case STATUS_OUTPUT_READ|STATUS_OUTPUT_WRITE:
                    so->fd = platform_open(filename,
                                           O_CREAT | O_RDWR,
                                           S_IRUSR | S_IWUSR);
                    break;

                default:
                    ASSERT(0);
            }
            if (so->fd >= 0)
            {
                so->filename = string_alloc(filename, NULL);
                set_cloexec(so->fd);

                /* allocate read buffer */
                if (so->flags & STATUS_OUTPUT_READ)
                {
                    so->read_buf = alloc_buf(512);
                }
            }
            else
            {
                msg(M_WARN, "Note: cannot open %s for %s", filename, print_status_mode(so->flags));
                so->errors = true;
            }
        }
        else
        {
            so->flags = STATUS_OUTPUT_WRITE;
        }

        if ((so->flags & STATUS_OUTPUT_WRITE) && refresh_freq > 0)
        {
            event_timeout_init(&so->et, refresh_freq, 0);
        }
    }
    return so;
}

bool
status_trigger(struct status_output *so)
{
    if (so)
    {
        struct timeval null;
        CLEAR(null);
        return event_timeout_trigger(&so->et, &null, ETT_DEFAULT);
    }
    else
    {
        return false;
    }
}

void
status_reset(struct status_output *so)
{
    if (so && so->fd >= 0)
    {
        lseek(so->fd, (off_t)0, SEEK_SET);
    }
}

void
status_flush(struct status_output *so)
{
    if (so && so->fd >= 0 && (so->flags & STATUS_OUTPUT_WRITE))
    {
#if defined(HAVE_FTRUNCATE)
        {
            const off_t off = lseek(so->fd, (off_t)0, SEEK_CUR);
            if (ftruncate(so->fd, off) != 0)
            {
                msg(M_WARN | M_ERRNO, "Failed to truncate status file");
            }
        }
#elif defined(HAVE_CHSIZE)
        {
            const long off = (long) lseek(so->fd, (off_t)0, SEEK_CUR);
            chsize(so->fd, off);
        }
#else  /* if defined(HAVE_FTRUNCATE) */
#warning both ftruncate and chsize functions appear to be missing from this OS
#endif

        /* clear read buffer */
        if (buf_defined(&so->read_buf))
        {
            ASSERT(buf_init(&so->read_buf, 0));
        }
    }
}

/* return false if error occurred */
bool
status_close(struct status_output *so)
{
    bool ret = true;
    if (so)
    {
        if (so->errors)
        {
            ret = false;
        }
        if (so->fd >= 0)
        {
            if (close(so->fd) < 0)
            {
                ret = false;
            }
        }
        if (so->filename)
        {
            free(so->filename);
        }
        if (buf_defined(&so->read_buf))
        {
            free_buf(&so->read_buf);
        }
        free(so);
    }
    else
    {
        ret = false;
    }
    return ret;
}

#define STATUS_PRINTF_MAXLEN 512

void
status_printf(struct status_output *so, const char *format, ...)
{
    if (so && (so->flags & STATUS_OUTPUT_WRITE))
    {
        char buf[STATUS_PRINTF_MAXLEN+2]; /* leave extra bytes for CR, LF */
        va_list arglist;
        int stat;

        va_start(arglist, format);
        stat = vsnprintf(buf, STATUS_PRINTF_MAXLEN, format, arglist);
        va_end(arglist);
        buf[STATUS_PRINTF_MAXLEN - 1] = 0;

        if (stat < 0 || stat >= STATUS_PRINTF_MAXLEN)
        {
            so->errors = true;
        }

        if (so->msglevel >= 0 && !so->errors)
        {
            msg(so->msglevel, "%s", buf);
        }

        if (so->fd >= 0 && !so->errors)
        {
            int len;
            strcat(buf, "\n");
            len = strlen(buf);
            if (len > 0)
            {
                if (write(so->fd, buf, len) != len)
                {
                    so->errors = true;
                }
            }
        }

        if (so->vout && !so->errors)
        {
            chomp(buf);
            (*so->vout->func)(so->vout->arg, so->vout->flags_default, buf);
        }
    }
}

bool
status_read(struct status_output *so, struct buffer *buf)
{
    bool ret = false;

    if (so && so->fd >= 0 && (so->flags & STATUS_OUTPUT_READ))
    {
        ASSERT(buf_defined(&so->read_buf));
        ASSERT(buf_defined(buf));
        while (true)
        {
            const int c = buf_read_u8(&so->read_buf);

            /* read more of file into buffer */
            if (c == -1)
            {
                int len;

                ASSERT(buf_init(&so->read_buf, 0));
                len = read(so->fd, BPTR(&so->read_buf), BCAP(&so->read_buf));
                if (len <= 0)
                {
                    break;
                }

                ASSERT(buf_inc_len(&so->read_buf, len));
                continue;
            }

            ret = true;

            if (c == '\r')
            {
                continue;
            }

            if (c == '\n')
            {
                break;
            }

            buf_write_u8(buf, c);
        }

        buf_null_terminate(buf);
    }

    return ret;
}
