fix endless-loop-at-shutdown bug now that abstract UI request buffers are used
[ardour.git] / libs / pbd / epa.cc
1 /*
2     Copyright (C) 2010 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <glib.h>
21
22 #include <cstdlib>
23
24 #include "pbd/epa.h"
25 #include "pbd/strsplit.h"
26
27 #ifdef COMPILER_MSVC
28 #define environ        _environ
29 _CRTIMP extern char ** _environ;
30 #else
31 extern char** environ;
32 #endif
33
34 using namespace PBD;
35 using namespace std;
36
37 EnvironmentalProtectionAgency* EnvironmentalProtectionAgency::_global_epa = 0;
38
39 EnvironmentalProtectionAgency::EnvironmentalProtectionAgency (bool arm, const std::string& envname)
40         : _armed (arm)
41         , _envname (envname)
42 {
43         if (_armed) {
44                 save ();
45         }
46 }
47
48 EnvironmentalProtectionAgency::~EnvironmentalProtectionAgency()
49 {
50         if (_armed) {
51                 restore ();
52         }
53 }
54
55 void
56 EnvironmentalProtectionAgency::arm ()
57 {
58         _armed = true;
59 }
60
61 void
62 EnvironmentalProtectionAgency::save ()
63 {
64         e.clear ();
65
66         if (!_envname.empty()) {
67
68                 /* fetch environment from named environment variable, rather than "environ"
69                  */
70
71                 const char* estr = g_getenv (_envname.c_str());
72
73                 if (!estr) {
74                         return;
75                 }
76
77                 /* parse line by line, and save into "e"
78                  */
79
80                 vector<string> lines;
81                 split (estr, lines, '\n');
82
83                 for (vector<string>::iterator i = lines.begin(); i != lines.end(); ++i) {
84
85                         string estring = *i;
86                         string::size_type equal = estring.find_first_of ('=');
87
88                         if (equal == string::npos) {
89                                 /* say what? an environ value without = ? */
90                                 continue;
91                         }
92
93                         string before = estring.substr (0, equal);
94                         string after = estring.substr (equal+1);
95
96                         e.insert (pair<string,string>(before,after));
97                 }
98
99         } else {
100
101                 /* fetch environment from "environ"
102                  */
103
104                 for (size_t i = 0; environ[i]; ++i) {
105
106                         string estring = environ[i];
107                         string::size_type equal = estring.find_first_of ('=');
108
109                         if (equal == string::npos) {
110                                 /* say what? an environ value without = ? */
111                                 continue;
112                         }
113
114                         string before = estring.substr (0, equal);
115                         string after = estring.substr (equal+1);
116
117                         e.insert (pair<string,string>(before,after));
118                 }
119         }
120 }
121 void
122 EnvironmentalProtectionAgency::restore () const
123 {
124                 clear ();
125
126         for (map<string,string>::const_iterator i = e.begin(); i != e.end(); ++i) {
127                 g_setenv (i->first.c_str(), i->second.c_str(), 1);
128         }
129 }
130
131 void
132 EnvironmentalProtectionAgency::clear () const
133 {
134         /* Copy the environment before using (g_)unsetenv() because on some
135            platforms (maybe all?) this directly modifies the environ array,
136            cause complications for iterating through it.
137         */
138
139         vector<string> ecopy;
140
141         for (size_t i = 0; environ[i]; ++i) {
142                 ecopy.push_back (environ[i]);
143         }
144
145         for (vector<string>::const_iterator e = ecopy.begin(); e != ecopy.end(); ++e) {
146                 string::size_type equal = (*e).find_first_of ('=');
147
148                 if (equal == string::npos) {
149                         /* say what? an environ value without = ? */
150                         continue;
151                 }
152
153                 string var_name = (*e).substr (0, equal);
154                 g_unsetenv(var_name.c_str());
155         }
156 }