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