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-2019 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_.begin(), dest_chain_.end(),
122                           [&dest_code](MessageDestinationInfo* d) {
123                             return d->dest_code_ == dest_code;
124                           });
125 
126   if (pos != dest_chain_.end()) {
127     MessageDestinationInfo* d = *pos;
128     bool append = false;
129 
130     if (where.empty() && d->where_.empty()) {
131       append = true;
132     } else if (where == d->where_) {
133       append = true;
134     }
135 
136     if (append) {
137       Dmsg4(850, "Add to existing d=%p msgtype=%d destcode=%d where=%s\n", pos,
138             msg_type, dest_code, NSTDPRNT(where));
139       SetBit(msg_type, d->msg_types_);
140       SetBit(msg_type, send_msg_types_);
141       return true;
142     }
143   }
144   return false;
145 }
146 
AddToNewChain(MessageDestinationCode dest_code,int msg_type,const std::string & where,const std::string & mail_cmd,const std::string & timestamp_format)147 void MessagesResource::AddToNewChain(MessageDestinationCode dest_code,
148                                      int msg_type,
149                                      const std::string& where,
150                                      const std::string& mail_cmd,
151                                      const std::string& timestamp_format)
152 {
153   MessageDestinationInfo* d;
154   d = new MessageDestinationInfo;
155   d->dest_code_ = dest_code;
156   SetBit(msg_type, d->msg_types_);   /* Set type bit in structure */
157   SetBit(msg_type, send_msg_types_); /* Set type bit in our local */
158 
159   d->where_ = where;
160   d->mail_cmd_ = mail_cmd;
161   d->timestamp_format_ = timestamp_format;
162 
163   // insert in front for compatibility to the former alist implementation */
164   dest_chain_.insert(dest_chain_.begin(), d);
165 
166   Dmsg6(850,
167         "add new d=%p msgtype=%d destcode=%d where=%s mailcmd=%s "
168         "timestampformat=%s\n",
169         d, msg_type, dest_code, NSTDPRNT(where), NSTDPRNT(d->mail_cmd_),
170         NSTDPRNT(d->timestamp_format_));
171 }
172 
AddMessageDestination(MessageDestinationCode dest_code,int msg_type,const std::string & where,const std::string & mail_cmd,const std::string & timestamp_format)173 void MessagesResource::AddMessageDestination(
174     MessageDestinationCode dest_code,
175     int msg_type,
176     const std::string& where,
177     const std::string& mail_cmd,
178     const std::string& timestamp_format)
179 {
180   if (!AddToExistingChain(dest_code, msg_type, where)) {
181     AddToNewChain(dest_code, msg_type, where, mail_cmd, timestamp_format);
182   }
183 }
184 
185 /*
186  * Called only during parsing of the config file.
187  */
RemoveMessageDestination(MessageDestinationCode dest_code,int msg_type,const std::string & where)188 void MessagesResource::RemoveMessageDestination(
189     MessageDestinationCode dest_code,
190     int msg_type,
191     const std::string& where)
192 {
193   for (MessageDestinationInfo* d : dest_chain_) {
194     Dmsg2(850, "Remove_msg_dest d=%p where=%s\n", d, NSTDPRNT(d->where_));
195     if (BitIsSet(msg_type, d->msg_types_) && (dest_code == d->dest_code_) &&
196         ((where.empty() && d->where_.empty()) || (where == d->where_))) {
197       Dmsg3(850, "Found for remove d=%p msgtype=%d destcode=%d\n", d, msg_type,
198             dest_code);
199       ClearBit(msg_type, d->msg_types_);
200       Dmsg0(850, "Return RemoveMessageDestination\n");
201       return;
202     }
203   }
204 }
205