1 // Copyright (C) 2008-2011 David Sugar, Tycho Softworks.
2 //
3 // This file is part of GNU Bayonne.
4 //
5 // GNU Bayonne is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // GNU Bayonne is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with GNU Bayonne. If not, see <http://www.gnu.org/licenses/>.
17
18 #include <config.h>
19 #include <ucommon/ucommon.h>
20 #include <ucommon/export.h>
22
23 #ifdef HAVE_PWD_H
24 #include <pwd.h>
25 #endif
26
28 using namespace UCOMMON_NAMESPACE;
29
30 shell_t *Env::sys;
31 bool Env::daemon_flag = true;
32 bool Env::tool_flag = false;
33
34 void Env::init(shell_t *args)
35 {
36 sys = args;
37
38 #ifdef _MSWINDOWS_
39 const char *rundir = strdup(str(env("APPDATA")) + "/bayonne");
40 const char *prefix = "C:\\Program Files\\bayonne";
41 const char *plugins = "C:\\Program Files\\bayonne\\plugins";
42
43 set("config", _STR(str(prefix) + "/bayonne.ini"));
44 set("configs", _STR(str(prefix) + "\\config\\"));
45 set("services", _STR(str(prefix) + "/services"));
46 set("controls", rundir);
47 set("control", "\\\\.\\mailslot\\bayonne_ctrl");
48 set("snapshot", _STR(str(rundir) + "/snapshot.log"));
49 set("boards", _STR(str(rundir) + "/boards.log"));
50 set("spans", _STR(str(rundir) + "/spans.log"));
51 set("logfiles", _STR(str(prefix) + "/logs"));
52 set("logfile", _STR(str(prefix) + "/logs/bayonne.log"));
53 set("calls", _STR(str(prefix) + "/logs/bayonne.calls"));
54 set("stats", _STR(str(prefix) + "/logs/bayonne.stats"));
55 set("scripts", _STR(str(prefix) + "/scripts"));
56 set("appaudio", _STR(str(prefix) + "/audio"));
57 set("sounds", _STR(str(prefix) + "/sounds"));
58 set("definitions", _STR(str(prefix) + "/scripts"));
59 set("shell", "cmd.exe");
60 set("voices", _STR(str(prefix) + "\\voices"));
61 set("temp", "C:\\Program Files\\bayonne\\temp");
62
63 prefix = "C:\\Program Files\\bayonne\\datafiles";
64
65 #else
66 const char *prefix = DEFAULT_VARPATH "/lib/bayonne";
67 const char *rundir = DEFAULT_VARPATH "/run/bayonne";
68 const char *plugins = DEFAULT_LIBPATH "/bayonne";
69
70 set("reply", "/tmp/.bayonne.");
71 set("config", DEFAULT_CFGPATH "/bayonne.conf");
72 set("configs", DEFAULT_CFGPATH "/bayonne/");
73 set("services", DEFAULT_SCRPATH);
74 set("controls", DEFAULT_VARPATH "/run/bayonne");
75 set("control", DEFAULT_VARPATH "/run/bayonne/control");
76 set("snapshot", DEFAULT_VARPATH "/run/bayonne/snapshot");
77 set("boards", DEFAULT_VARPATH "/run/bayonne/boards");
78 set("spans", DEFAULT_VARPATH "/run/bayonne/spans");
79 set("logfiles", DEFAULT_VARPATH "/log");
80 set("logfile", DEFAULT_VARPATH "/log/bayonne.log");
81 set("calls", DEFAULT_VARPATH "/log/bayonne.calls");
82 set("stats", DEFAULT_VARPATH "/log/bayonne.stats");
83 set("scripts", DEFAULT_VARPATH "/lib/bayonne/scripts");
84 set("audio", DEFAULT_DATADIR "/bayonne");
85 set("sounds", DEFAULT_DATADIR "/sounds");
86 set("applications", DEFAULT_DATADIR "/bayonne");
87 set("definitions", DEFAULT_DATADIR "/bayonne");
88 set("shell", "/bin/sh");
89 set("voices", DEFAULT_DATADIR "/phrasebook");
90 set("temp", DEFAULT_VARPATH "/tmp/bayonne");
91 #endif
92
93 #ifdef HAVE_PWD_H
94 const char *home_prefix = NULL;
95 struct passwd *pwd = getpwuid(getuid());
96 umask(007);
97
98 if(getuid() && pwd && pwd->pw_dir && *pwd->pw_dir == '/') {
99 if(!eq(pwd->pw_shell, "/bin/false") && !eq(pwd->pw_dir, "/var/", 5) && !eq(pwd->pw_dir, "/srv/", 5)) {
100 umask(077);
101 daemon_flag = false;
102 }
103 else // alternate media prefix possible if not root startup...
104 prefix = strdup(pwd->pw_dir);
105 }
106
107 // if user mode (testing)...
108 if(!daemon_flag && pwd)
109 home_prefix = strdup(str(pwd->pw_dir) + "/.bayonne");
110
111 // tool mode only uses ~/.bayonne if also actually exists...
112 if(home_prefix && tool_flag && !fsys::isdir(home_prefix))
113 home_prefix = NULL;
114
115 if(home_prefix) {
116 rundir = strdup(str("/tmp/bayonne-") + str(pwd->pw_name));
117 prefix = home_prefix;
118
119 set("config", _STR(str(pwd->pw_dir) + "/.bayonnerc"));
120 set("configs", home_prefix);
121 set("scripts", home_prefix);
122 set("sysconfigs", _STR(str(DEFAULT_CFGPATH) + "/bayonne"));
123 set("services", prefix);
124 set("controls", rundir);
125 set("control", _STR(str(rundir) + "/control"));
126 set("snapshot", _STR(str(rundir) + "/snapshot"));
127 set("boards", _STR(str(rundir) + "/boards"));
128 set("spans", _STR(str(rundir) + "/spans"));
129 set("logfiles", rundir);
130 set("logfile", _STR(str(rundir) + "/logfile"));
131 set("calls", _STR(str(rundir) + "/calls"));
132 set("stats", _STR(str(rundir) + "/stats"));
133 set("prefix", prefix);
134 set("shell", pwd->pw_shell);
135 }
136 #endif
137
138 set("voice", "default");
139 set("extension", ".au");
140 set("prefix", prefix);
141 set("rundir", rundir);
142 set("plugins", plugins);
143 }
144
145 void Env::tool(shell_t *args)
146 {
147 tool_flag = true;
148 init(args);
149 }
150
151 const char *Env::config(const char *name)
152 {
153 // if we have cached copy of config path, use it...
154 const char *result = env(name);
155 if(result)
156 return result;
157
158 const char *sysconfig = env("sysconfig");
159
160 string_t filename = str(env("configs")) + str(name);
161
162 if(sysconfig && !fsys::isfile(*filename))
163 filename = str(sysconfig) + str(name);
164
165 // cache and use requested config path...
166 set(name, *filename);
167 return env(name);
168 }
169
170 const char *Env::path(pathinfo_t& pi, const char *path, char *buffer, size_t size, bool writeflag)
171 {
172 const char *ext = strrchr(path, '/');
173
174 // file: and tool: can be used anywhere, but for toolmode only...
175 if(case_eq(path, "file:", 5) || case_eq(path, "tool:")) {
176 if(!tool_flag)
177 return NULL;
178
179 String::set(buffer, size, path + 5);
180 return buffer;
181 }
182
183 // out: can be used to override for writing absolute path in tool mode...
184 if(case_eq(path, "out:", 4)) {
185 if(!tool_flag || !writeflag)
186 return NULL;
187
188 String::set(buffer, size, path + 4);
189 return buffer;
190 }
191
192 // writeflag used to restrict what bayonne can modify. We disable this
193 // for various bayonne tools.
194 if(tool_flag)
195 writeflag = false;
196
197 // all other xxx: paths cannot include subdirectories...
198 if(ext && strchr(path + 2, ':'))
199 return NULL;
200
201 // xxx.ext is a local file, not phrase library, in tool mode...
202 if(!ext && strchr(path, '.') && tool_flag && !strchr(path + 2, ':'))
203 ext = path;
204
205 if(ext) {
206 ext = strchr(ext, '.');
207 if(ext)
208 ext = "";
209 else
210 ext = env("extension");
211
212 if(*path != '/' && tool_flag)
213 snprintf(buffer, size, "%s/%s%s",
214 env("prefix"), path, ext);
215 else
216 snprintf(buffer, size, "%s%s", path, ext);
217
218 return buffer;
219 }
220
221 const char *voice = pi.voices;
222 if(!voice)
223 voice = env("voice");
224
225 ext = strchr(path, '.');
226
227 if(ext)
228 ext = "";
229 else
230 ext = env("extension");
231
232 // tmp: to access bayonne temporary files...
233 if(case_eq(path, "tmp:", 4) || case_eq(path, "temp:", 5)) {
234 snprintf(buffer, size, "%s/%s%s",
235 env("temp"), strchr(path, ':') + 1, ext);
236 return buffer;
237 }
238
239 // we cannot write to system sounds directory...
240 if(case_eq(path, "sound:", 6) || case_eq(path, "sounds:", 7)) {
241 if(writeflag)
242 return NULL;
243
244 snprintf(buffer, size, "%s/%s%s",
245 env("sounds"), strchr(path, ':') + 1, ext);
246 }
247
248
249 // lib: optional way to always specify use library
250 else if(case_eq(path, "lib:", 4))
251 path += 4;
252 else if(strchr(path, ':'))
253 return NULL;
254
255 // normally cannot write to phrasebook library unless toolmode
256 if(writeflag)
257 return NULL;
258
259 // can optionally force path through voice library setting
260 if(strchr(voice, '/')) {
261 snprintf(buffer, size, "%s/%s%s", voice, path, ext);
262 return buffer;
263 }
264
265 if(pi.book) {
266 snprintf(buffer, size, "%s%s%s/%s%s",
267 env("voices"), pi->path(), voice, path, ext);
268
269 return buffer;
270 }
271 return NULL;
272 }
273
274
#define BAYONNE_NAMESPACE
GNU Bayonne library namespace.