PageRenderTime 69ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/meataxe-2.4.24/src/os.c

#
C | 434 lines | 192 code | 100 blank | 142 comment | 35 complexity | bdf291898216fc9f4656dba807978c20 MD5 | raw file
Possible License(s): GPL-3.0
  1. /* ============================= C MeatAxe ==================================
  2. File: $Id: os.c,v 1.4 2007-09-09 21:38:11 mringe Exp $
  3. Comment: OS dependent stuff
  4. --------------------------------------------------------------------------
  5. (C) Copyright 1998 Michael Ringe, Lehrstuhl D fuer Mathematik,
  6. RWTH Aachen, Germany <mringe@math.rwth-aachen.de>
  7. This program is free software; see the file COPYING for details.
  8. ========================================================================== */
  9. /** @defgroup os Operating System Interface
  10. * @{
  11. * @details
  12. * The MeatAxe is written for a UNIX-like operating environment and uses many functions of
  13. * the standard C library. To make the MeatAxe more portable between different operating
  14. * systems, some C library and system calls are accessed through wrapper functions. These
  15. * wrapper functions have names that begin with 'Sys'. For example @c SysFree() is the wrapper
  16. * function for @c free().
  17. **/
  18. /* --------------------------------------------------------------------------
  19. These sybols can be defined:
  20. OS_NO_CPU_TIME .......... no CPU times are available
  21. OS_TIMES_AND_SYSCONF .... use times() and sysconf() instead of getrusage()
  22. OS_NO_ITIMER ............ no interval timers
  23. -------------------------------------------------------------------------- */
  24. /* --------------------------------------------------------------------------
  25. Include files
  26. -------------------------------------------------------------------------- */
  27. #include "meataxe.h"
  28. #if defined (_WIN32)
  29. #pragma warning(disable: 4514)
  30. #pragma warning(disable: 4201 4214 4115)
  31. #include <windows.h>
  32. #pragma warning(default: 4201 4214 4115)
  33. #include <direct.h>
  34. #else
  35. #include <sys/stat.h>
  36. #include <sys/time.h>
  37. #include <sys/times.h>
  38. #include <signal.h>
  39. #include <unistd.h>
  40. #include <sys/resource.h>
  41. #endif
  42. #include <string.h>
  43. #include <time.h>
  44. #include <stdlib.h>
  45. #include <stdarg.h>
  46. /* ------------------------------------------------------------------
  47. Global data
  48. ------------------------------------------------------------------ */
  49. #if defined(OS_NO_CPU_TIME)
  50. time_t zinittime = 0; /**< Start time of this process. */
  51. #endif
  52. MTX_DEFINE_FILE_INFO
  53. /* ------------------------------------------------------------------
  54. fopen() modes
  55. ------------------------------------------------------------------ */
  56. static char *fmodes[7] = { NULL,"rt","wt","at","rb","wb","ab" };
  57. /**
  58. ** OS-specific initialization.
  59. ** This function is called during library initialization. It performs any OS-specific
  60. ** actions. Applications should never call this function directly. Use MtxInit() instead.
  61. **/
  62. void SysInit()
  63. {
  64. #if defined(OS_NO_CPU_TIME)
  65. zinittime = time(NULL);
  66. #endif
  67. }
  68. /**
  69. ** CPU time.
  70. ** This function returns the CPU time used by the calling process in units of 1/10 seconds.
  71. ** @see SysSetTimeLimit()
  72. ** @return CPU time used.
  73. **/
  74. long SysTimeUsed(void)
  75. {
  76. #if defined(_WIN32)
  77. FILETIME cr, ex, krnl, usr;
  78. LARGE_INTEGER k, u;
  79. GetProcessTimes(GetCurrentProcess(),&cr,&ex,&krnl,&usr);
  80. memcpy(&k,&krnl,sizeof(k));
  81. memcpy(&u,&usr,sizeof(u));
  82. return (long)((k.QuadPart + u.QuadPart) / 1000000);
  83. #elif defined(OS_TIMES_AND_SYSCONF)
  84. struct tms t;
  85. static long clk_tck = 0;
  86. if (clk_tck == 0)
  87. clk_tck = sysconf(_SC_CLK_TCK);
  88. times(&t);
  89. return ((long)((t.tms_utime + t.tms_stime) * 10 / clk_tck ));
  90. #elif defined(OS_NO_CPU_TIME)
  91. return (time(NULL) - zinittime) * 10;
  92. #else
  93. static struct rusage ru;
  94. getrusage(RUSAGE_SELF,&ru);
  95. return (ru.ru_utime.tv_sec * 10 + ru.ru_utime.tv_usec / 100000);
  96. #endif
  97. }
  98. /**
  99. ** @fn SysSetTimeLimit(long)
  100. ** Set CPU time limit.
  101. ** This function sets a CPU time limit for the calling process. When the limit is exceeded
  102. ** the process is killed.
  103. ** @param nsecs CPU time limit in seconds.
  104. ** @attention This function is not available on all platforms.
  105. **/
  106. #ifdef _WIN32
  107. DWORD CALLBACK Killer(void *x)
  108. {
  109. DWORD ms = (long) x;
  110. Sleep(ms);
  111. MTX_ERROR1("%E",MTX_ERR_GAME_OVER);
  112. return 0;
  113. }
  114. void SysSetTimeLimit(long nsecs)
  115. {
  116. DWORD id;
  117. CreateThread(NULL,0,Killer,(void *)(nsecs * 1000),0,&id);
  118. }
  119. #elif !defined(OS_NO_ITIMER)
  120. void vtalarm(int i)
  121. {
  122. MTX_ERROR1("%E",MTX_ERR_GAME_OVER);
  123. }
  124. void SysSetTimeLimit(long nsecs)
  125. {
  126. struct itimerval tv;
  127. tv.it_interval.tv_sec = 0;
  128. tv.it_interval.tv_usec = 0;
  129. tv.it_value.tv_sec = nsecs;
  130. tv.it_value.tv_usec = 0;
  131. setitimer(ITIMER_VIRTUAL,&tv,NULL);
  132. signal(SIGVTALRM,vtalarm);
  133. }
  134. #else /* No interval timer, sorry... */
  135. void SysSetTimeLimit(long nsecs)
  136. {
  137. }
  138. #endif
  139. /**
  140. ** Open a file.
  141. ** This function opens a file, like @c fopen(). The second argument, must be one of the
  142. ** predfined constants FM_READ (open for reading), FM_CREAT (create a new file and open for
  143. ** writing, or FM_APPEND (append to existing file or create a new file).
  144. ** Additional flags may be or'ed to the mode:
  145. ** @par FM_LIB
  146. ** If the file does not exist in the current directory, look in the library directory.
  147. ** The library directory is defined either by the environment variable @c MTXLIB, or at
  148. ** compile-time by the macro @c MTXLIB.
  149. ** @par FM_TEXT
  150. ** Open in text mode. This flag must be used on some systems (e.g., MS-DOS) to open text files.
  151. ** By default, files are assumed to contain binary data.
  152. ** @par FM_NOERROR
  153. ** Do not generate an error if the file does not exist.
  154. ** @see FfReadHeader() FfWriteHeader()
  155. ** @return A pointer to the open file or NULL on error.
  156. **/
  157. FILE *SysFopen(const char *name, int mode)
  158. {
  159. char buf[300];
  160. int m;
  161. FILE *f;
  162. m = mode & 0x0F; /* Append, read or create? */
  163. if ((mode & FM_TEXT) == 0) m += 3; /* Binary mode */
  164. if (m < 1 || m > 6 || (mode & 0x0F) == 0)
  165. {
  166. MTX_ERROR1("Invalid file mode %d",mode);
  167. return NULL;
  168. }
  169. f = fopen(name,fmodes[m]);
  170. if (f != NULL)
  171. return f;
  172. /* Search library directory
  173. ------------------------ */
  174. if ((mode & FM_LIB) != 0)
  175. {
  176. strcpy(buf,MtxLibDir);
  177. strcat(buf,"/");
  178. strcat(buf,name);
  179. f = fopen(buf,fmodes[m]);
  180. }
  181. /* Error handling
  182. -------------- */
  183. if (f == NULL && (mode & FM_NOERROR) == 0)
  184. MTX_ERROR1("%s: %S",name);
  185. return f;
  186. }
  187. /** Set file pointer.
  188. ** This function sets the file pointer to a given position. If pos is greater than or equal to
  189. ** zero, it is interpreted as an absolute position (relative to start of file). If @c pos is
  190. ** negative, the file pointer is moved to the end of file.
  191. ** @see SysFseekRelative(), FfSeekRow()
  192. ** @param file File handle.
  193. ** @param pos New position of file pointer.
  194. ** @return 0 on success, nonzero otherwise.
  195. **/
  196. int SysFseek(FILE *file, long pos)
  197. {
  198. if (pos < 0)
  199. return fseek(file,(long) 0,SEEK_END);
  200. else
  201. return fseek(file,pos,SEEK_SET);
  202. }
  203. /**
  204. ** Remove a file
  205. ** This function deletes a file. On a UNIX system, SysRemoveFile() just calls remove().
  206. ** If the file to be deleted does not exist or cannot be removed for some other reason,
  207. ** run-time error error is generated.
  208. **/
  209. int SysRemoveFile(const char *name)
  210. {
  211. if (remove(name) != 0)
  212. {
  213. MTX_ERROR1("Cannot remove file '%s'",name);
  214. return -1;
  215. }
  216. return 0;
  217. }
  218. /**
  219. ** Remove a directory.
  220. ** This function removes the specified directory.
  221. ** @see SysCreateDirectory().
  222. ** @param name Name of the directory.
  223. ** @return 0 on success, -1 on error.
  224. **/
  225. int SysRemoveDirectory(const char *name)
  226. {
  227. if (rmdir(name) != 0)
  228. {
  229. MTX_ERROR1("Cannot remove directory '%s'",name);
  230. return -1;
  231. }
  232. return 0;
  233. }
  234. /**
  235. ** Create a directory.
  236. ** This function creates a new directory. If the directory cannot be created for some reason,
  237. ** a run-time error is generated and the function returns -1.
  238. ** @see SysRemoveDirectory()
  239. ** @param name Name of the directory.
  240. ** @return 0 on success, -1 on error.
  241. **/
  242. int SysCreateDirectory(const char *name)
  243. {
  244. #ifdef _WIN32
  245. if (mkdir(name) != 0)
  246. #else
  247. if (mkdir(name,0755) != 0)
  248. #endif
  249. {
  250. MTX_ERROR1("Cannot create directory '%s'",name);
  251. return -1;
  252. }
  253. return 0;
  254. }
  255. /**
  256. ** Set file pointer relative to current position.
  257. ** This function moves the file pointer by a given number of bytes, which may be positive
  258. ** or negative.
  259. ** @param file The file handle.
  260. ** @param distance The number of bytes by which the file pointer shall be moved.
  261. ** @return 0 on success, nonzero on error.
  262. ** @see SysFseek(), FfSeekRow()
  263. **/
  264. int SysFseekRelative(FILE *file, long distance)
  265. {
  266. return fseek(file,distance,SEEK_CUR);
  267. }
  268. /**
  269. ** Allocate memory.
  270. ** This function works like @c malloc(), but the return value is never 0, even when the function
  271. ** was called with a 0 argument.
  272. ** @param nbytes Size of memory block to allocate.
  273. ** @return Pointer to memory block or NULL on error.
  274. **/
  275. void *SysMalloc(size_t nbytes)
  276. {
  277. void *x;
  278. if (nbytes == 0)
  279. nbytes = 1;
  280. x = malloc(nbytes);
  281. if (x == NULL)
  282. MTX_ERROR1("Cannot allocate %l bytes: %S",(long int) nbytes);
  283. return x;
  284. }
  285. /**
  286. ** Resize memory block.
  287. ** This function works like @c realloc() but handles zero-length blocks differently (namely, by
  288. ** allocating 1 byte instead) to avoid problems with broken @c realloc() implementations.
  289. ** @param buf Pointer to memory block.
  290. ** @param nbytes Desired new size.
  291. ** @return Pointer to resized memory block or NULL on error.
  292. **/
  293. void *SysRealloc(void *buf, size_t nbytes)
  294. {
  295. void *x;
  296. if (nbytes == 0)
  297. nbytes = 1;
  298. x = realloc(buf,nbytes);
  299. if (x == NULL)
  300. MTX_ERROR1("Cannot reallocate %l bytes: %S",(long) nbytes);
  301. return x;
  302. }
  303. /**
  304. ** Free memory block.
  305. ** This function works like @c free() but checks if the argument is not NULL. Otherwise, an
  306. ** appropriate error message is generated.
  307. ** @param x Pointer to the memory block.
  308. **/
  309. void SysFree(void *x)
  310. {
  311. if (x == NULL)
  312. MTX_ERROR("Attempt to free() NULL pointer");
  313. else
  314. free(x);
  315. }
  316. /** Get process id.
  317. ** This function returns a number which uniquely identifies the calling process on the local
  318. ** system. The exact meaning of this number depends on the operating system. In an UNIX
  319. ** environment, it is the process id (PID).
  320. ** @return Process id.
  321. **/
  322. int SysGetPid()
  323. {
  324. int pid;
  325. #ifdef _WIN32
  326. pid = (int) GetCurrentProcessId();
  327. #else
  328. pid = (int) getpid();
  329. #endif
  330. return pid;
  331. }
  332. /** @}
  333. **/