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