Jack2 1.9.10
|
00001 /* 00002 Copyright (C) 2006-2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as published by 00006 the Free Software Foundation; either version 2.1 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 00018 */ 00019 00020 #include "JackConstants.h" 00021 #include "JackDriverLoader.h" 00022 #include "JackTools.h" 00023 #include "JackError.h" 00024 #include <stdlib.h> 00025 #include <stdio.h> 00026 #include <assert.h> 00027 #include <signal.h> 00028 00029 #ifdef WIN32 00030 #include <process.h> 00031 #endif 00032 00033 00034 using namespace std; 00035 00036 namespace Jack { 00037 00038 void JackTools::KillServer() 00039 { 00040 #ifdef WIN32 00041 raise(SIGINT); 00042 #else 00043 kill(GetPID(), SIGINT); 00044 #endif 00045 } 00046 00047 void JackTools::ThrowJackNetException() 00048 { 00049 throw JackNetException(); 00050 } 00051 00052 int JackTools::MkDir(const char* path) 00053 { 00054 #ifdef WIN32 00055 return CreateDirectory(path, NULL) == 0; 00056 #else 00057 return mkdir(path, 0777) != 0; 00058 #endif 00059 } 00060 00061 #define DEFAULT_TMP_DIR "/tmp" 00062 char* jack_tmpdir = (char*)DEFAULT_TMP_DIR; 00063 00064 int JackTools::GetPID() 00065 { 00066 #ifdef WIN32 00067 return _getpid(); 00068 #else 00069 return getpid(); 00070 #endif 00071 } 00072 00073 int JackTools::GetUID() 00074 { 00075 #ifdef WIN32 00076 return _getpid(); 00077 //#error "No getuid function available" 00078 #else 00079 return getuid(); 00080 #endif 00081 } 00082 00083 const char* JackTools::DefaultServerName() 00084 { 00085 const char* server_name; 00086 if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL) { 00087 server_name = JACK_DEFAULT_SERVER_NAME; 00088 } 00089 return server_name; 00090 } 00091 00092 /* returns the name of the per-user subdirectory of jack_tmpdir */ 00093 #ifdef WIN32 00094 00095 char* JackTools::UserDir() 00096 { 00097 return ""; 00098 } 00099 00100 char* JackTools::ServerDir(const char* server_name, char* server_dir) 00101 { 00102 return ""; 00103 } 00104 00105 void JackTools::CleanupFiles(const char* server_name) {} 00106 00107 int JackTools::GetTmpdir() 00108 { 00109 return 0; 00110 } 00111 00112 #else 00113 char* JackTools::UserDir() 00114 { 00115 static char user_dir[JACK_PATH_MAX + 1] = ""; 00116 00117 /* format the path name on the first call */ 00118 if (user_dir[0] == '\0') { 00119 if (getenv ("JACK_PROMISCUOUS_SERVER")) { 00120 snprintf(user_dir, sizeof(user_dir), "%s/jack", jack_tmpdir); 00121 } else { 00122 snprintf(user_dir, sizeof(user_dir), "%s/jack-%d", jack_tmpdir, GetUID()); 00123 } 00124 } 00125 00126 return user_dir; 00127 } 00128 00129 /* returns the name of the per-server subdirectory of jack_user_dir() */ 00130 char* JackTools::ServerDir(const char* server_name, char* server_dir) 00131 { 00132 /* format the path name into the suppled server_dir char array, 00133 * assuming that server_dir is at least as large as JACK_PATH_MAX + 1 */ 00134 00135 snprintf(server_dir, JACK_PATH_MAX + 1, "%s/%s", UserDir(), server_name); 00136 return server_dir; 00137 } 00138 00139 void JackTools::CleanupFiles(const char* server_name) 00140 { 00141 DIR* dir; 00142 struct dirent *dirent; 00143 char dir_name[JACK_PATH_MAX + 1] = ""; 00144 ServerDir(server_name, dir_name); 00145 00146 /* On termination, we remove all files that jackd creates so 00147 * subsequent attempts to start jackd will not believe that an 00148 * instance is already running. If the server crashes or is 00149 * terminated with SIGKILL, this is not possible. So, cleanup 00150 * is also attempted when jackd starts. 00151 * 00152 * There are several tricky issues. First, the previous JACK 00153 * server may have run for a different user ID, so its files 00154 * may be inaccessible. This is handled by using a separate 00155 * JACK_TMP_DIR subdirectory for each user. Second, there may 00156 * be other servers running with different names. Each gets 00157 * its own subdirectory within the per-user directory. The 00158 * current process has already registered as `server_name', so 00159 * we know there is no other server actively using that name. 00160 */ 00161 00162 /* nothing to do if the server directory does not exist */ 00163 if ((dir = opendir(dir_name)) == NULL) { 00164 return; 00165 } 00166 00167 /* unlink all the files in this directory, they are mine */ 00168 while ((dirent = readdir(dir)) != NULL) { 00169 00170 char fullpath[JACK_PATH_MAX + 1]; 00171 00172 if ((strcmp(dirent->d_name, ".") == 0) || (strcmp (dirent->d_name, "..") == 0)) { 00173 continue; 00174 } 00175 00176 snprintf(fullpath, sizeof(fullpath), "%s/%s", dir_name, dirent->d_name); 00177 00178 if (unlink(fullpath)) { 00179 jack_error("cannot unlink `%s' (%s)", fullpath, strerror(errno)); 00180 } 00181 } 00182 00183 closedir(dir); 00184 00185 /* now, delete the per-server subdirectory, itself */ 00186 if (rmdir(dir_name)) { 00187 jack_error("cannot remove `%s' (%s)", dir_name, strerror(errno)); 00188 } 00189 00190 /* finally, delete the per-user subdirectory, if empty */ 00191 if (rmdir(UserDir())) { 00192 if (errno != ENOTEMPTY) { 00193 jack_error("cannot remove `%s' (%s)", UserDir(), strerror(errno)); 00194 } 00195 } 00196 } 00197 00198 int JackTools::GetTmpdir() 00199 { 00200 FILE* in; 00201 size_t len; 00202 char buf[JACK_PATH_MAX + 2]; /* allow tmpdir to live anywhere, plus newline, plus null */ 00203 00204 if ((in = popen("jackd -l", "r")) == NULL) { 00205 return -1; 00206 } 00207 00208 if (fgets(buf, sizeof(buf), in) == NULL) { 00209 pclose(in); 00210 return -1; 00211 } 00212 00213 len = strlen(buf); 00214 00215 if (buf[len - 1] != '\n') { 00216 /* didn't get a whole line */ 00217 pclose(in); 00218 return -1; 00219 } 00220 00221 jack_tmpdir = (char *)malloc(len); 00222 memcpy(jack_tmpdir, buf, len - 1); 00223 jack_tmpdir[len - 1] = '\0'; 00224 00225 pclose(in); 00226 return 0; 00227 } 00228 #endif 00229 00230 void JackTools::RewriteName(const char* name, char* new_name) 00231 { 00232 size_t i; 00233 for (i = 0; i < strlen(name); i++) { 00234 if ((name[i] == '/') || (name[i] == '\\')) { 00235 new_name[i] = '_'; 00236 } else { 00237 new_name[i] = name[i]; 00238 } 00239 } 00240 new_name[i] = '\0'; 00241 } 00242 00243 #ifdef WIN32 00244 00245 void BuildClientPath(char* path_to_so, int path_len, const char* so_name) 00246 { 00247 snprintf(path_to_so, path_len, ADDON_DIR "/%s.dll", so_name); 00248 } 00249 00250 void PrintLoadError(const char* so_name) 00251 { 00252 // Retrieve the system error message for the last-error code 00253 LPVOID lpMsgBuf; 00254 LPVOID lpDisplayBuf; 00255 DWORD dw = GetLastError(); 00256 00257 FormatMessage( 00258 FORMAT_MESSAGE_ALLOCATE_BUFFER | 00259 FORMAT_MESSAGE_FROM_SYSTEM | 00260 FORMAT_MESSAGE_IGNORE_INSERTS, 00261 NULL, 00262 dw, 00263 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 00264 (LPTSTR) &lpMsgBuf, 00265 0, NULL ); 00266 00267 // Display the error message and exit the process 00268 lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 00269 (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)so_name) + 40) * sizeof(TCHAR)); 00270 _snprintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), 00271 TEXT("error loading %s err = %s"), so_name, lpMsgBuf); 00272 00273 jack_error((LPCTSTR)lpDisplayBuf); 00274 00275 LocalFree(lpMsgBuf); 00276 LocalFree(lpDisplayBuf); 00277 } 00278 00279 #else 00280 00281 void PrintLoadError(const char* so_name) 00282 { 00283 jack_log("error loading %s err = %s", so_name, dlerror()); 00284 } 00285 00286 void BuildClientPath(char* path_to_so, int path_len, const char* so_name) 00287 { 00288 const char* internal_dir; 00289 if ((internal_dir = getenv("JACK_INTERNAL_DIR")) == 0) { 00290 if ((internal_dir = getenv("JACK_DRIVER_DIR")) == 0) { 00291 internal_dir = ADDON_DIR; 00292 } 00293 } 00294 00295 snprintf(path_to_so, path_len, "%s/%s.so", internal_dir, so_name); 00296 } 00297 00298 #endif 00299 00300 00301 } // end of namespace 00302