Jack2 1.9.10

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 "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