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