sys_linux.c (7227B)
1 #include <unistd.h> 2 #include <signal.h> 3 #include <stdlib.h> 4 #include <limits.h> 5 #include <sys/time.h> 6 #include <sys/types.h> 7 #include <unistd.h> 8 #include <fcntl.h> 9 #include <stdarg.h> 10 #include <stdio.h> 11 #include <sys/ipc.h> 12 #include <sys/shm.h> 13 #include <sys/stat.h> 14 #include <string.h> 15 #include <ctype.h> 16 #include <sys/wait.h> 17 #include <sys/mman.h> 18 #include <errno.h> 19 #include <mntent.h> 20 21 #include <dlfcn.h> 22 23 #include "../qcommon/qcommon.h" 24 25 #include "../linux/rw_linux.h" 26 27 cvar_t *nostdout; 28 29 unsigned sys_frame_time; 30 31 uid_t saved_euid; 32 qboolean stdin_active = true; 33 34 // ======================================================================= 35 // General routines 36 // ======================================================================= 37 38 void Sys_ConsoleOutput (char *string) 39 { 40 if (nostdout && nostdout->value) 41 return; 42 43 fputs(string, stdout); 44 } 45 46 void Sys_Printf (char *fmt, ...) 47 { 48 va_list argptr; 49 char text[1024]; 50 unsigned char *p; 51 52 va_start (argptr,fmt); 53 vsprintf (text,fmt,argptr); 54 va_end (argptr); 55 56 if (strlen(text) > sizeof(text)) 57 Sys_Error("memory overwrite in Sys_Printf"); 58 59 if (nostdout && nostdout->value) 60 return; 61 62 for (p = (unsigned char *)text; *p; p++) { 63 *p &= 0x7f; 64 if ((*p > 128 || *p < 32) && *p != 10 && *p != 13 && *p != 9) 65 printf("[%02x]", *p); 66 else 67 putc(*p, stdout); 68 } 69 } 70 71 void Sys_Quit (void) 72 { 73 CL_Shutdown (); 74 Qcommon_Shutdown (); 75 fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); 76 _exit(0); 77 } 78 79 void Sys_Init(void) 80 { 81 #if id386 82 // Sys_SetFPCW(); 83 #endif 84 } 85 86 void Sys_Error (char *error, ...) 87 { 88 va_list argptr; 89 char string[1024]; 90 91 // change stdin to non blocking 92 fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); 93 94 CL_Shutdown (); 95 Qcommon_Shutdown (); 96 97 va_start (argptr,error); 98 vsprintf (string,error,argptr); 99 va_end (argptr); 100 fprintf(stderr, "Error: %s\n", string); 101 102 _exit (1); 103 104 } 105 106 void Sys_Warn (char *warning, ...) 107 { 108 va_list argptr; 109 char string[1024]; 110 111 va_start (argptr,warning); 112 vsprintf (string,warning,argptr); 113 va_end (argptr); 114 fprintf(stderr, "Warning: %s", string); 115 } 116 117 /* 118 ============ 119 Sys_FileTime 120 121 returns -1 if not present 122 ============ 123 */ 124 int Sys_FileTime (char *path) 125 { 126 struct stat buf; 127 128 if (stat (path,&buf) == -1) 129 return -1; 130 131 return buf.st_mtime; 132 } 133 134 void floating_point_exception_handler(int whatever) 135 { 136 // Sys_Warn("floating point exception\n"); 137 signal(SIGFPE, floating_point_exception_handler); 138 } 139 140 char *Sys_ConsoleInput(void) 141 { 142 static char text[256]; 143 int len; 144 fd_set fdset; 145 struct timeval timeout; 146 147 if (!dedicated || !dedicated->value) 148 return NULL; 149 150 if (!stdin_active) 151 return NULL; 152 153 FD_ZERO(&fdset); 154 FD_SET(0, &fdset); // stdin 155 timeout.tv_sec = 0; 156 timeout.tv_usec = 0; 157 if (select (1, &fdset, NULL, NULL, &timeout) == -1 || !FD_ISSET(0, &fdset)) 158 return NULL; 159 160 len = read (0, text, sizeof(text)); 161 if (len == 0) { // eof! 162 stdin_active = false; 163 return NULL; 164 } 165 166 if (len < 1) 167 return NULL; 168 text[len-1] = 0; // rip off the /n and terminate 169 170 return text; 171 } 172 173 /*****************************************************************************/ 174 175 static void *game_library; 176 177 /* 178 ================= 179 Sys_UnloadGame 180 ================= 181 */ 182 void Sys_UnloadGame (void) 183 { 184 if (game_library) 185 dlclose (game_library); 186 game_library = NULL; 187 } 188 189 /* 190 ================= 191 Sys_GetGameAPI 192 193 Loads the game dll 194 ================= 195 */ 196 void *Sys_GetGameAPI (void *parms) 197 { 198 void *(*GetGameAPI) (void *); 199 200 char name[MAX_OSPATH]; 201 char curpath[MAX_OSPATH]; 202 char *path; 203 #ifdef __i386__ 204 const char *gamename = "gamei386.so"; 205 #elif defined __alpha__ 206 const char *gamename = "gameaxp.so"; 207 #else 208 #error Unknown arch 209 #endif 210 211 setreuid(getuid(), getuid()); 212 setegid(getgid()); 213 214 if (game_library) 215 Com_Error (ERR_FATAL, "Sys_GetGameAPI without Sys_UnloadingGame"); 216 217 getcwd(curpath, sizeof(curpath)); 218 219 Com_Printf("------- Loading %s -------", gamename); 220 221 // now run through the search paths 222 path = NULL; 223 while (1) 224 { 225 path = FS_NextPath (path); 226 if (!path) 227 return NULL; // couldn't find one anywhere 228 sprintf (name, "%s/%s/%s", curpath, path, gamename); 229 game_library = dlopen (name, RTLD_NOW ); 230 if (game_library) 231 { 232 Com_DPrintf ("LoadLibrary (%s)\n",name); 233 break; 234 } 235 } 236 237 GetGameAPI = (void *)dlsym (game_library, "GetGameAPI"); 238 if (!GetGameAPI) 239 { 240 Sys_UnloadGame (); 241 return NULL; 242 } 243 244 return GetGameAPI (parms); 245 } 246 247 /*****************************************************************************/ 248 249 void Sys_AppActivate (void) 250 { 251 } 252 253 void Sys_SendKeyEvents (void) 254 { 255 #ifndef DEDICATED_ONLY 256 if (KBD_Update_fp) 257 KBD_Update_fp(); 258 #endif 259 260 // grab frame time 261 sys_frame_time = Sys_Milliseconds(); 262 } 263 264 /*****************************************************************************/ 265 266 char *Sys_GetClipboardData(void) 267 { 268 return NULL; 269 } 270 271 int main (int argc, char **argv) 272 { 273 int time, oldtime, newtime; 274 275 // go back to real user for config loads 276 saved_euid = geteuid(); 277 seteuid(getuid()); 278 279 Qcommon_Init(argc, argv); 280 281 fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); 282 283 nostdout = Cvar_Get("nostdout", "0", 0); 284 if (!nostdout->value) { 285 fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); 286 // printf ("Linux Quake -- Version %0.3f\n", LINUX_VERSION); 287 } 288 289 oldtime = Sys_Milliseconds (); 290 while (1) 291 { 292 // find time spent rendering last frame 293 do { 294 newtime = Sys_Milliseconds (); 295 time = newtime - oldtime; 296 } while (time < 1); 297 Qcommon_Frame (time); 298 oldtime = newtime; 299 } 300 301 } 302 303 void Sys_CopyProtect(void) 304 { 305 FILE *mnt; 306 struct mntent *ent; 307 char path[MAX_OSPATH]; 308 struct stat st; 309 qboolean found_cd = false; 310 311 static qboolean checked = false; 312 313 if (checked) 314 return; 315 316 if ((mnt = setmntent("/etc/mtab", "r")) == NULL) 317 Com_Error(ERR_FATAL, "Can't read mount table to determine mounted cd location."); 318 319 while ((ent = getmntent(mnt)) != NULL) { 320 if (strcmp(ent->mnt_type, "iso9660") == 0) { 321 // found a cd file system 322 found_cd = true; 323 sprintf(path, "%s/%s", ent->mnt_dir, "install/data/quake2.exe"); 324 if (stat(path, &st) == 0) { 325 // found it 326 checked = true; 327 endmntent(mnt); 328 return; 329 } 330 sprintf(path, "%s/%s", ent->mnt_dir, "Install/Data/quake2.exe"); 331 if (stat(path, &st) == 0) { 332 // found it 333 checked = true; 334 endmntent(mnt); 335 return; 336 } 337 sprintf(path, "%s/%s", ent->mnt_dir, "quake2.exe"); 338 if (stat(path, &st) == 0) { 339 // found it 340 checked = true; 341 endmntent(mnt); 342 return; 343 } 344 } 345 } 346 endmntent(mnt); 347 348 if (found_cd) 349 Com_Error (ERR_FATAL, "Could not find a Quake2 CD in your CD drive."); 350 Com_Error (ERR_FATAL, "Unable to find a mounted iso9660 file system.\n" 351 "You must mount the Quake2 CD in a cdrom drive in order to play."); 352 } 353 354 #if 0 355 /* 356 ================ 357 Sys_MakeCodeWriteable 358 ================ 359 */ 360 void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) 361 { 362 363 int r; 364 unsigned long addr; 365 int psize = getpagesize(); 366 367 addr = (startaddr & ~(psize-1)) - psize; 368 369 // fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr, 370 // addr, startaddr+length, length); 371 372 r = mprotect((char*)addr, length + startaddr - addr + psize, 7); 373 374 if (r < 0) 375 Sys_Error("Protection change failed\n"); 376 377 } 378 379 #endif