xref: /haiku/src/system/boot/loader/stdio.cpp (revision 899e0ef82b5624ace2ccfa5f5a58c8ebee54aaef)
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
29 int errno;
30 
31 
32 int*
33 _errnop(void)
34 {
35 	return &errno;
36 }
37 
38 
39 #ifdef ENABLE_SYSLOG
40 
41 static UDPSocket *sSyslogSocket = NULL;
42 
43 static void
44 sendToSyslog(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 
84 int
85 vfprintf(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 
104 int
105 vprintf(const char *format, va_list args)
106 {
107 	return vfprintf(stdout, format, args);
108 }
109 
110 
111 int
112 printf(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 
124 int
125 fprintf(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 
137 int
138 fputc(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 
160 int
161 fputs(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 
177 int
178 putc(int character)
179 {
180 	return fputc(character, stdout);
181 }
182 
183 
184 int
185 putchar(int character)
186 {
187 	return fputc(character, stdout);
188 }
189 
190 
191 int
192 puts(const char *string)
193 {
194 	return fputs(string, stdout);
195 }
196 
197