Merge branch 'master' into develop
[jack2.git] / common / JackTools.cpp
blob94e7034d1ae22d9e4dc1c7881cf6c8ffe9b18ff9
1 /*
2 Copyright (C) 2006-2008 Grame
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.
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.
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.
20 #include "JackConstants.h"
21 #include "driver_interface.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>
29 #ifdef WIN32
30 #include <process.h>
31 #include "JackPlatformPlug_os.h"
32 #endif
35 using namespace std;
37 namespace Jack {
39 void JackTools::KillServer()
41 #ifdef WIN32
42 raise(SIGINT);
43 #else
44 kill(GetPID(), SIGINT);
45 #endif
48 int JackTools::MkDir(const char* path)
50 #ifdef WIN32
51 return CreateDirectory(path, NULL) == 0;
52 #else
53 return mkdir(path, 0777) != 0;
54 #endif
57 #define DEFAULT_TMP_DIR "/tmp"
58 char* jack_tmpdir = (char*)DEFAULT_TMP_DIR;
60 int JackTools::GetPID()
62 #ifdef WIN32
63 return _getpid();
64 #else
65 return getpid();
66 #endif
69 int JackTools::GetUID()
71 #ifdef WIN32
72 return _getpid();
73 //#error "No getuid function available"
74 #else
75 return geteuid();
76 #endif
79 const char* JackTools::DefaultServerName()
81 const char* server_name;
82 if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL) {
83 server_name = JACK_DEFAULT_SERVER_NAME;
85 return server_name;
88 /* returns the name of the per-user subdirectory of jack_tmpdir */
89 #ifdef WIN32
91 const char* JackTools::UserDir()
93 return "";
96 const char* JackTools::ServerDir(const char* server_name, char* server_dir)
98 return "";
101 void JackTools::CleanupFiles(const char* server_name) {}
103 int JackTools::GetTmpdir()
105 return 0;
108 #else
109 const char* JackTools::UserDir()
111 static char user_dir[JACK_PATH_MAX + 1] = "";
113 /* format the path name on the first call */
114 if (user_dir[0] == '\0') {
115 if (getenv ("JACK_PROMISCUOUS_SERVER")) {
116 snprintf(user_dir, sizeof(user_dir), "%s/jack", jack_tmpdir);
117 } else {
118 snprintf(user_dir, sizeof(user_dir), "%s/jack-%d", jack_tmpdir, GetUID());
122 return user_dir;
125 /* returns the name of the per-server subdirectory of jack_user_dir() */
126 const char* JackTools::ServerDir(const char* server_name, char* server_dir)
128 /* format the path name into the suppled server_dir char array,
129 * assuming that server_dir is at least as large as JACK_PATH_MAX + 1 */
131 snprintf(server_dir, JACK_PATH_MAX + 1, "%s/%s", UserDir(), server_name);
132 return server_dir;
135 void JackTools::CleanupFiles(const char* server_name)
137 DIR* dir;
138 struct dirent *dirent;
139 char dir_name[JACK_PATH_MAX + 1] = "";
140 ServerDir(server_name, dir_name);
142 /* On termination, we remove all files that jackd creates so
143 * subsequent attempts to start jackd will not believe that an
144 * instance is already running. If the server crashes or is
145 * terminated with SIGKILL, this is not possible. So, cleanup
146 * is also attempted when jackd starts.
148 * There are several tricky issues. First, the previous JACK
149 * server may have run for a different user ID, so its files
150 * may be inaccessible. This is handled by using a separate
151 * JACK_TMP_DIR subdirectory for each user. Second, there may
152 * be other servers running with different names. Each gets
153 * its own subdirectory within the per-user directory. The
154 * current process has already registered as `server_name', so
155 * we know there is no other server actively using that name.
158 /* nothing to do if the server directory does not exist */
159 if ((dir = opendir(dir_name)) == NULL) {
160 return;
163 /* unlink all the files in this directory, they are mine */
164 while ((dirent = readdir(dir)) != NULL) {
166 char fullpath[JACK_PATH_MAX + 1];
168 if ((strcmp(dirent->d_name, ".") == 0) || (strcmp (dirent->d_name, "..") == 0)) {
169 continue;
172 snprintf(fullpath, sizeof(fullpath), "%s/%s", dir_name, dirent->d_name);
174 if (unlink(fullpath)) {
175 jack_error("cannot unlink `%s' (%s)", fullpath, strerror(errno));
179 closedir(dir);
181 /* now, delete the per-server subdirectory, itself */
182 if (rmdir(dir_name)) {
183 jack_error("cannot remove `%s' (%s)", dir_name, strerror(errno));
186 /* finally, delete the per-user subdirectory, if empty */
187 if (rmdir(UserDir())) {
188 if (errno != ENOTEMPTY) {
189 jack_error("cannot remove `%s' (%s)", UserDir(), strerror(errno));
194 int JackTools::GetTmpdir()
196 FILE* in;
197 size_t len;
198 char buf[JACK_PATH_MAX + 2]; /* allow tmpdir to live anywhere, plus newline, plus null */
200 if ((in = popen("jackd -l", "r")) == NULL) {
201 return -1;
204 if (fgets(buf, sizeof(buf), in) == NULL) {
205 pclose(in);
206 return -1;
209 len = strlen(buf);
211 if (buf[len - 1] != '\n') {
212 /* didn't get a whole line */
213 pclose(in);
214 return -1;
217 jack_tmpdir = (char *)malloc(len);
218 memcpy(jack_tmpdir, buf, len - 1);
219 jack_tmpdir[len - 1] = '\0';
221 pclose(in);
222 return 0;
224 #endif
226 void JackTools::RewriteName(const char* name, char* new_name)
228 size_t i;
229 for (i = 0; i < strlen(name); i++) {
230 if ((name[i] == '/') || (name[i] == '\\')) {
231 new_name[i] = '_';
232 } else {
233 new_name[i] = name[i];
236 new_name[i] = '\0';
239 #ifdef WIN32
241 void BuildClientPath(char* path_to_so, int path_len, const char* so_name)
243 snprintf(path_to_so, path_len, ADDON_DIR "/%s.dll", so_name);
246 void PrintLoadError(const char* so_name)
248 // Retrieve the system error message for the last-error code
249 LPVOID lpMsgBuf;
250 LPVOID lpDisplayBuf;
251 DWORD dw = GetLastError();
253 FormatMessage(
254 FORMAT_MESSAGE_ALLOCATE_BUFFER |
255 FORMAT_MESSAGE_FROM_SYSTEM |
256 FORMAT_MESSAGE_IGNORE_INSERTS,
257 NULL,
259 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
260 (LPTSTR) &lpMsgBuf,
261 0, NULL );
263 // Display the error message and exit the process
264 lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
265 (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)so_name) + 40) * sizeof(TCHAR));
266 _snprintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR),
267 TEXT("error loading %s err = %s"), so_name, (LPCTSTR)lpMsgBuf);
269 jack_error((LPCTSTR)lpDisplayBuf);
271 LocalFree(lpMsgBuf);
272 LocalFree(lpDisplayBuf);
275 #else
277 void PrintLoadError(const char* so_name)
279 jack_log("error loading %s err = %s", so_name, dlerror());
282 void BuildClientPath(char* path_to_so, int path_len, const char* so_name)
284 const char* internal_dir;
285 if ((internal_dir = getenv("JACK_INTERNAL_DIR")) == 0) {
286 if ((internal_dir = getenv("JACK_DRIVER_DIR")) == 0) {
287 internal_dir = ADDON_DIR;
291 snprintf(path_to_so, path_len, "%s/%s.so", internal_dir, so_name);
294 #endif
297 } // end of namespace