|
|
|
@@ -31,188 +31,258 @@ |
|
|
|
#include <process.h> |
|
|
|
#endif |
|
|
|
|
|
|
|
namespace Jack |
|
|
|
{ |
|
|
|
using namespace std; |
|
|
|
|
|
|
|
namespace Jack { |
|
|
|
|
|
|
|
#define DEFAULT_TMP_DIR "/tmp" |
|
|
|
char* jack_tmpdir = (char*)DEFAULT_TMP_DIR; |
|
|
|
char* jack_tmpdir = (char*)DEFAULT_TMP_DIR; |
|
|
|
|
|
|
|
int JackTools::GetPID() |
|
|
|
{ |
|
|
|
int JackTools::GetPID() { |
|
|
|
#ifdef WIN32 |
|
|
|
return _getpid(); |
|
|
|
return _getpid(); |
|
|
|
#else |
|
|
|
return getpid(); |
|
|
|
return getpid(); |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int JackTools::GetUID() |
|
|
|
{ |
|
|
|
int JackTools::GetUID() { |
|
|
|
#ifdef WIN32 |
|
|
|
return _getpid(); |
|
|
|
//#error "No getuid function available" |
|
|
|
return _getpid(); |
|
|
|
//#error "No getuid function available" |
|
|
|
#else |
|
|
|
return getuid(); |
|
|
|
return getuid(); |
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const char* JackTools::DefaultServerName() |
|
|
|
{ |
|
|
|
const char* server_name; |
|
|
|
if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL) |
|
|
|
server_name = JACK_DEFAULT_SERVER_NAME; |
|
|
|
return server_name; |
|
|
|
} |
|
|
|
const char* JackTools::DefaultServerName() { |
|
|
|
const char* server_name; |
|
|
|
if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL) |
|
|
|
server_name = JACK_DEFAULT_SERVER_NAME; |
|
|
|
return server_name; |
|
|
|
} |
|
|
|
|
|
|
|
/* returns the name of the per-user subdirectory of jack_tmpdir */ |
|
|
|
/* returns the name of the per-user subdirectory of jack_tmpdir */ |
|
|
|
#ifdef WIN32 |
|
|
|
|
|
|
|
char* JackTools::UserDir() |
|
|
|
{ |
|
|
|
return ""; |
|
|
|
} |
|
|
|
char* JackTools::UserDir() { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
|
|
|
|
char* JackTools::ServerDir(const char* server_name, char* server_dir) |
|
|
|
{ |
|
|
|
return ""; |
|
|
|
} |
|
|
|
char* JackTools::ServerDir(const char* server_name, char* server_dir) { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
|
|
|
|
void JackTools::CleanupFiles(const char* server_name) |
|
|
|
{} |
|
|
|
void JackTools::CleanupFiles(const char* server_name) {} |
|
|
|
|
|
|
|
int JackTools::GetTmpdir() |
|
|
|
{ |
|
|
|
return 0; |
|
|
|
} |
|
|
|
int JackTools::GetTmpdir() { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
#else |
|
|
|
char* JackTools::UserDir() |
|
|
|
{ |
|
|
|
static char user_dir[PATH_MAX + 1] = ""; |
|
|
|
|
|
|
|
/* format the path name on the first call */ |
|
|
|
if (user_dir[0] == '\0') { |
|
|
|
if (getenv ("JACK_PROMISCUOUS_SERVER")) { |
|
|
|
snprintf(user_dir, sizeof(user_dir), "%s/jack", jack_tmpdir); |
|
|
|
} else { |
|
|
|
snprintf(user_dir, sizeof(user_dir), "%s/jack-%d", jack_tmpdir, GetUID()); |
|
|
|
char* JackTools::UserDir() { |
|
|
|
static char user_dir[PATH_MAX + 1] = ""; |
|
|
|
|
|
|
|
/* format the path name on the first call */ |
|
|
|
if (user_dir[0] == '\0') { |
|
|
|
if (getenv ("JACK_PROMISCUOUS_SERVER")) { |
|
|
|
snprintf(user_dir, sizeof(user_dir), "%s/jack", jack_tmpdir); |
|
|
|
} else { |
|
|
|
snprintf(user_dir, sizeof(user_dir), "%s/jack-%d", jack_tmpdir, GetUID()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return user_dir; |
|
|
|
} |
|
|
|
|
|
|
|
return user_dir; |
|
|
|
} |
|
|
|
/* returns the name of the per-server subdirectory of jack_user_dir() */ |
|
|
|
char* JackTools::ServerDir(const char* server_name, char* server_dir) { |
|
|
|
/* format the path name into the suppled server_dir char array, |
|
|
|
* assuming that server_dir is at least as large as PATH_MAX+1 */ |
|
|
|
|
|
|
|
/* returns the name of the per-server subdirectory of jack_user_dir() */ |
|
|
|
char* JackTools::ServerDir(const char* server_name, char* server_dir) |
|
|
|
{ |
|
|
|
/* format the path name into the suppled server_dir char array, |
|
|
|
* assuming that server_dir is at least as large as PATH_MAX+1 */ |
|
|
|
snprintf(server_dir, PATH_MAX + 1, "%s/%s", UserDir(), server_name); |
|
|
|
return server_dir; |
|
|
|
} |
|
|
|
|
|
|
|
snprintf(server_dir, PATH_MAX + 1, "%s/%s", UserDir(), server_name); |
|
|
|
return server_dir; |
|
|
|
} |
|
|
|
void JackTools::CleanupFiles(const char* server_name) { |
|
|
|
DIR* dir; |
|
|
|
struct dirent *dirent; |
|
|
|
char dir_name[PATH_MAX + 1] = ""; |
|
|
|
ServerDir(server_name, dir_name); |
|
|
|
|
|
|
|
/* On termination, we remove all files that jackd creates so |
|
|
|
* subsequent attempts to start jackd will not believe that an |
|
|
|
* instance is already running. If the server crashes or is |
|
|
|
* terminated with SIGKILL, this is not possible. So, cleanup |
|
|
|
* is also attempted when jackd starts. |
|
|
|
* |
|
|
|
* There are several tricky issues. First, the previous JACK |
|
|
|
* server may have run for a different user ID, so its files |
|
|
|
* may be inaccessible. This is handled by using a separate |
|
|
|
* JACK_TMP_DIR subdirectory for each user. Second, there may |
|
|
|
* be other servers running with different names. Each gets |
|
|
|
* its own subdirectory within the per-user directory. The |
|
|
|
* current process has already registered as `server_name', so |
|
|
|
* we know there is no other server actively using that name. |
|
|
|
*/ |
|
|
|
|
|
|
|
/* nothing to do if the server directory does not exist */ |
|
|
|
if ((dir = opendir(dir_name)) == NULL) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
void JackTools::CleanupFiles(const char* server_name) |
|
|
|
{ |
|
|
|
DIR* dir; |
|
|
|
struct dirent *dirent; |
|
|
|
char dir_name[PATH_MAX + 1] = ""; |
|
|
|
ServerDir(server_name, dir_name); |
|
|
|
|
|
|
|
/* On termination, we remove all files that jackd creates so |
|
|
|
* subsequent attempts to start jackd will not believe that an |
|
|
|
* instance is already running. If the server crashes or is |
|
|
|
* terminated with SIGKILL, this is not possible. So, cleanup |
|
|
|
* is also attempted when jackd starts. |
|
|
|
* |
|
|
|
* There are several tricky issues. First, the previous JACK |
|
|
|
* server may have run for a different user ID, so its files |
|
|
|
* may be inaccessible. This is handled by using a separate |
|
|
|
* JACK_TMP_DIR subdirectory for each user. Second, there may |
|
|
|
* be other servers running with different names. Each gets |
|
|
|
* its own subdirectory within the per-user directory. The |
|
|
|
* current process has already registered as `server_name', so |
|
|
|
* we know there is no other server actively using that name. |
|
|
|
*/ |
|
|
|
|
|
|
|
/* nothing to do if the server directory does not exist */ |
|
|
|
if ((dir = opendir(dir_name)) == NULL) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* unlink all the files in this directory, they are mine */ |
|
|
|
while ((dirent = readdir(dir)) != NULL) { |
|
|
|
|
|
|
|
char fullpath[PATH_MAX + 1]; |
|
|
|
|
|
|
|
if ((strcmp(dirent->d_name, ".") == 0) || (strcmp (dirent->d_name, "..") == 0)) { |
|
|
|
continue; |
|
|
|
/* unlink all the files in this directory, they are mine */ |
|
|
|
while ((dirent = readdir(dir)) != NULL) { |
|
|
|
|
|
|
|
char fullpath[PATH_MAX + 1]; |
|
|
|
|
|
|
|
if ((strcmp(dirent->d_name, ".") == 0) || (strcmp (dirent->d_name, "..") == 0)) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
snprintf(fullpath, sizeof(fullpath), "%s/%s", dir_name, dirent->d_name); |
|
|
|
|
|
|
|
if (unlink(fullpath)) { |
|
|
|
jack_error("cannot unlink `%s' (%s)", fullpath, strerror(errno)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
snprintf(fullpath, sizeof(fullpath), "%s/%s", dir_name, dirent->d_name); |
|
|
|
closedir(dir); |
|
|
|
|
|
|
|
if (unlink(fullpath)) { |
|
|
|
jack_error("cannot unlink `%s' (%s)", fullpath, strerror(errno)); |
|
|
|
/* now, delete the per-server subdirectory, itself */ |
|
|
|
if (rmdir(dir_name)) { |
|
|
|
jack_error("cannot remove `%s' (%s)", dir_name, strerror(errno)); |
|
|
|
} |
|
|
|
|
|
|
|
/* finally, delete the per-user subdirectory, if empty */ |
|
|
|
if (rmdir(UserDir())) { |
|
|
|
if (errno != ENOTEMPTY) { |
|
|
|
jack_error("cannot remove `%s' (%s)", UserDir(), strerror(errno)); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
closedir(dir); |
|
|
|
int JackTools::GetTmpdir() { |
|
|
|
FILE* in; |
|
|
|
size_t len; |
|
|
|
char buf[PATH_MAX + 2]; /* allow tmpdir to live anywhere, plus newline, plus null */ |
|
|
|
|
|
|
|
/* now, delete the per-server subdirectory, itself */ |
|
|
|
if (rmdir(dir_name)) { |
|
|
|
jack_error("cannot remove `%s' (%s)", dir_name, strerror(errno)); |
|
|
|
} |
|
|
|
if ((in = popen("jackd -l", "r")) == NULL) { |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
/* finally, delete the per-user subdirectory, if empty */ |
|
|
|
if (rmdir(UserDir())) { |
|
|
|
if (errno != ENOTEMPTY) { |
|
|
|
jack_error("cannot remove `%s' (%s)", UserDir(), strerror(errno)); |
|
|
|
if (fgets(buf, sizeof(buf), in) == NULL) { |
|
|
|
fclose(in); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int JackTools::GetTmpdir() |
|
|
|
{ |
|
|
|
FILE* in; |
|
|
|
size_t len; |
|
|
|
char buf[PATH_MAX + 2]; /* allow tmpdir to live anywhere, plus newline, plus null */ |
|
|
|
len = strlen(buf); |
|
|
|
|
|
|
|
if ((in = popen("jackd -l", "r")) == NULL) { |
|
|
|
return -1; |
|
|
|
} |
|
|
|
if (buf[len - 1] != '\n') { |
|
|
|
/* didn't get a whole line */ |
|
|
|
fclose(in); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
jack_tmpdir = (char *)malloc(len); |
|
|
|
memcpy(jack_tmpdir, buf, len - 1); |
|
|
|
jack_tmpdir[len - 1] = '\0'; |
|
|
|
|
|
|
|
if (fgets(buf, sizeof(buf), in) == NULL) { |
|
|
|
fclose(in); |
|
|
|
return -1; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
void JackTools::RewriteName(const char* name, char* new_name) { |
|
|
|
size_t i; |
|
|
|
for (i = 0; i < strlen(name); i++) { |
|
|
|
if ((name[i] == '/') || (name[i] == '\\')) |
|
|
|
new_name[i] = '_'; |
|
|
|
else |
|
|
|
new_name[i] = name[i]; |
|
|
|
} |
|
|
|
new_name[i] = '\0'; |
|
|
|
} |
|
|
|
|
|
|
|
len = strlen(buf); |
|
|
|
JackArgParser::JackArgParser(const char* arg) { |
|
|
|
fArgc=0; |
|
|
|
fNumArgv=0; |
|
|
|
fArgString=string(arg); |
|
|
|
fArgString+=" "; |
|
|
|
const size_t arg_len=fArgString.length(); |
|
|
|
int i=0; |
|
|
|
size_t pos=0; |
|
|
|
size_t start=0; |
|
|
|
size_t copy_start=0; |
|
|
|
size_t copy_length=0; |
|
|
|
vector<string> args; |
|
|
|
|
|
|
|
//first fill a vector with args |
|
|
|
do { |
|
|
|
//find the first non-space character from the actual position |
|
|
|
start=fArgString.find_first_not_of(' ',start); |
|
|
|
//get the next quote or space position |
|
|
|
pos=fArgString.find_first_of(" \"",start); |
|
|
|
//no more quotes or spaces, consider the end of the string |
|
|
|
if (pos==string::npos) |
|
|
|
pos=arg_len; |
|
|
|
//if it's a double quote |
|
|
|
if (fArgString.at(pos)=='\"') { |
|
|
|
//first character : copy the substring |
|
|
|
if (pos==start) { |
|
|
|
copy_start=start+1; |
|
|
|
pos=fArgString.find('\"',++pos); |
|
|
|
copy_length=pos-copy_start; |
|
|
|
start=pos+1; |
|
|
|
} |
|
|
|
//else there is someting before the quote, first copy that |
|
|
|
else { |
|
|
|
copy_start=start; |
|
|
|
copy_length=pos-copy_start; |
|
|
|
start=pos; |
|
|
|
} |
|
|
|
} |
|
|
|
//if it's a space |
|
|
|
if (fArgString.at(pos)==' ') { |
|
|
|
copy_start=start; |
|
|
|
copy_length=pos-copy_start; |
|
|
|
start=pos+1; |
|
|
|
} |
|
|
|
//then push the substring to the args vector |
|
|
|
args.push_back(fArgString.substr(copy_start,copy_length)); |
|
|
|
} while(start<arg_len); |
|
|
|
|
|
|
|
//and then duplicate args into the argv array |
|
|
|
fNumArgv=args.size(); |
|
|
|
fArgv=new char* [fNumArgv]; |
|
|
|
for (i=0; i<fNumArgv; i++) { |
|
|
|
fArgv[i]=new char[args[i].length()]; |
|
|
|
fill_n(fArgv[i],args[i].length()+1,0); |
|
|
|
args[i].copy(fArgv[i],args[i].length()); |
|
|
|
} |
|
|
|
for (i=0; i<fNumArgv; i++) |
|
|
|
if (fArgv[i][0]=='-') |
|
|
|
fArgc++; |
|
|
|
} |
|
|
|
|
|
|
|
if (buf[len - 1] != '\n') { |
|
|
|
/* didn't get a whole line */ |
|
|
|
fclose(in); |
|
|
|
return -1; |
|
|
|
JackArgParser::~JackArgParser() { |
|
|
|
delete[] fArgv; |
|
|
|
} |
|
|
|
|
|
|
|
jack_tmpdir = (char *)malloc(len); |
|
|
|
memcpy(jack_tmpdir, buf, len - 1); |
|
|
|
jack_tmpdir[len - 1] = '\0'; |
|
|
|
string JackArgParser::GetArgString() { |
|
|
|
return fArgString; |
|
|
|
} |
|
|
|
|
|
|
|
fclose(in); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
#endif |
|
|
|
int JackArgParser::GetNumArgv() { |
|
|
|
return fNumArgv; |
|
|
|
} |
|
|
|
|
|
|
|
void JackTools::RewriteName(const char* name, char* new_name) |
|
|
|
{ |
|
|
|
size_t i; |
|
|
|
for (i = 0; i < strlen(name); i++) { |
|
|
|
if ((name[i] == '/') || (name[i] == '\\')) |
|
|
|
new_name[i] = '_'; |
|
|
|
else |
|
|
|
new_name[i] = name[i]; |
|
|
|
int JackArgParser::GetArgc() { |
|
|
|
return fArgc; |
|
|
|
} |
|
|
|
new_name[i] = '\0'; |
|
|
|
} |
|
|
|
|
|
|
|
const char** JackArgParser::GetArgv() { |
|
|
|
return const_cast<const char**>(fArgv); |
|
|
|
} |
|
|
|
} |
|
|
|
|