001:
002:
003:
004:
005:
006:
007:
008:
009:
010:
011:
012:
013:
014:
015:
016:
017:
018:
019:
020:
021:
022:
023:
024:
025:
026:
027:
028:
029:
030:
031:
032:
033:
034:
035:
036:
037:
038:
039:
040:
041:
042:
043:
044:
045:
046:
047:
048:
049:
050:
051:
052:
053:
054:
055:
056:
057:
058:
059:
060:
061:
062:
063:
064:
065:
066:
067:
068:
069:
070:
071:
072:
073:
074:
075:
076:
077:
078:
079:
080:
081:
082:
083:
084:
085:
086:
087:
088:
089:
090:
091:
092:
093:
094:
095:
096:
097:
098:
099:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339:
340:
341:
342:
343:
344:
345:
346:
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360:
361:
362:
363:
364:
365:
366:
367:
368:
369:
370:
371:
372:
373:


/*
* Copyright (c), Zeriph Enterprises
* All rights reserved.
*
* Contributor(s):
* Zechariah Perez, omni (at) zeriph (dot) com
*
* THIS SOFTWARE IS PROVIDED BY ZERIPH AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ZERIPH AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <omni/system.hpp>
#include <omni/defs/consts.hpp>
#include <iostream>
#include <string>
#if !defined(OMNI_WIN_API)
#if defined(OMNI_OS_WIN)
#include <direct.h> // _getcwd
#else
#include <sys/param.h>
#include <unistd.h>
#endif
#if defined(OMNI_OS_BSD)
#include <sys/sysctl.h>
#endif
#if defined(OMNI_NON_PORTABLE)
#if defined(OMNI_OS_APPLE)
#include <mach-o/dyld.h>
#include <limits.h>
#elif defined(OMNI_OS_FREEBSD)
#include <sys/sysctl.h>
#endif
#endif
#endif
#include <csignal>
#include <signal.h>
#include <cstdlib>
#include <climits>
#include <cstring>
omni::system::endian_type omni::system::endianness()
{
union {
uint32_t value;
uint8_t data[sizeof(uint32_t)];
} number;
number.data[0] = 0x00;
number.data[1] = 0x01;
number.data[2] = 0x02;
number.data[3] = 0x03;
switch (number.value) {
case UINT32_C(0x00010203):
return omni::system::endian_type::BIG;
case UINT32_C(0x03020100):
return omni::system::endian_type::LITTLE;
case UINT32_C(0x02030001):
return omni::system::endian_type::BIG_WORD;
case UINT32_C(0x01000302):
return omni::system::endian_type::LITTLE_WORD;
default: break;
}
return omni::system::endian_type::UNKNOWN;
}
omni::system::architecture_type omni::system::architecture()
{
#if defined(OMNI_ARCH_AMD64)
// AMD64
return omni::system::architecture_type::AMD64;
#elif defined(OMNI_ARCH_ARM)
// ARM
return omni::system::architecture_type::ARM;
#elif defined(OMNI_ARCH_ARM64)
//ARM64
return omni::system::architecture_type::ARM64;
#elif defined(OMNI_ARCH_BLACKFIN)
// Blackfin
return omni::system::architecture_type::BLACKFIN;
#elif defined(OMNI_ARCH_CONVEX)
// Convex
return omni::system::architecture_type::CONVEX;
#elif defined(OMNI_ARCH_DEC_ALPHA)
// DEC-Alpha
return omni::system::architecture_type::DEC_ALPHA;
#elif defined(OMNI_ARCH_ELBRUS)
// Elbrus
return omni::system::architecture_type::ELBRUS;
#elif defined(OMNI_ARCH_EPIPHANY)
// Epiphany
return omni::system::architecture_type::EPIPHANY;
#elif defined(OMNI_ARCH_HPPA_RISC)
// HP/PA RISC
return omni::system::architecture_type::HPPA_RISC;
#elif defined(OMNI_ARCH_INTEL_X80)
// Intel x80
return omni::system::architecture_type::INTEL_X80;
#elif defined(OMNI_ARCH_INTEL_X86)
// Intel x86
return omni::system::architecture_type::INTEL_X86;
#elif defined(OMNI_ARCH_INTEL_IA64)
// Intel Itanium (IA-64)
return omni::system::architecture_type::INTEL_IA64;
#elif defined(OMNI_ARCH_LOONGARCH)
// LoongArch
return omni::system::architecture_type::LOONGARCH;
#elif defined(OMNI_ARCH_MOTOROLA_68K)
// Motorola 68k
return omni::system::architecture_type::MOTOROLA_68K;
#elif defined(OMNI_ARCH_MIPS)
// MIPS
return omni::system::architecture_type::MIPS;
#elif defined(OMNI_ARCH_NEC)
// HP-NEC
return omni::system::architecture_type::NEC;
#elif defined(OMNI_ARCH_PNACL)
// PNaCl
return omni::system::architecture_type::PNACL;
#elif defined(OMNI_ARCH_POWER_PC)
// PowerPC
return omni::system::architecture_type::POWER_PC;
#elif defined(OMNI_ARCH_PYRAMID_9810)
// Pyramid 9810
return omni::system::architecture_type::PYRAMID_9810;
#elif defined(OMNI_ARCH_RISC_V)
// RISC-V
return omni::system::architecture_type::RISC_V;
#elif defined(OMNI_ARCH_RS6000)
// RS/6000
return omni::system::architecture_type::RS6000;
#elif defined(OMNI_ARCH_SPARC)
// SPARC
return omni::system::architecture_type::SPARC;
#elif defined(OMNI_ARCH_SUPER_H)
// SuperH
return omni::system::architecture_type::SUPER_H;
#elif defined(OMNI_ARCH_SYSTEM_Z)
// SystemZ
return omni::system::architecture_type::SYSTEM_Z;
#elif defined(OMNI_ARCH_TMS320)
// TMS320
return omni::system::architecture_type::TMS320;
#elif defined(OMNI_ARCH_TMS470)
// TMS470
return omni::system::architecture_type::TMS470;
#else
// Unknown
return omni::system::architecture_type::UNKNOWN;
#endif
}
int32_t omni::system::last_error()
{
return OMNI_GLE;
}
std::string omni::system::last_error_str()
{
return omni::system::error_str(OMNI_GLE);
}
#if defined(OMNI_NON_PORTABLE)
omni::string_t omni::system::cwd()
{
omni::char_t* p = new omni::char_t[FILENAME_MAX]();
#if defined(OMNI_WIN_API)
bool ret = (::GetCurrentDirectory(FILENAME_MAX, p) != 0);
#else
char* tp = new char[FILENAME_MAX]();
#if defined(OMNI_OS_WIN)
bool ret = (::_getcwd(tp, FILENAME_MAX) != 0);
#else
bool ret = (::getcwd(tp, FILENAME_MAX) != 0);
#endif
if (ret) {
tp[FILENAME_MAX - 1] = '\0';
#if defined(OMNI_UNICODE)
std::mbstowcs(p, tp, FILENAME_MAX);
#else
std::memcpy(p, tp, FILENAME_MAX);
#endif
}
delete[] tp;
#endif
if (!ret) {
delete[] p;
OMNI_DBGE(OMNI_PATH_NOT_ACCESSIBLE_STR << ": " << OMNI_GLE)
return omni::string_t();
}
omni::string_t sret(p);
delete[] p;
return sret;
}
std::string omni::system::error_str(int code)
{
#if defined(OMNI_WIN_API)//defined(OMNI_OS_WIN)
OMNI_CHAR_T* serr = new OMNI_CHAR_T[65535];
// not a direct system message, must use IGNORE_INSERTS
DWORD ret = ::FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
serr,
65535,
NULL
);
if (ret != 0) {
omni::string_t werr(serr); // make copy
delete[] serr;
serr = OMNI_NULL_PTR;
return omni::string::to_string(werr);
}
delete[] serr;
serr = OMNI_NULL_PTR;
return std::string("Unknown error ").append(omni::string::util::to_string(code));
#else
return std::strerror(code);
#endif
}
omni::string_t omni::system::path()
{
omni::char_t* p = new omni::char_t[FILENAME_MAX]();
#if !defined(OMNI_OS_WIN)
char* tp = new char[FILENAME_MAX]();
#endif
#if defined(OMNI_OS_WIN) // windows
// DEV_NOTE: ifdef OMNI_WIN_API not applicable here
bool ret = (::GetModuleFileName(0, p, FILENAME_MAX) != 0);
#elif defined(OMNI_OS_APPLE) // apple
uint32_t cb = FILENAME_MAX;
bool ret = (::_NSGetExecutablePath(tp, &cb) == 0);
#elif defined(OMNI_OS_SOLARIS) // solaris/sun
bool ret = (std::strncpy(tp, ::getexecname(), FILENAME_MAX) != 0);
#elif defined(OMNI_OS_BSD) // bsd
#if defined(OMNI_OS_FREEBSD) // freebsd
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
std::size_t cb = FILENAME_MAX;
bool ret = (::sysctl(mib, 4, tp, &cb, NULL, 0) == 0);
#else // other bsd with procfs
#if !defined(OMNI_NO_PROC_SYS)
bool ret = (::readlink("/proc/curproc/file", tp, (FILENAME_MAX - 1)) != -1);
if (!ret) {
std::memset(tp, 0, FILENAME_MAX);
char* e = std::getenv("_");
ret = (e ? (std::strncpy(tp, e, FILENAME_MAX) != 0) : false);
}
#else
std::memset(tp, 0, FILENAME_MAX);
char* e = std::getenv("_");
bool ret = (e ? (std::strncpy(tp, e, FILENAME_MAX) != 0) : false);
#endif
#endif
#else // *nix
#if !defined(OMNI_NO_PROC_SYS)
bool ret = (::readlink("/proc/self/exe", tp, (FILENAME_MAX - 1)) != -1);
if (!ret) {
std::memset(tp, 0, FILENAME_MAX);
char* e = std::getenv("_");
ret = (e ? (std::strncpy(tp, e, FILENAME_MAX) != 0) : false);
}
#else
std::memset(tp, 0, FILENAME_MAX);
char* e = std::getenv("_");
bool ret = (e ? (std::strncpy(tp, e, FILENAME_MAX) != 0) : false);
#endif
#endif
#if !defined(OMNI_OS_WIN)
if (ret) {
#if defined(OMNI_UNICODE)
ret = (std::mbstowcs(p, tp, FILENAME_MAX) != 0);
#else
ret = (std::strncpy(&p[0], tp, FILENAME_MAX) != 0);
#endif
}
delete[] tp;
#endif
if (!ret) {
delete[] p;
OMNI_DBGE(OMNI_PATH_NOT_ACCESSIBLE_STR << ": " << OMNI_GLE)
return omni::string_t();
}
omni::string_t sret(p);
delete[] p;
return sret;
}
uint64_t omni::system::processors()
{
//may return 0 when not able to detect
// if C++11, return std::thread::hardware_concurrency();
#if defined(OMNI_OS_WIN) // windows
// DEV_NOTE: ifdef OMNI_WIN_API not applicable here
SYSTEM_INFO si;
::GetSystemInfo(&si);
return static_cast<uint64_t>(si.dwNumberOfProcessors);
#elif defined(OMNI_OS_HPUX) // HPUX
// DEV_NOTE: untested (no access to HPUX system)
return static_cast<uint64_t>(::mpctl(MPC_GETNUMSPUS, NULL, NULL));
#elif defined(OMNI_OS_IRIX) // IRIX
// DEV_NOTE: untested (no access to Irix system)
return static_cast<uint64_t>(::sysconf(_SC_NPROC_ONLN));
#elif defined(OMNI_OS_BSD) // bsd
int mib[4];
int ret = 0;
std::size_t len = sizeof(ret);
/* set the mib for hw.ncpu */
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
/* get the number of CPUs from the system */
::sysctl(mib, 2, &ret, &len, NULL, 0);
if (ret < 1) {
mib[1] = HW_NCPU;
::sysctl(mib, 2, &ret, &len, NULL, 0);
if (ret < 0) { ret = 0; }
}
return static_cast<uint64_t>(ret);
#else // *nix
return static_cast<uint64_t>(::sysconf(_SC_NPROCESSORS_ONLN));
#endif
}
std::string omni::system::signal_str(int sig)
{
/* DEV_NOTE: we do not "redefine" any of the signal names in the
omni namespace as it would be redundant and unnecessarily verbose */
#if defined(OMNI_WIN_API)
switch (sig) {
case CTRL_C_EVENT: // signal when CTRL+C received
return "CTRL_C_EVENT: CTRL+C received";
case CTRL_BREAK_EVENT: // signal when CTRL+BREAK received
return "CTRL_BREAK_EVENT: CTRL+BREAK received";
case CTRL_CLOSE_EVENT: // signal when console window being closed
return "CTRL_CLOSE_EVENT: console window closing";
case CTRL_LOGOFF_EVENT: // signal when user being logged off
return "CTRL_C_EVENT: user logging off";
case CTRL_SHUTDOWN_EVENT: // signal when system is shutting down
return "CTRL_C_EVENT: system shutting down";
default: break; // other/unknown signal
}
#endif
switch (sig) {
// SIGINT is caught by the console handler in windows
case SIGINT: // signal interrupt: typically occurs when user interrupts the program (like when pressing CTRL+C)
return "SIGINT: signal interrupt";
case SIGABRT: // signal abort: abnormal termination
return "SIGABRT: abort/abnormal termination";
case SIGFPE: // signal floating point exception: occurs on erroneous arithmetic operations (like division by 0)
return "SIGFPE: floating point exception";
case SIGILL: // signal illegal instruction: typically occurs with code corruption
return "SIGILL: illegal instruction";
case SIGSEGV: // signal segmentation violation: typically occurs when the program tries to read/write invalid memory
return "SIGSEGV: segmentation violation";
case SIGTERM: // signal terminate: termination request sent to the program
return "SIGTERM: terminate";
default: break; // other/unknown signal
}
return std::string("Other/Unknown: ").append(omni::string::util::lexical_cast<std::string, int>(sig));
}
#endif