xref: /haiku/src/servers/syslog_daemon/SyslogDaemon.cpp (revision 22440f4105cafc95cc1d49f9bc65bb395c527d86)
1 /*
2  * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "SyslogDaemon.h"
8 #include "listener_output.h"
9 #include "syslog_output.h"
10 
11 #include <Alert.h>
12 #include <Catalog.h>
13 #include <FindDirectory.h>
14 #include <Font.h>
15 #include <Path.h>
16 #include <TextView.h>
17 
18 #include <stdio.h>
19 #include <string.h>
20 
21 #undef B_TRANSLATION_CONTEXT
22 #define B_TRANSLATION_CONTEXT "SyslogDaemon"
23 
24 const char *kSignature = "application/x-vnd.Haiku-SystemLogger";
25 
26 
27 SyslogDaemon::SyslogDaemon()
28 	: BApplication(kSignature),
29 	fHandlerLock("handler lock")
30 {
31 }
32 
33 
34 void
35 SyslogDaemon::ReadyToRun()
36 {
37 	fPort = create_port(256, SYSLOG_PORT_NAME);
38 	fDaemon = spawn_thread(daemon_thread, "daemon", B_NORMAL_PRIORITY, this);
39 
40 	if (fPort >= B_OK && fDaemon >= B_OK) {
41 		init_syslog_output(this);
42 		init_listener_output(this);
43 
44 		resume_thread(fDaemon);
45 	} else
46 		Quit();
47 }
48 
49 
50 void
51 SyslogDaemon::AboutRequested()
52 {
53 	BPath path;
54 	find_directory(B_SYSTEM_LOG_DIRECTORY, &path);
55 	path.Append("syslog");
56 
57 	BString name(B_TRANSLATE("Syslog Daemon"));
58 	BString message;
59 	snprintf(message.LockBuffer(512), 512,
60 		B_TRANSLATE("%s\n\nThis daemon is responsible for collecting "
61 			"all system messages and write them to the system-wide log "
62 			"at \"%s\".\n\n"), name.String(), path.Path());
63 	message.UnlockBuffer();
64 
65 	BAlert *alert = new BAlert(name.String(), message.String(), B_TRANSLATE("OK"));
66 	BTextView *view = alert->TextView();
67 	BFont font;
68 
69 	view->SetStylable(true);
70 
71 	view->GetFont(&font);
72 	font.SetSize(21);
73 	font.SetFace(B_BOLD_FACE);
74 	view->SetFontAndColor(0, name.Length(), &font);
75 
76 	alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
77 	alert->Go(NULL);
78 }
79 
80 
81 bool
82 SyslogDaemon::QuitRequested()
83 {
84 	delete_port(fPort);
85 
86 	int32 returnCode;
87 	wait_for_thread(fDaemon, &returnCode);
88 
89 	return true;
90 }
91 
92 
93 void
94 SyslogDaemon::MessageReceived(BMessage *msg)
95 {
96 	switch (msg->what) {
97 		case SYSLOG_ADD_LISTENER:
98 		{
99 			BMessenger messenger;
100 			if (msg->FindMessenger("target", &messenger) == B_OK)
101 				add_listener(&messenger);
102 			break;
103 		}
104 		case SYSLOG_REMOVE_LISTENER:
105 		{
106 			BMessenger messenger;
107 			if (msg->FindMessenger("target", &messenger) == B_OK)
108 				remove_listener(&messenger);
109 			break;
110 		}
111 
112 		default:
113 			BApplication::MessageReceived(msg);
114 	}
115 }
116 
117 
118 void
119 SyslogDaemon::AddHandler(handler_func function)
120 {
121 	fHandlers.AddItem((void *)function);
122 }
123 
124 
125 void
126 SyslogDaemon::Daemon()
127 {
128 	char buffer[SYSLOG_MESSAGE_BUFFER_SIZE + 1];
129 	syslog_message &message = *(syslog_message *)buffer;
130 	int32 code;
131 
132 	while (true) {
133 		ssize_t bytesRead = read_port(fPort, &code, &message, sizeof(buffer));
134 		if (bytesRead == B_BAD_PORT_ID) {
135 			// we've been quit
136 			break;
137 		}
138 
139 		// if we don't get what we want, ignore it
140 		if (bytesRead < (ssize_t)sizeof(syslog_message) || code != SYSLOG_MESSAGE)
141 			continue;
142 
143 		// add terminating null byte
144 		message.message[bytesRead - sizeof(syslog_message)] = '\0';
145 
146 		if (!message.message[0]) {
147 			// ignore empty messages
148 			continue;
149 		}
150 
151 		fHandlerLock.Lock();
152 
153 		for (int32 i = fHandlers.CountItems(); i-- > 0;) {
154 			handler_func handle = (handler_func)fHandlers.ItemAt(i);
155 
156 			handle(message);
157 		}
158 
159 		fHandlerLock.Unlock();
160 	}
161 }
162 
163 
164 int32
165 SyslogDaemon::daemon_thread(void *data)
166 {
167 	((SyslogDaemon *)data)->Daemon();
168 	return B_OK;
169 }
170 
171 
172 int
173 main(int argc, char **argv)
174 {
175 	SyslogDaemon daemon;
176 	daemon.Run();
177 
178 	return 0;
179 }
180