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*
_errnop(void)33 _errnop(void)
34 {
35 return &errno;
36 }
37
38
39 #ifdef ENABLE_SYSLOG
40
41 static UDPSocket *sSyslogSocket = NULL;
42
43 static void
sendToSyslog(const char * message,int length)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
vfprintf(FILE * file,const char * format,va_list list)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
vprintf(const char * format,va_list args)105 vprintf(const char *format, va_list args)
106 {
107 return vfprintf(stdout, format, args);
108 }
109
110
111 int
printf(const char * format,...)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
fprintf(FILE * file,const char * format,...)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
fputc(int c,FILE * file)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
fputs(const char * string,FILE * file)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
putc(int character)178 putc(int character)
179 {
180 return fputc(character, stdout);
181 }
182
183
184 int
putchar(int character)185 putchar(int character)
186 {
187 return fputc(character, stdout);
188 }
189
190
191 int
puts(const char * string)192 puts(const char *string)
193 {
194 return fputs(string, stdout);
195 }
196
197