/* ======================== Sys_ReLaunch ======================== */ void Sys_ReLaunch() { TCHAR szPathOrig[MAX_PRINT_MSG]; STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); // DG: we don't have function arguments in Sys_ReLaunch() anymore, everyone only passed // the command-line +" +set com_skipIntroVideos 1" anyway and it was painful on POSIX systems // so let's just add it here. idStr cmdLine = Sys_GetCmdLine(); if( cmdLine.Find( "com_skipIntroVideos" ) < 0 ) { cmdLine.Append( " +set com_skipIntroVideos 1" ); } strcpy( szPathOrig, va( "\"%s\" %s", Sys_EXEPath(), cmdLine.c_str() ) ); // DG end CloseHandle( hProcessMutex ); if ( !CreateProcess( NULL, szPathOrig, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ) ) { idLib::Error( "Could not start process: '%s' ", szPathOrig ); return; } cmdSystem->AppendCommandText( "quit\n" ); }
/* ================ Sys_DefaultBasePath Get the default base path - binary image path - current directory - hardcoded Try to be intelligent: if there is no BASE_GAMEDIR, try the next path ================ */ const char *Sys_DefaultBasePath( void ) { struct stat st; idStr testbase; basepath = Sys_EXEPath(); if( basepath.Length() ) { basepath.StripFilename(); testbase = basepath; testbase += "/"; testbase += BASE_GAMEDIR; if( stat( testbase.c_str(), &st ) != -1 && S_ISDIR( st.st_mode ) ) { return basepath.c_str(); } else { common->Printf( "no '%s' directory in exe path %s, skipping\n", BASE_GAMEDIR, basepath.c_str() ); } } if( basepath != Posix_Cwd() ) { basepath = Posix_Cwd(); testbase = basepath; testbase += "/"; testbase += BASE_GAMEDIR; if( stat( testbase.c_str(), &st ) != -1 && S_ISDIR( st.st_mode ) ) { return basepath.c_str(); } else { common->Printf( "no '%s' directory in cwd path %s, skipping\n", BASE_GAMEDIR, basepath.c_str() ); } } common->Printf( "WARNING: using hardcoded default base path\n" ); return LINUX_DEFAULT_PATH; }
/* ======================== Sys_Launch ======================== */ void Sys_Launch( const char * path, idCmdArgs & args, void * data, unsigned int dataSize ) { TCHAR szPathOrig[_MAX_PATH]; STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); strcpy( szPathOrig, va( "\"%s\" %s", Sys_EXEPath(), (const char *)data ) ); if ( !CreateProcess( NULL, szPathOrig, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ) ) { idLib::Error( "Could not start process: '%s' ", szPathOrig ); return; } cmdSystem->AppendCommandText( "quit\n" ); }
/* ============== Sys_DLLPath ============== */ const char *Sys_DLLPath(void) { return Sys_EXEPath(); }
/* ======================== Sys_ReLaunch ======================== */ void Sys_ReLaunch() { // DG: implementing this... basic old fork() exec() (+ setsid()) routine.. // NOTE: this function used to have parameters: the commandline arguments, but as one string.. // for Linux/Unix we want one char* per argument so we'll just add the friggin' // " +set com_skipIntroVideos 1" to the other commandline arguments in this function. int ret = fork(); if( ret < 0 ) idLib::Error( "Sys_ReLaunch(): Couldn't fork(), reason: %s ", strerror( errno ) ); if( ret == 0 ) { // child process // get our own session so we don't depend on the (soon to be killed) // parent process anymore - else we'll freeze pid_t sId = setsid(); if( sId == ( pid_t ) - 1 ) { idLib::Error( "Sys_ReLaunch(): setsid() failed! Reason: %s ", strerror( errno ) ); } // close all FDs (except for stdin/out/err) so we don't leak FDs DIR* devfd = opendir( "/dev/fd" ); if( devfd != NULL ) { struct dirent entry; struct dirent* result; while( readdir_r( devfd, &entry, &result ) == 0 ) { const char* filename = result->d_name; char* endptr = NULL; long int fd = strtol( filename, &endptr, 0 ); if( endptr != filename && fd > STDERR_FILENO ) close( fd ); } } else { idLib::Warning( "Sys_ReLaunch(): Couldn't open /dev/fd/ - will leak file descriptors. Reason: %s", strerror( errno ) ); } // + 3 because "+set" "com_skipIntroVideos" "1" - and note that while we'll skip // one (the first) cmdargv argument, we need one more pointer for NULL at the end. int argc = cmdargc + 3; const char** argv = ( const char** )calloc( argc, sizeof( char* ) ); int i; for( i = 0; i < cmdargc - 1; ++i ) argv[i] = cmdargv[i + 1]; // ignore cmdargv[0] == executable name // add +set com_skipIntroVideos 1 argv[i++] = "+set"; argv[i++] = "com_skipIntroVideos"; argv[i++] = "1"; // execv expects NULL terminated array argv[i] = NULL; const char* exepath = Sys_EXEPath(); errno = 0; execv( exepath, ( char** )argv ); // we only get here if execv() fails, else the executable is restarted idLib::Error( "Sys_ReLaunch(): WTF exec() failed! Reason: %s ", strerror( errno ) ); } else { // original process // just do a clean shutdown cmdSystem->AppendCommandText( "quit\n" ); } // DG end }