switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Utils / Logger / SyslogUDPTarget.cc
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief SyslogUDPTarget non-inline non-template implementation */
30
31 #include "SyslogUDPTarget.hh"
32 //#include "SyslogUDPTarget.ih"
33
34 // Custom includes
35 #include <sstream>
36 #include <boost/algorithm/string/trim.hpp>
37 #include <boost/tokenizer.hpp>
38 #include <senf/Utils/Console/ParsedCommand.hh>
39 #include <senf/Utils/Console/Traits.hh>
40 #include <senf/Utils/Console/ScopedDirectory.hh>
41
42 //#include "SyslogUDPTarget.mpp"
43 #define prefix_
44 //-/////////////////////////////////////////////////////////////////////////////////////////////////
45
46 prefix_ void senf::log::SyslogUDPTarget::init()
47 {
48     namespace kw = console::kw;
49     namespace fty = console::factory;
50
51     consoleDir().remove("format");
52     consoleDir()
53         .add("format", fty::Command(&SyslogUDPTarget::consoleFormat, this)
54              .doc("Show the current log message format.") );
55     consoleDir()
56         .add("syslog", fty::Command(SENF_MEMBINDFNP(void, SyslogUDPTarget, syslog, (bool)))
57              .arg("flag","new syslog format state",
58                   kw::default_value=true)
59              .doc("Change the syslog format flag. By default, syslog formating is enabled. In this\n"
60                   "state, the udp target will send out minimal but valid syslog format messages.\n"
61                   "\n"
62                   "Disabling syslog format will remove the syslog prefix. Log messages will then be\n"
63                   "sent using plain UDP.") );
64 }
65
66 prefix_ void senf::log::SyslogUDPTarget::v_write(time_type timestamp, std::string const & stream,
67                                                  std::string const & area, unsigned level,
68                                                  std::string const & message)
69 {
70     std::string m (message);
71     boost::trim_right(m);
72     detail::quoteNonPrintable(m);
73
74     std::stringstream prfstream;
75     // The space after the '>' is there on purpose: It ensures, that the prefix (which may be empty)
76     // or message will not inadvertently be interpreted as date or hostname by a receiving syslog
77     // daemon or proxy
78     if (syslogFormat_)
79         prfstream << '<' << (facility_ | SyslogTarget::LEVELMAP[level]) << "> ";
80     prfstream << prefix(timestamp, stream, area, level);
81     std::string const & prf (prfstream.str());
82
83     typedef boost::char_separator<char> Separator;
84     typedef boost::tokenizer<Separator> Tokenizer;
85     Separator separator ("\n");
86     Tokenizer tokenizer (m, separator);
87     Tokenizer::iterator i (tokenizer.begin());
88     Tokenizer::iterator const i_end (tokenizer.end());
89
90     std::string line;
91     unsigned sz (896-prf.size());
92     for (; i != i_end; ++i)
93         for (unsigned j (0); j < i->size(); j += sz) {
94             line = prf;
95             line += std::string(*i, j, sz);
96             handle_.write(line);
97         }
98 }
99
100 prefix_ void senf::log::SyslogUDPTarget::consoleFormat(std::ostream & os)
101 {
102     LogFormat::consoleFormat(os);
103     os << "syslog prefix " << (syslogFormat_ ? "enabled" : "disabled") << "\n";
104 }
105
106 namespace senf {
107 namespace log {
108
109     SENF_CONSOLE_REGISTER_ENUM_MEMBER(SyslogUDPTarget, LogFacility,
110                                       (AUTHPRIV)(CRON)(DAEMON)(FTP)(KERN)(LPR)(MAIL)(NEWS)(SYSLOG)
111                                       (USER)(UUCP)(LOCAL0)(LOCAL1)(LOCAL2)(LOCAL3)(LOCAL4)(LOCAL5)
112                                       (LOCAL6)(LOCAL7));
113
114 }}
115
116 prefix_ senf::log::SyslogUDPTarget::RegisterConsole::RegisterConsole()
117 {
118     namespace kw = console::kw;
119     namespace fty = console::factory;
120
121     detail::TargetRegistry::instance().consoleDir()
122         .add("udp-target",
123              fty::Command<console::DirectoryNode::ptr (*)(INet4SocketAddress const &,
124                                                                 LogFacility)
125              >(&RegisterConsole::create)
126              .arg("address", "target address to send log messages to")
127              .arg("facility", "syslog facility to send messages to. One of\n"
128                   "                  AUTHPRIV CRON DAEMON FTP KERN LPR MAIL NEWS SYSLOG USER\n"
129                   "                  UUCP LOCAL0 LOCAL1 LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7",
130                   kw::default_value = USER)
131              .doc("Create new udp target. The {address} can be an IPv4 or IPv6 address. If the port\n"
132                   "number is omitted, it defaults to the default syslog port 514. Examples:\n"
133                   "\n"
134                   "Create new udp target sending messages to the syslog daemon running at localhost\n"
135                   "    $ udp-target localhost\n"
136                   "    <Directory '/sys/log/udp-127.0.0.1:514'>\n"
137                   "\n"
138                   "In a configuration file, create new udp target and set some parameters (If\n"
139                   "written on one line, this works at the console too:\n"
140                   "    /sys/log/udp-target localhost:2345 LOCAL2 {\n"
141                   "        route (IMPORTANT);             # route all important messages\n"
142                   "        timeFormat \"\";               # use non-formatted time format\n"
143                   "        showArea false;                # don't show log area\n"
144                   "        syslog false;                  # no syslog format, just plain udp\n"
145                   "    }\n") );
146     detail::TargetRegistry::instance().consoleDir()
147         .add("udp-target",
148              fty::Command<console::DirectoryNode::ptr (*)(INet4Address const &, LogFacility)
149              >(&RegisterConsole::create)
150              .arg("address")
151              .arg("facility", kw::default_value = USER) );
152     detail::TargetRegistry::instance().consoleDir()
153         .add("udp-target",
154              fty::Command<console::DirectoryNode::ptr (*)(INet6SocketAddress const &, LogFacility)
155              >(&RegisterConsole::create)
156              .arg("address")
157              .arg("facility", kw::default_value = USER) );
158     detail::TargetRegistry::instance().consoleDir()
159         .add("udp-target",
160              fty::Command<console::DirectoryNode::ptr (*)(INet6Address const &, LogFacility)
161              >(&RegisterConsole::create)
162              .arg("address")
163              .arg("facility", kw::default_value = USER) );
164 }
165
166 prefix_ boost::shared_ptr<senf::console::DirectoryNode>
167 senf::log::SyslogUDPTarget::RegisterConsole::create(INet4SocketAddress const & target,
168                                                     LogFacility facility)
169 {
170     std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
171     Target & tg (*tp.get());
172     detail::TargetRegistry::instance().dynamicTarget(tp);
173     return tg.consoleDir().node().thisptr();
174 }
175
176 prefix_ boost::shared_ptr<senf::console::DirectoryNode>
177 senf::log::SyslogUDPTarget::RegisterConsole::create(INet4Address const & target,
178                                                     LogFacility facility)
179 {
180     std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
181     Target & tg (*tp.get());
182     detail::TargetRegistry::instance().dynamicTarget(tp);
183     return tg.consoleDir().node().thisptr();
184 }
185
186 prefix_ boost::shared_ptr<senf::console::DirectoryNode>
187 senf::log::SyslogUDPTarget::RegisterConsole::create(INet6SocketAddress const & target,
188                                                     LogFacility facility)
189 {
190     std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
191     Target & tg (*tp.get());
192     detail::TargetRegistry::instance().dynamicTarget(tp);
193     return tg.consoleDir().node().thisptr();
194 }
195
196 prefix_ boost::shared_ptr<senf::console::DirectoryNode>
197 senf::log::SyslogUDPTarget::RegisterConsole::create(INet6Address const & target,
198                                                     LogFacility facility)
199 {
200     std::auto_ptr<Target> tp (new SyslogUDPTarget(target, facility));
201     Target & tg (*tp.get());
202     detail::TargetRegistry::instance().dynamicTarget(tp);
203     return tg.consoleDir().node().thisptr();
204 }
205
206 //-/////////////////////////////////////////////////////////////////////////////////////////////////
207 #undef prefix_
208 //#include "SyslogUDPTarget.mpp"
209
210 \f
211 // Local Variables:
212 // mode: c++
213 // fill-column: 100
214 // comment-column: 40
215 // c-file-style: "senf"
216 // indent-tabs-mode: nil
217 // ispell-local-dictionary: "american"
218 // compile-command: "scons -u test"
219 // End: