1/*
2 * Copyright (c) 2010-2016 OTClient <https://github.com/edubart/otclient>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#if !defined(WIN32) && !defined(__EMSCRIPTEN__)
24
25#include <framework/global.h>
26#include "platform.h"
27#include <fstream>
28#include <unistd.h>
29#include <string.h>
30#include <framework/stdext/stdext.h>
31#include <framework/core/eventdispatcher.h>
32
33#include <sys/stat.h>
34#include <execinfo.h>
35
36void Platform::processArgs(std::vector<std::string>& args)
37{
38 //nothing todo, linux args are already utf8 encoded
39}
40
41bool Platform::spawnProcess(std::string process, const std::vector<std::string>& args)
42{
43 struct stat sts;
44 if(stat(process.c_str(), &sts) == -1 && errno == ENOENT)
45 return false;
46
47 pid_t pid = fork();
48 if(pid == -1)
49 return false;
50
51 if(pid == 0) {
52 char* cargs[args.size()+2];
53 cargs[0] = (char*)process.c_str();
54 for(uint i=1;i<=args.size();++i)
55 cargs[i] = (char*)args[i-1].c_str();
56 cargs[args.size()+1] = 0;
57
58 if(execv(process.c_str(), cargs) == -1)
59 _exit(EXIT_FAILURE);
60 }
61
62 return true;
63}
64
65int Platform::getProcessId()
66{
67 return getpid();
68}
69
70bool Platform::isProcessRunning(const std::string& name)
71{
72 return false;
73}
74
75bool Platform::killProcess(const std::string& name)
76{
77 return false;
78}
79
80std::string Platform::getTempPath()
81{
82 return "/tmp/";
83}
84
85std::string Platform::getCurrentDir()
86{
87 std::string res;
88 char cwd[2048];
89 if(getcwd(cwd, sizeof(cwd)) != NULL) {
90 res = cwd;
91 res += "/";
92 }
93 return res;
94}
95
96bool Platform::copyFile(std::string from, std::string to)
97{
98 return system(stdext::format("/bin/cp '%s' '%s'", from, to).c_str()) == 0;
99}
100
101bool Platform::fileExists(std::string file)
102{
103 struct stat buffer;
104 return (stat(file.c_str(), &buffer) == 0);
105}
106
107bool Platform::removeFile(std::string file)
108{
109 if(unlink(file.c_str()) == 0)
110 return true;
111 return false;
112}
113
114ticks_t Platform::getFileModificationTime(std::string file)
115{
116 struct stat attrib;
117 if(stat(file.c_str(), &attrib) == 0)
118 return attrib.st_mtime;
119 return 0;
120}
121
122bool Platform::openUrl(std::string url, bool now)
123{
124 if(now) {
125 return system(stdext::format("xdg-open %s", url).c_str()) == 0;
126 } else {
127 g_dispatcher.scheduleEvent([url] {
128 system(stdext::format("xdg-open %s", url).c_str());
129 }, 50);
130 }
131 return true;
132}
133
134bool Platform::openDir(std::string path, bool now)
135{
136 if(now) {
137 return system(stdext::format("xdg-open %s", path).c_str()) == 0;
138 } else {
139 g_dispatcher.scheduleEvent([path] {
140 system(stdext::format("xdg-open %s", path).c_str());
141 }, 50);
142 }
143 return true;
144}
145
146std::string Platform::getCPUName()
147{
148 std::string line;
149 std::ifstream in("/proc/cpuinfo");
150 while(getline(in, line)) {
151 auto strs = stdext::split(line, ":");
152 std::string first = strs[0];
153 std::string second = strs[1];
154 stdext::trim(first);
155 stdext::trim(second);
156 if(strs.size() == 2 && first == "model name")
157 return second;
158 }
159 return std::string();
160}
161
162double Platform::getTotalSystemMemory()
163{
164 std::string line;
165 std::ifstream in("/proc/meminfo");
166 while(getline(in, line)) {
167 auto strs = stdext::split(line, ":");
168 std::string first = strs[0];
169 std::string second = strs[1];
170 stdext::trim(first);
171 stdext::trim(second);
172 if(strs.size() == 2 && first == "MemTotal")
173 return stdext::unsafe_cast<double>(second.substr(0, second.length() - 3)) * 1000.0;
174 }
175 return 0;
176}
177
178double Platform::getMemoryUsage()
179{
180 return 0;
181}
182
183std::string Platform::getOSName()
184{
185 std::string line;
186 std::ifstream in("/etc/issue");
187 if(getline(in, line)) {
188 std::size_t end = line.find('\\');
189 std::string res = line.substr(0, end);
190 stdext::trim(res);
191 return res;
192 }
193 return std::string();
194}
195
196std::string Platform::traceback(const std::string& where, int level, int maxDepth)
197{
198 std::stringstream ss;
199
200 ss << "\nC++ stack traceback:";
201 if(!where.empty())
202 ss << "\n\t[C++]: " << where;
203
204 void* buffer[maxDepth + level + 1];
205 int numLevels = backtrace(buffer, maxDepth + level + 1);
206 char **tracebackBuffer = backtrace_symbols(buffer, numLevels);
207 if(tracebackBuffer) {
208 for(int i = 1 + level; i < numLevels; i++) {
209 std::string line = tracebackBuffer[i];
210 if(line.find("__libc_start_main") != std::string::npos)
211 break;
212 std::size_t demanglePos = line.find("(_Z");
213 if(demanglePos != std::string::npos) {
214 demanglePos++;
215 int len = std::min(line.find_first_of("+", demanglePos), line.find_first_of(")", demanglePos)) - demanglePos;
216 std::string funcName = line.substr(demanglePos, len);
217 line.replace(demanglePos, len, stdext::demangle_name(funcName.c_str()));
218 }
219 ss << "\n\t" << line;
220 }
221 free(tracebackBuffer);
222 }
223
224 return ss.str();
225}
226
227std::vector<std::string> Platform::getMacAddresses()
228{
229 return std::vector<std::string>();
230}
231
232std::string Platform::getUserName()
233{
234 char buffer[30];
235 getlogin_r(buffer, sizeof(buffer) - 1);
236 buffer[29] = 0; // just in case
237 return std::string(buffer);
238}
239
240std::vector<std::string> Platform::getDlls()
241{
242 return std::vector<std::string>();
243}
244
245std::vector<std::string> Platform::getProcesses()
246{
247 return std::vector<std::string>();
248}
249
250std::vector<std::string> Platform::getWindows()
251{
252 return std::vector<std::string>();
253}
254
255
256#endif
257