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_log
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:108
jack_error
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92