27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 34 #include "PosixPlatform.h" 35 36 #ifdef POSIX 37 38 #include "PlatformString.h" 39 #include "FilePath.h" 40 #include "Helpers.h" 41 42 #include <assert.h> 43 #include <stdbool.h> 44 #include <sys/types.h> 45 #include <unistd.h> 46 #include <sys/sysctl.h> 47 #include <iostream> 48 #include <dlfcn.h> 49 #include <signal.h> 50 51 52 PosixPlatform::PosixPlatform(void) { 53 } 54 55 PosixPlatform::~PosixPlatform(void) { 56 } 57 58 MessageResponse PosixPlatform::ShowResponseMessage(TString title, TString description) { 59 MessageResponse result = mrCancel; 60 61 printf("%s %s (Y/N)\n", PlatformString(title).toPlatformString(), PlatformString(description).toPlatformString()); 62 fflush(stdout); 63 64 std::string input; 65 std::cin >> input; 66 67 if (input == "Y") { 68 result = mrOK; 69 } 70 71 return result; 72 } 73 74 //MessageResponse PosixPlatform::ShowResponseMessageB(TString description) { 75 // TString appname = GetModuleFileName(); | 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 34 #include "PosixPlatform.h" 35 36 #ifdef POSIX 37 38 #include "PlatformString.h" 39 #include "FilePath.h" 40 #include "Helpers.h" 41 42 #include <assert.h> 43 #include <stdbool.h> 44 #include <sys/types.h> 45 #include <unistd.h> 46 #include <sys/sysctl.h> 47 #include <sys/file.h> 48 #include <sys/stat.h> 49 #include <errno.h> 50 #include <limits.h> 51 #include <pwd.h> 52 #include <iostream> 53 #include <dlfcn.h> 54 #include <signal.h> 55 56 57 PosixPlatform::PosixPlatform(void) { 58 } 59 60 PosixPlatform::~PosixPlatform(void) { 61 if (!SingleInstanceFile.empty()) { 62 unlink(SingleInstanceFile.c_str()); 63 } 64 } 65 66 bool PosixPlatform::mkdirs(const char* path) { 67 char* p = NULL; 68 char tmp_path[PATH_MAX] = {0}; 69 70 if (strlen(path) > (sizeof(tmp_path) - 1)) { 71 // too long name 72 return false; 73 } 74 75 strcpy(tmp_path, path); 76 77 errno = 0; 78 for (p = tmp_path + 1; *p; ++p) { 79 if (*p == '/') { 80 *p = '\0'; 81 if (mkdir(tmp_path, S_IRWXU) != 0) { 82 if (errno != EEXIST) { 83 return false; 84 } 85 } 86 *p = '/'; 87 } 88 } 89 90 if (mkdir(tmp_path, S_IRWXU) != 0) { 91 if (errno != EEXIST) { 92 return false; 93 } 94 } 95 96 return true; 97 } 98 99 bool PosixPlatform::getTmpDir(char* path, int len) { 100 struct passwd* pw = getpwuid(getuid()); 101 const char* homedir = pw->pw_dir; 102 snprintf(path, len-1 , "%s%s", homedir, getTmpDirString()); 103 struct stat sb; 104 if (stat(path, &sb) != 0 || !S_ISDIR(sb.st_mode)) { 105 // the dir doesn't exist 106 if (!mkdirs(path)) { 107 return false; 108 } 109 } 110 111 return true; 112 } 113 114 // returns true if another instance is already running. 115 // if false, we need to continue regular launch. 116 bool PosixPlatform::CheckForSingleInstance(TString appName) { 117 char tmpDir[PATH_MAX] = {0}; 118 if (!getTmpDir(tmpDir, PATH_MAX)) { 119 printf("Unable to check for single instance.\n"); 120 return false; 121 } 122 123 char lock_file[PATH_MAX] = {0}; 124 snprintf(lock_file, PATH_MAX-1, "%s/%s", tmpDir, appName.c_str()); 125 SingleInstanceFile = lock_file; 126 int pid_file = open(lock_file, O_CREAT | O_RDWR, 0666); 127 int rc = flock(pid_file, LOCK_EX | LOCK_NB); 128 129 if (rc) { 130 if (EWOULDBLOCK == errno) { 131 // another instance is running 132 pid_t pid = 0; 133 read(pid_file, (void*)&pid, sizeof(pid_t)); 134 printf("Another instance is running PID: %d\n", pid); 135 if (pid != 0) { 136 singleInstanceProcessId = pid; 137 SingleInstanceFile.clear(); 138 return true; 139 } 140 } else { 141 printf("Unable to check for single instance.\n"); 142 } 143 } else { 144 // It is the first instance. 145 pid_t pid = getpid(); 146 write(pid_file, (void*)&pid, sizeof(pid_t)); 147 } 148 149 return false; 150 } 151 152 MessageResponse PosixPlatform::ShowResponseMessage(TString title, TString description) { 153 MessageResponse result = mrCancel; 154 155 printf("%s %s (Y/N)\n", PlatformString(title).toPlatformString(), PlatformString(description).toPlatformString()); 156 fflush(stdout); 157 158 std::string input; 159 std::cin >> input; 160 161 if (input == "Y") { 162 result = mrOK; 163 } 164 165 return result; 166 } 167 168 //MessageResponse PosixPlatform::ShowResponseMessageB(TString description) { 169 // TString appname = GetModuleFileName(); |