1/*
2 * Copyright 2003-2013, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <boot/vfs.h>
8#include <boot/stdio.h>
9#include <boot/net/NetStack.h>
10#include <boot/net/UDP.h>
11
12#include <errno.h>
13#include <stdarg.h>
14#include <string.h>
15
16#include <algorithm>
17
18
19//#undef stdout
20//#undef stdin
21//extern FILE *stdout;
22//extern FILE *stdin;
23
24
25//#define ENABLE_SYSLOG
26
27
28#undef errno
29int errno;
30
31
32int*
33_errnop(void)
34{
35	return &errno;
36}
37
38
39#ifdef ENABLE_SYSLOG
40
41static UDPSocket *sSyslogSocket = NULL;
42
43static void
44sendToSyslog(const char *message, int length)
45{
46	// Lazy-initialize the socket
47	if (sSyslogSocket == NULL) {
48		// Check if the network stack has been initialized yet
49		if (NetStack::Default() != NULL) {
50			sSyslogSocket = new(std::nothrow) UDPSocket;
51			sSyslogSocket->Bind(INADDR_ANY, 60514);
52		}
53	}
54
55	if (sSyslogSocket == NULL)
56		return;
57
58	// Strip trailing newlines
59	while (length > 0) {
60		if (message[length - 1] != '\n'
61			&& message[length - 1] != '\r') {
62			break;
63		}
64		length--;
65	}
66	if (length <= 0)
67		return;
68
69	char buffer[1500];
70		// same comment as in vfprintf applies...
71	const int facility = 0; // kernel
72	int severity = 7; // debug
73	int offset = snprintf(buffer, sizeof(buffer),
74		"<%d>1 - - Haiku - - - \xEF\xBB\xBF",
75		facility * 8 + severity);
76	length = std::min(length, (int)sizeof(buffer) - offset);
77	memcpy(buffer + offset, message, length);
78	sSyslogSocket->Send(INADDR_BROADCAST, 514, buffer, offset + length);
79}
80
81#endif
82
83
84int
85vfprintf(FILE *file, const char *format, va_list list)
86{
87	ConsoleNode *node = (ConsoleNode *)file;
88	char buffer[512];
89		// the buffer handling could (or should) be done better...
90
91	int length = vsnprintf(buffer, sizeof(buffer), format, list);
92	length = std::min(length, (int)sizeof(buffer) - 1);
93	if (length > 0) {
94		node->Write(buffer, length);
95#ifdef ENABLE_SYSLOG
96		sendToSyslog(buffer, length);
97#endif
98	}
99
100	return length;
101}
102
103
104int
105vprintf(const char *format, va_list args)
106{
107	return vfprintf(stdout, format, args);
108}
109
110
111int
112printf(const char *format, ...)
113{
114	va_list args;
115
116	va_start(args, format);
117	int status = vfprintf(stdout, format, args);
118	va_end(args);
119
120	return status;
121}
122
123
124int
125fprintf(FILE *file, const char *format, ...)
126{
127	va_list args;
128
129	va_start(args, format);
130	int status = vfprintf(file, format, args);
131	va_end(args);
132
133	return status;
134}
135
136
137int
138fputc(int c, FILE *file)
139{
140	if (file == NULL)
141		return B_FILE_ERROR;
142
143    status_t status;
144	char character = (char)c;
145
146	// we only support direct console output right now...
147	status = ((ConsoleNode *)file)->Write(&character, 1);
148
149#ifdef ENABLE_SYSLOG
150	sendToSyslog(&character, 1);
151#endif
152
153	if (status > 0)
154		return character;
155
156	return status;
157}
158
159
160int
161fputs(const char *string, FILE *file)
162{
163	if (file == NULL)
164		return B_FILE_ERROR;
165
166	status_t status = ((ConsoleNode *)file)->Write(string, strlen(string));
167	fputc('\n', file);
168
169#ifdef ENABLE_SYSLOG
170	sendToSyslog(string, strlen(string));
171#endif
172
173	return status;
174}
175
176
177int
178putc(int character)
179{
180	return fputc(character, stdout);
181}
182
183
184int
185putchar(int character)
186{
187	return fputc(character, stdout);
188}
189
190
191int
192puts(const char *string)
193{
194	return fputs(string, stdout);
195}
196
197