xref: /haiku/src/servers/syslog_daemon/SyslogDaemon.cpp (revision 4f00613311d0bd6b70fa82ce19931c41f071ea4e)
1 /*
2 ** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 ** Distributed under the terms of the OpenBeOS 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.Be-SYSL";
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 	resume_thread(fDaemon);
37 
38 	if (fPort >= B_OK && fDaemon >= B_OK) {
39 		init_syslog_output(this);
40 		init_listener_output(this);
41 	} else
42 		Quit();
43 }
44 
45 
46 void
47 SyslogDaemon::AboutRequested()
48 {
49 	BPath path;
50 	find_directory(B_COMMON_LOG_DIRECTORY, &path);
51 	path.Append("syslog");
52 
53 	char message[512];
54 	sprintf(message,
55 		"Syslog Daemon\n\n"
56 		"This daemon is responsible for collecting "
57 		"all system messages and write them to the "
58 		"system-wide log at \"%s\".\n\n", path.Path());
59 
60 	BAlert *alert = new BAlert("Syslog Daemon", message, "Ok");
61 	BTextView *view = alert->TextView();
62 	BFont font;
63 
64 	view->SetStylable(true);
65 
66 	view->GetFont(&font);
67 	font.SetSize(21);
68 	font.SetFace(B_BOLD_FACE);
69 	view->SetFontAndColor(0, 13, &font);
70 
71 	alert->Go(NULL);
72 }
73 
74 
75 bool
76 SyslogDaemon::QuitRequested()
77 {
78 	delete_port(fPort);
79 
80 	int32 returnCode;
81 	wait_for_thread(fDaemon, &returnCode);
82 
83 	return true;
84 }
85 
86 
87 void
88 SyslogDaemon::MessageReceived(BMessage *msg)
89 {
90 	switch (msg->what) {
91 		case SYSLOG_ADD_LISTENER:
92 		{
93 			BMessenger messenger;
94 			if (msg->FindMessenger("target", &messenger) == B_OK)
95 				add_listener(&messenger);
96 			break;
97 		}
98 		case SYSLOG_REMOVE_LISTENER:
99 		{
100 			BMessenger messenger;
101 			if (msg->FindMessenger("target", &messenger) == B_OK)
102 				remove_listener(&messenger);
103 			break;
104 		}
105 
106 		default:
107 			BApplication::MessageReceived(msg);
108 	}
109 }
110 
111 
112 void
113 SyslogDaemon::AddHandler(handler_func function)
114 {
115 	fHandlers.AddItem((void *)function);
116 }
117 
118 
119 void
120 SyslogDaemon::Daemon()
121 {
122 	char buffer[4096];
123 	syslog_message &message = *(syslog_message *)buffer;
124 	int32 code;
125 
126 	while (true) {
127 		ssize_t bytesRead = read_port(fPort, &code, &message, sizeof(buffer));
128 		if (bytesRead == B_BAD_PORT_ID) {
129 			// we've been quit
130 			break;
131 		}
132 
133 		// if we don't get what we want, ignore it
134 		if (bytesRead < (ssize_t)sizeof(syslog_message) || code != SYSLOG_MESSAGE)
135 			continue;
136 
137 		fHandlerLock.Lock();
138 
139 		for (int32 i = fHandlers.CountItems(); i-- > 0;) {
140 			handler_func handle = (handler_func)fHandlers.ItemAt(i);
141 
142 			handle(message);
143 		}
144 
145 		fHandlerLock.Unlock();
146 	}
147 }
148 
149 
150 int32
151 SyslogDaemon::daemon_thread(void *data)
152 {
153 	((SyslogDaemon *)data)->Daemon();
154 	return B_OK;
155 }
156 
157 
158 int
159 main(int argc, char **argv)
160 {
161 	SyslogDaemon daemon;
162 	daemon.Run();
163 
164 	return 0;
165 }
166