1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
5    Copyright (C) 2011-2012 Planets Communications B.V.
6    Copyright (C) 2013-2020 Bareos GmbH & Co. KG
7 
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12 
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    Affero General Public License for more details.
17 
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22 */
23 
24 #include "lib/messages_resource.h"
25 #include "lib/message_destination_info.h"
26 
27 #include <algorithm>
28 #include <iostream>
29 
30 static pthread_mutex_t mutex_ = PTHREAD_MUTEX_INITIALIZER;
31 
MessagesResource()32 MessagesResource::MessagesResource() : BareosResource(), send_msg_types_(3, 0)
33 {
34   return;
35 }
36 
~MessagesResource()37 MessagesResource::~MessagesResource()
38 {
39   for (MessageDestinationInfo* d : dest_chain_) { delete d; }
40 }
41 
Lock() const42 void MessagesResource::Lock() const { P(mutex_); }
43 
Unlock() const44 void MessagesResource::Unlock() const { V(mutex_); }
45 
WaitNotInUse() const46 void MessagesResource::WaitNotInUse() const
47 {
48   // leaves mutex_ locked
49   Lock();
50   while (in_use_ || closing_) {
51     Unlock();
52     Bmicrosleep(0, 200);
53     Lock();
54   }
55 }
56 
ClearInUse()57 void MessagesResource::ClearInUse()
58 {
59   Lock();
60   in_use_ = false;
61   Unlock();
62 }
SetInUse()63 void MessagesResource::SetInUse()
64 {
65   WaitNotInUse();
66   in_use_ = true;
67   Unlock();
68 }
69 
SetClosing()70 void MessagesResource::SetClosing() { closing_ = true; }
71 
GetClosing() const72 bool MessagesResource::GetClosing() const { return closing_; }
73 
ClearClosing()74 void MessagesResource::ClearClosing()
75 {
76   Lock();
77   closing_ = false;
78   Unlock();
79 }
80 
IsClosing() const81 bool MessagesResource::IsClosing() const
82 {
83   Lock();
84   bool rtn = closing_;
85   Unlock();
86   return rtn;
87 }
88 
DuplicateDestChain() const89 std::vector<MessageDestinationInfo*> MessagesResource::DuplicateDestChain()
90     const
91 {
92   std::vector<MessageDestinationInfo*> temp_chain;
93 
94   for (MessageDestinationInfo* d : dest_chain_) {
95     MessageDestinationInfo* dnew = new MessageDestinationInfo(*d);
96     dnew->file_pointer_ = nullptr;
97     dnew->mail_filename_.clear();
98     temp_chain.push_back(dnew);
99   }
100 
101   return temp_chain;
102 }
103 
DuplicateResourceTo(MessagesResource & other) const104 void MessagesResource::DuplicateResourceTo(MessagesResource& other) const
105 {
106   other.dest_chain_ = DuplicateDestChain();
107   other.send_msg_types_ = send_msg_types_;
108 }
109 
110 /*
111  * Called only during parsing of the config file.
112  *
113  * Note, where in the case of dest_code FILE is a filename,
114  * but in the case of MAIL is a space separated list of
115  * email addresses, ...
116  */
AddToExistingChain(MessageDestinationCode dest_code,int msg_type,const std::string & where)117 bool MessagesResource::AddToExistingChain(MessageDestinationCode dest_code,
118                                           int msg_type,
119                                           const std::string& where)
120 {
121   auto pos = std::find_if(dest_chain_.rbegin(), dest_chain_.rend(),
122                           [&dest_code, where](MessageDestinationInfo* d) {
123                             return ((d->dest_code_ == dest_code)
124                                     && ((where.empty() && d->where_.empty())
125                                         || (where == d->where_)));
126                           });
127 
128   if (pos != dest_chain_.rend()) {
129     MessageDestinationInfo* d = *pos;
130     Dmsg4(850, "add to existing d=%p msgtype=%d destcode=%d where=%s\n", d,
131           msg_type, dest_code, NSTDPRNT(where));
132     SetBit(msg_type, d->msg_types_);
133     SetBit(msg_type, send_msg_types_);
134     return true;
135   }
136   return false;
137 }
138 
AddToNewChain(MessageDestinationCode dest_code,int msg_type,const std::string & where,const std::string & mail_cmd,const std::string & timestamp_format)139 void MessagesResource::AddToNewChain(MessageDestinationCode dest_code,
140                                      int msg_type,
141                                      const std::string& where,
142                                      const std::string& mail_cmd,
143                                      const std::string& timestamp_format)
144 {
145   MessageDestinationInfo* d;
146   d = new MessageDestinationInfo;
147   d->dest_code_ = dest_code;
148   SetBit(msg_type, d->msg_types_);   /* Set type bit in structure */
149   SetBit(msg_type, send_msg_types_); /* Set type bit in our local */
150 
151   d->where_ = where;
152   d->mail_cmd_ = mail_cmd;
153   d->timestamp_format_ = timestamp_format;
154 
155   dest_chain_.push_back(d);
156 
157   Dmsg6(850,
158         "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s "
159         "timestampformat=%s\n",
160         d, msg_type, dest_code, NSTDPRNT(where), NSTDPRNT(d->mail_cmd_),
161         NSTDPRNT(d->timestamp_format_));
162 }
163 
AddMessageDestination(MessageDestinationCode dest_code,int msg_type,const std::string & where,const std::string & mail_cmd,const std::string & timestamp_format)164 void MessagesResource::AddMessageDestination(
165     MessageDestinationCode dest_code,
166     int msg_type,
167     const std::string& where,
168     const std::string& mail_cmd,
169     const std::string& timestamp_format)
170 {
171   if (!AddToExistingChain(dest_code, msg_type, where)) {
172     AddToNewChain(dest_code, msg_type, where, mail_cmd, timestamp_format);
173   }
174 }
175 
176 /*
177  * Called only during parsing of the config file.
178  */
RemoveMessageDestination(MessageDestinationCode dest_code,int msg_type,const std::string & where)179 void MessagesResource::RemoveMessageDestination(
180     MessageDestinationCode dest_code,
181     int msg_type,
182     const std::string& where)
183 {
184   for (MessageDestinationInfo* d : dest_chain_) {
185     Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NSTDPRNT(d->where_));
186     if (BitIsSet(msg_type, d->msg_types_) && (dest_code == d->dest_code_)
187         && ((where.empty() && d->where_.empty()) || (where == d->where_))) {
188       Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n", d, msg_type,
189             dest_code);
190       ClearBit(msg_type, d->msg_types_);
191       Dmsg0(850, "Return RemoveMessageDestination\n");
192       return;
193     }
194   }
195 }
196