2
* OpenVPN -- An application to securely tunnel IP networks
3
* over a single TCP/UDP port, with support for SSL/TLS-based
4
* session authentication and key exchange,
5
* packet encryption, packet authentication, and
8
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License version 2
12
* as published by the Free Software Foundation.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program (see the file COPYING included with this
21
* distribution); if not, write to the Free Software Foundation, Inc.,
22
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
#elif defined(_MSC_VER)
28
#include "config-msvc.h"
41
* printf-style interface for outputting status info
45
print_status_mode (unsigned int flags)
49
case STATUS_OUTPUT_WRITE:
51
case STATUS_OUTPUT_READ:
53
case STATUS_OUTPUT_READ|STATUS_OUTPUT_WRITE:
60
struct status_output *
61
status_open (const char *filename,
62
const int refresh_freq,
64
const struct virtual_output *vout,
65
const unsigned int flags)
67
struct status_output *so = NULL;
68
if (filename || msglevel >= 0 || vout)
70
ALLOC_OBJ_CLEAR (so, struct status_output);
72
so->msglevel = msglevel;
75
buf_reset (&so->read_buf);
76
event_timeout_clear (&so->et);
81
case STATUS_OUTPUT_WRITE:
82
so->fd = platform_open (filename,
83
O_CREAT | O_TRUNC | O_WRONLY,
86
case STATUS_OUTPUT_READ:
87
so->fd = platform_open (filename,
91
case STATUS_OUTPUT_READ|STATUS_OUTPUT_WRITE:
92
so->fd = platform_open (filename,
101
so->filename = string_alloc (filename, NULL);
102
set_cloexec (so->fd);
104
/* allocate read buffer */
105
if (so->flags & STATUS_OUTPUT_READ)
106
so->read_buf = alloc_buf (512);
110
msg (M_WARN, "Note: cannot open %s for %s", filename, print_status_mode (so->flags));
115
so->flags = STATUS_OUTPUT_WRITE;
117
if ((so->flags & STATUS_OUTPUT_WRITE) && refresh_freq > 0)
119
event_timeout_init (&so->et, refresh_freq, 0);
126
status_trigger (struct status_output *so)
132
return event_timeout_trigger (&so->et, &null, ETT_DEFAULT);
139
status_trigger_tv (struct status_output *so, struct timeval *tv)
142
return event_timeout_trigger (&so->et, tv, ETT_DEFAULT);
148
status_reset (struct status_output *so)
150
if (so && so->fd >= 0)
151
lseek (so->fd, (off_t)0, SEEK_SET);
155
status_flush (struct status_output *so)
157
if (so && so->fd >= 0 && (so->flags & STATUS_OUTPUT_WRITE))
159
#if defined(HAVE_FTRUNCATE)
161
const off_t off = lseek (so->fd, (off_t)0, SEEK_CUR);
162
if (ftruncate (so->fd, off) != 0) {
163
msg (M_WARN, "Failed to truncate status file: %s", strerror(errno));
166
#elif defined(HAVE_CHSIZE)
168
const long off = (long) lseek (so->fd, (off_t)0, SEEK_CUR);
169
chsize (so->fd, off);
172
#warning both ftruncate and chsize functions appear to be missing from this OS
175
/* clear read buffer */
176
if (buf_defined (&so->read_buf))
178
ASSERT (buf_init (&so->read_buf, 0));
183
/* return false if error occurred */
185
status_close (struct status_output *so)
194
if (close (so->fd) < 0)
199
if (buf_defined (&so->read_buf))
200
free_buf (&so->read_buf);
208
#define STATUS_PRINTF_MAXLEN 512
211
status_printf (struct status_output *so, const char *format, ...)
213
if (so && (so->flags & STATUS_OUTPUT_WRITE))
215
char buf[STATUS_PRINTF_MAXLEN+2]; /* leave extra bytes for CR, LF */
219
va_start (arglist, format);
220
stat = vsnprintf (buf, STATUS_PRINTF_MAXLEN, format, arglist);
222
buf[STATUS_PRINTF_MAXLEN - 1] = 0;
224
if (stat < 0 || stat >= STATUS_PRINTF_MAXLEN)
227
if (so->msglevel >= 0 && !so->errors)
228
msg (so->msglevel, "%s", buf);
230
if (so->fd >= 0 && !so->errors)
237
if (write (so->fd, buf, len) != len)
242
if (so->vout && !so->errors)
245
(*so->vout->func) (so->vout->arg, so->vout->flags_default, buf);
251
status_read (struct status_output *so, struct buffer *buf)
255
if (so && so->fd >= 0 && (so->flags & STATUS_OUTPUT_READ))
257
ASSERT (buf_defined (&so->read_buf));
258
ASSERT (buf_defined (buf));
261
const int c = buf_read_u8 (&so->read_buf);
263
/* read more of file into buffer */
268
ASSERT (buf_init (&so->read_buf, 0));
269
len = read (so->fd, BPTR (&so->read_buf), BCAP (&so->read_buf));
273
ASSERT (buf_inc_len (&so->read_buf, len));
285
buf_write_u8 (buf, c);
288
buf_null_terminate (buf);