Jack2 1.9.6

JackTools.cpp

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