Jack2: JackTools.cpp Source File

Jack2 1.9.12

JackTools.cpp
1 /*
2 Copyright (C) 2006-2008 Grame
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 */
19
20 #include "JackConstants.h"
21 #include "JackDriverLoader.h"
22 #include "JackTools.h"
23 #include "JackError.h"
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <assert.h>
27 #include <signal.h>
28
29 #ifdef WIN32
30 #include <process.h>
31 #endif
32
33
34 using namespace std;
35
36 namespace Jack {
37
38 void JackTools::KillServer()
39 {
40 #ifdef WIN32
41 raise(SIGINT);
42 #else
43 kill(GetPID(), SIGINT);
44 #endif
45 }
46
47 void JackTools::ThrowJackNetException()
48 {
49 throw JackNetException();
50 }
51
52 int JackTools::MkDir(const char* path)
53 {
54 #ifdef WIN32
55 return CreateDirectory(path, NULL) == 0;
56 #else
57 return mkdir(path, 0777) != 0;
58 #endif
59 }
60
61 #define DEFAULT_TMP_DIR "/tmp"
62 char* jack_tmpdir = (char*)DEFAULT_TMP_DIR;
63
64 int JackTools::GetPID()
65 {
66 #ifdef WIN32
67 return _getpid();
68 #else
69 return getpid();
70 #endif
71 }
72
73 int JackTools::GetUID()
74 {
75 #ifdef WIN32
76 return _getpid();
77 //#error "No getuid function available"
78 #else
79 return getuid();
80 #endif
81 }
82
83 const char* JackTools::DefaultServerName()
84 {
85 const char* server_name;
86 if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL) {
87 server_name = JACK_DEFAULT_SERVER_NAME;
88 }
89 return server_name;
90 }
91
92 /* returns the name of the per-user subdirectory of jack_tmpdir */
93 #ifdef WIN32
94
95 char* JackTools::UserDir()
96 {
97 return "";
98 }
99
100 char* JackTools::ServerDir(const char* server_name, char* server_dir)
101 {
102 return "";
103 }
104
105 void JackTools::CleanupFiles(const char* server_name) {}
106
107 int JackTools::GetTmpdir()
108 {
109 return 0;
110 }
111
112 #else
113 char* JackTools::UserDir()
114 {
115 static char user_dir[JACK_PATH_MAX + 1] = "";
116
117 /* format the path name on the first call */
118 if (user_dir[0] == '\0') {
119 if (getenv ("JACK_PROMISCUOUS_SERVER")) {
120 snprintf(user_dir, sizeof(user_dir), "%s/jack", jack_tmpdir);
121 } else {
122 snprintf(user_dir, sizeof(user_dir), "%s/jack-%d", jack_tmpdir, GetUID());
123 }
124 }
125
126 return user_dir;
127 }
128
129 /* returns the name of the per-server subdirectory of jack_user_dir() */
130 char* JackTools::ServerDir(const char* server_name, char* server_dir)
131 {
132 /* format the path name into the suppled server_dir char array,
133 * assuming that server_dir is at least as large as JACK_PATH_MAX + 1 */
134
135 snprintf(server_dir, JACK_PATH_MAX + 1, "%s/%s", UserDir(), server_name);
136 return server_dir;
137 }
138
139 void JackTools::CleanupFiles(const char* server_name)
140 {
141 DIR* dir;
142 struct dirent *dirent;
143 char dir_name[JACK_PATH_MAX + 1] = "";
144 ServerDir(server_name, dir_name);
145
146 /* On termination, we remove all files that jackd creates so
147 * subsequent attempts to start jackd will not believe that an
148 * instance is already running. If the server crashes or is
149 * terminated with SIGKILL, this is not possible. So, cleanup
150 * is also attempted when jackd starts.
151 *
152 * There are several tricky issues. First, the previous JACK
153 * server may have run for a different user ID, so its files
154 * may be inaccessible. This is handled by using a separate
155 * JACK_TMP_DIR subdirectory for each user. Second, there may
156 * be other servers running with different names. Each gets
157 * its own subdirectory within the per-user directory. The
158 * current process has already registered as `server_name', so
159 * we know there is no other server actively using that name.
160 */
161
162 /* nothing to do if the server directory does not exist */
163 if ((dir = opendir(dir_name)) == NULL) {
164 return;
165 }
166
167 /* unlink all the files in this directory, they are mine */
168 while ((dirent = readdir(dir)) != NULL) {
169
170 char fullpath[JACK_PATH_MAX + 1];
171
172 if ((strcmp(dirent->d_name, ".") == 0) || (strcmp (dirent->d_name, "..") == 0)) {
173 continue;
174 }
175
176 snprintf(fullpath, sizeof(fullpath), "%s/%s", dir_name, dirent->d_name);
177
178 if (unlink(fullpath)) {
179 jack_error("cannot unlink `%s' (%s)", fullpath, strerror(errno));
180 }
181 }
182
183 closedir(dir);
184
185 /* now, delete the per-server subdirectory, itself */
186 if (rmdir(dir_name)) {
187 jack_error("cannot remove `%s' (%s)", dir_name, strerror(errno));
188 }
189
190 /* finally, delete the per-user subdirectory, if empty */
191 if (rmdir(UserDir())) {
192 if (errno != ENOTEMPTY) {
193 jack_error("cannot remove `%s' (%s)", UserDir(), strerror(errno));
194 }
195 }
196 }
197
198 int JackTools::GetTmpdir()
199 {
200 FILE* in;
201 size_t len;
202 char buf[JACK_PATH_MAX + 2]; /* allow tmpdir to live anywhere, plus newline, plus null */
203
204 if ((in = popen("jackd -l", "r")) == NULL) {
205 return -1;
206 }
207
208 if (fgets(buf, sizeof(buf), in) == NULL) {
209 pclose(in);
210 return -1;
211 }
212
213 len = strlen(buf);
214
215 if (buf[len - 1] != '\n') {
216 /* didn't get a whole line */
217 pclose(in);
218 return -1;
219 }
220
221 jack_tmpdir = (char *)malloc(len);
222 memcpy(jack_tmpdir, buf, len - 1);
223 jack_tmpdir[len - 1] = '\0';
224
225 pclose(in);
226 return 0;
227 }
228 #endif
229
230 void JackTools::RewriteName(const char* name, char* new_name)
231 {
232 size_t i;
233 for (i = 0; i < strlen(name); i++) {
234 if ((name[i] == '/') || (name[i] == '\\')) {
235 new_name[i] = '_';
236 } else {
237 new_name[i] = name[i];
238 }
239 }
240 new_name[i] = '\0';
241 }
242
243 #ifdef WIN32
244
245 void BuildClientPath(char* path_to_so, int path_len, const char* so_name)
246 {
247 snprintf(path_to_so, path_len, ADDON_DIR "/%s.dll", so_name);
248 }
249
250 void PrintLoadError(const char* so_name)
251 {
252 // Retrieve the system error message for the last-error code
253 LPVOID lpMsgBuf;
254 LPVOID lpDisplayBuf;
255 DWORD dw = GetLastError();
256
257 FormatMessage(
258 FORMAT_MESSAGE_ALLOCATE_BUFFER |
259 FORMAT_MESSAGE_FROM_SYSTEM |
260 FORMAT_MESSAGE_IGNORE_INSERTS,
261 NULL,
262 dw,
263 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
264 (LPTSTR) &lpMsgBuf,
265 0, NULL );
266
267 // Display the error message and exit the process
268 lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
269 (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)so_name) + 40) * sizeof(TCHAR));
270 _snprintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR),
271 TEXT("error loading %s err = %s"), so_name, lpMsgBuf);
272
273 jack_error((LPCTSTR)lpDisplayBuf);
274
275 LocalFree(lpMsgBuf);
276 LocalFree(lpDisplayBuf);
277 }
278
279 #else
280
281 void PrintLoadError(const char* so_name)
282 {
283 jack_log("error loading %s err = %s", so_name, dlerror());
284 }
285
286 void BuildClientPath(char* path_to_so, int path_len, const char* so_name)
287 {
288 const char* internal_dir;
289 if ((internal_dir = getenv("JACK_INTERNAL_DIR")) == 0) {
290 if ((internal_dir = getenv("JACK_DRIVER_DIR")) == 0) {
291 internal_dir = ADDON_DIR;
292 }
293 }
294
295 snprintf(path_to_so, path_len, "%s/%s.so", internal_dir, so_name);
296 }
297
298 #endif
299
300
301 } // end of namespace
302
jack_error
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
jack_log
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:108