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