vfs: check userland buffers before reading them.
[haiku.git] / src / servers / syslog_daemon / SyslogDaemon.cpp
blobbb3796086e70d6fea8dccedb041eab018951d7a4
1 /*
2 * Copyright 2003-2015, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "SyslogDaemon.h"
9 #include <stdio.h>
10 #include <string.h>
12 #include <Alert.h>
13 #include <Catalog.h>
14 #include <FindDirectory.h>
15 #include <Font.h>
16 #include <Path.h>
17 #include <TextView.h>
19 #include <LaunchRoster.h>
20 #include <syscalls.h>
21 #include <syslog_daemon.h>
23 #include "listener_output.h"
24 #include "syslog_output.h"
27 #undef B_TRANSLATION_CONTEXT
28 #define B_TRANSLATION_CONTEXT "SyslogDaemon"
31 static const int32 kQuitDaemon = 'quit';
34 SyslogDaemon::SyslogDaemon()
36 BApplication(B_SYSTEM_LOGGER_SIGNATURE),
37 fHandlerLock("handler lock")
42 void
43 SyslogDaemon::ReadyToRun()
45 fPort = BLaunchRoster().GetPort("logger");
46 fDaemon = spawn_thread(_DaemonThread, "daemon", B_NORMAL_PRIORITY, this);
48 if (fPort >= 0 && fDaemon >= 0) {
49 _kern_register_syslog_daemon(fPort);
51 init_syslog_output(this);
52 init_listener_output(this);
54 resume_thread(fDaemon);
55 } else
56 Quit();
60 void
61 SyslogDaemon::AboutRequested()
63 BPath path;
64 find_directory(B_SYSTEM_LOG_DIRECTORY, &path);
65 path.Append("syslog");
67 BString name(B_TRANSLATE("Syslog Daemon"));
68 BString message;
69 snprintf(message.LockBuffer(512), 512,
70 B_TRANSLATE("%s\n\nThis daemon is responsible for collecting "
71 "all system messages and write them to the system-wide log "
72 "at \"%s\".\n\n"), name.String(), path.Path());
73 message.UnlockBuffer();
75 BAlert* alert = new BAlert(name.String(), message.String(),
76 B_TRANSLATE("OK"));
77 BTextView* view = alert->TextView();
78 BFont font;
80 view->SetStylable(true);
82 view->GetFont(&font);
83 font.SetSize(21);
84 font.SetFace(B_BOLD_FACE);
85 view->SetFontAndColor(0, name.Length(), &font);
87 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
88 alert->Go(NULL);
92 bool
93 SyslogDaemon::QuitRequested()
95 write_port(fPort, kQuitDaemon, NULL, 0);
96 wait_for_thread(fDaemon, NULL);
98 return true;
102 void
103 SyslogDaemon::MessageReceived(BMessage* message)
105 switch (message->what) {
106 case SYSLOG_ADD_LISTENER:
108 BMessenger messenger;
109 if (message->FindMessenger("target", &messenger) == B_OK)
110 add_listener(&messenger);
111 break;
113 case SYSLOG_REMOVE_LISTENER:
115 BMessenger messenger;
116 if (message->FindMessenger("target", &messenger) == B_OK)
117 remove_listener(&messenger);
118 break;
121 default:
122 BApplication::MessageReceived(message);
127 void
128 SyslogDaemon::AddHandler(handler_func function)
130 fHandlers.AddItem((void*)function);
134 void
135 SyslogDaemon::_Daemon()
137 char buffer[SYSLOG_MESSAGE_BUFFER_SIZE + 1];
138 syslog_message& message = *(syslog_message*)buffer;
139 int32 code;
141 while (true) {
142 ssize_t bytesRead = read_port(fPort, &code, &message, sizeof(buffer));
143 if (bytesRead == B_BAD_PORT_ID) {
144 // we've been quit
145 break;
148 if (code == kQuitDaemon)
149 return;
151 // if we don't get what we want, ignore it
152 if (bytesRead < (ssize_t)sizeof(syslog_message)
153 || code != SYSLOG_MESSAGE)
154 continue;
156 // add terminating null byte
157 message.message[bytesRead - sizeof(syslog_message)] = '\0';
159 if (!message.message[0]) {
160 // ignore empty messages
161 continue;
164 fHandlerLock.Lock();
166 for (int32 i = fHandlers.CountItems(); i-- > 0;) {
167 handler_func handle = (handler_func)fHandlers.ItemAt(i);
169 handle(message);
172 fHandlerLock.Unlock();
177 int32
178 SyslogDaemon::_DaemonThread(void* data)
180 ((SyslogDaemon*)data)->_Daemon();
181 return B_OK;
185 // #pragma mark -
189 main(int argc, char** argv)
191 SyslogDaemon daemon;
192 daemon.Run();
194 return 0;