Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

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