switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Utils / Console / Config.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 Config non-inline non-template implementation */
30
31 #include "Config.hh"
32 #include "Config.ih"
33
34 // Custom includes
35 #include <senf/Utils/membind.hh>
36
37 //#include "Config.mpp"
38 #define prefix_
39 //-/////////////////////////////////////////////////////////////////////////////////////////////////
40
41 //-/////////////////////////////////////////////////////////////////////////////////////////////////
42 // senf::console::detail::RestrictedExecutor
43
44 prefix_ senf::console::detail::RestrictedExecutor::RestrictedExecutor(DirectoryNode & root)
45 {
46     executor_
47         .chroot(root)
48         .policy(senf::membind(&RestrictedExecutor::policyCallback, this));
49 }
50
51 prefix_ void
52 senf::console::detail::RestrictedExecutor::execute(std::ostream & output,
53                                                    ParseCommandInfo const & command)
54 {
55     executor_.execute(output, command);
56 }
57
58 prefix_ void
59 senf::console::detail::RestrictedExecutor::operator()(std::ostream & output,
60                                                       ParseCommandInfo const & command)
61 {
62     execute(output, command);
63 }
64
65 prefix_ senf::console::GenericNode &
66 senf::console::detail::RestrictedExecutor::getNode(ParseCommandInfo const & command)
67 {
68     return executor_.getNode(command);
69 }
70
71 prefix_ bool senf::console::detail::RestrictedExecutor::parsed(GenericNode & node)
72     const
73 {
74     ParsedNodes::const_iterator i (parsedNodes_.begin());
75     ParsedNodes::const_iterator const i_end (parsedNodes_.end());
76     for (; i != i_end; ++i)
77         if ( ! i->expired() && node.isChildOf(*(i->lock())) )
78             return true;
79     return false;
80 }
81
82 prefix_ void senf::console::detail::RestrictedExecutor::policyCallback(DirectoryNode & dir,
83                                                                        std::string const & name)
84 {
85     if (dir.hasChild(name)) {
86         GenericNode & item (dir.get(name));
87         if (restrict_ && ! item.isChildOf(*restrict_) && ! item.isDirectory())
88             throw Executor::IgnoreCommandException();
89         if (parsed(item))
90             throw Executor::IgnoreCommandException();
91     }
92     else if (restrict_ && ! dir.isChildOf(*restrict_))
93         throw Executor::IgnoreCommandException();
94 }
95
96 namespace {
97     struct RemoveNodesFn
98     {
99         RemoveNodesFn(senf::console::DirectoryNode::ptr newNode) : newNode_ (newNode) {}
100
101         bool operator()(senf::console::DirectoryNode::weak_ptr node) const
102             { return node.expired() || node.lock()->isChildOf(*newNode_); }
103
104         senf::console::DirectoryNode::ptr newNode_;
105     };
106 }
107
108 prefix_ void
109 senf::console::detail::RestrictedExecutor::insertParsedNode(DirectoryNode & node)
110 {
111     parsedNodes_.erase(
112         std::remove_if(parsedNodes_.begin(), parsedNodes_.end(), RemoveNodesFn(node.thisptr())),
113         parsedNodes_.end());
114     parsedNodes_.push_back(node.thisptr());
115 }
116
117 //-/////////////////////////////////////////////////////////////////////////////////////////////////
118 // senf::console::ConfigBundle
119
120 prefix_ void senf::console::ConfigBundle::parse()
121 {
122     detail::RestrictedExecutor::RestrictGuard guard (executor_);
123     parseInternal();
124 }
125
126 prefix_ void senf::console::ConfigBundle::parse(DirectoryNode & restrict)
127 {
128     detail::RestrictedExecutor::RestrictGuard guard (executor_, restrict);
129     parseInternal();
130 }
131
132 prefix_ void senf::console::ConfigBundle::parseInternal()
133 {
134     // It is valid to add additional sources at the end while parsing ...
135     for (Sources::const_iterator i (sources_.begin()); i != sources_.end(); ++i)
136         (*i)->parse(executor_);
137 }
138
139 //-/////////////////////////////////////////////////////////////////////////////////////////////////
140 // senf::console::detail::RestrictedExecutor::RestrictGuard
141
142 prefix_ senf::console::detail::RestrictedExecutor::RestrictGuard::
143 RestrictGuard(RestrictedExecutor & executor)
144     : executor_ (executor)
145 {
146     // This MUST BE root() not chroot() since restriction does NOT follow symlinks.
147     // Therefore, if chroot() is a directory of symlinks, restricting to it will
148     // execute NOTHING.
149     executor_.restrict_ = console::root().thisptr();
150 }
151
152 prefix_ senf::console::detail::RestrictedExecutor::RestrictGuard::
153 RestrictGuard(RestrictedExecutor & executor, DirectoryNode & restrict)
154     : executor_ (executor)
155 {
156     executor_.restrict_ = restrict.thisptr();
157 }
158
159 prefix_ senf::console::detail::RestrictedExecutor::RestrictGuard::~RestrictGuard()
160 {
161     if (! std::uncaught_exception())
162         executor_.insertParsedNode( *executor_.restrict_ );
163     executor_.restrict_ = console::root().thisptr();
164 }
165
166 //-/////////////////////////////////////////////////////////////////////////////////////////////////
167 // senf::console::detail::ConfigSource
168
169 prefix_ senf::console::detail::ConfigSource::~ConfigSource()
170 {}
171
172 //-/////////////////////////////////////////////////////////////////////////////////////////////////
173 #undef prefix_
174 //#include "Config.mpp"
175
176 \f
177 // Local Variables:
178 // mode: c++
179 // fill-column: 100
180 // comment-column: 40
181 // c-file-style: "senf"
182 // indent-tabs-mode: nil
183 // ispell-local-dictionary: "american"
184 // compile-command: "scons -u test"
185 // End: