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_TRANSLATE_CONTEXT 22 #define B_TRANSLATE_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_COMMON_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->Go(NULL); 77 } 78 79 80 bool 81 SyslogDaemon::QuitRequested() 82 { 83 delete_port(fPort); 84 85 int32 returnCode; 86 wait_for_thread(fDaemon, &returnCode); 87 88 return true; 89 } 90 91 92 void 93 SyslogDaemon::MessageReceived(BMessage *msg) 94 { 95 switch (msg->what) { 96 case SYSLOG_ADD_LISTENER: 97 { 98 BMessenger messenger; 99 if (msg->FindMessenger("target", &messenger) == B_OK) 100 add_listener(&messenger); 101 break; 102 } 103 case SYSLOG_REMOVE_LISTENER: 104 { 105 BMessenger messenger; 106 if (msg->FindMessenger("target", &messenger) == B_OK) 107 remove_listener(&messenger); 108 break; 109 } 110 111 default: 112 BApplication::MessageReceived(msg); 113 } 114 } 115 116 117 void 118 SyslogDaemon::AddHandler(handler_func function) 119 { 120 fHandlers.AddItem((void *)function); 121 } 122 123 124 void 125 SyslogDaemon::Daemon() 126 { 127 char buffer[SYSLOG_MESSAGE_BUFFER_SIZE + 1]; 128 syslog_message &message = *(syslog_message *)buffer; 129 int32 code; 130 131 while (true) { 132 ssize_t bytesRead = read_port(fPort, &code, &message, sizeof(buffer)); 133 if (bytesRead == B_BAD_PORT_ID) { 134 // we've been quit 135 break; 136 } 137 138 // if we don't get what we want, ignore it 139 if (bytesRead < (ssize_t)sizeof(syslog_message) || code != SYSLOG_MESSAGE) 140 continue; 141 142 // add terminating null byte 143 message.message[bytesRead - sizeof(syslog_message)] = '\0'; 144 145 if (!message.message[0]) { 146 // ignore empty messages 147 continue; 148 } 149 150 fHandlerLock.Lock(); 151 152 for (int32 i = fHandlers.CountItems(); i-- > 0;) { 153 handler_func handle = (handler_func)fHandlers.ItemAt(i); 154 155 handle(message); 156 } 157 158 fHandlerLock.Unlock(); 159 } 160 } 161 162 163 int32 164 SyslogDaemon::daemon_thread(void *data) 165 { 166 ((SyslogDaemon *)data)->Daemon(); 167 return B_OK; 168 } 169 170 171 int 172 main(int argc, char **argv) 173 { 174 SyslogDaemon daemon; 175 daemon.Run(); 176 177 return 0; 178 } 179