/*:::::*/ FBCALL void *fb_DylibLoad( FBSTRING *library ) { void *res = NULL; int i; char libname[MAX_PATH]; char *libnameformat[] = { "%s", "lib%s", "lib%s.so", "./%s", "./lib%s", "./lib%s.so", NULL }; // Just in case the shared lib is an FB one, temporarily reset the // terminal, to let the 2nd rtlib capture the original terminal state. // That way both rtlibs can restore the terminal properly on exit. // Note: The shared lib rtlib exits *after* the program rtlib, in case // the user forgot to dylibfree(). fb_hExitConsole(); libname[MAX_PATH-1] = '\0'; if( (library) && (library->data) ) { for( i = 0; libnameformat[i]; i++ ) { snprintf( libname, MAX_PATH-1, libnameformat[i], library->data ); fb_hConvertPath( libname ); res = dlopen( libname, RTLD_LAZY ); if( res ) break; } } /* del if temp */ fb_hStrDelTemp( library ); fb_hInitConsole(); return res; }
/*:::::*/ FBCALL int fb_ExecEx ( FBSTRING *program, FBSTRING *args, int do_fork ) { char buffer[MAX_PATH+1], *application, *arguments, **argv, *p; int i, argc = 0, res = -1, status, len_program, len_arguments; pid_t pid; if( (program == NULL) || (program->data == NULL) ) { fb_hStrDelTemp( args ); fb_hStrDelTemp( program ); return -1; } application = fb_hGetShortPath( program->data, buffer, MAX_PATH ); DBG_ASSERT( application!=NULL ); if( application==program->data ) { len_program = FB_STRSIZE( program ); application = buffer; FB_MEMCPY(application, program->data, len_program ); application[len_program] = 0; } fb_hConvertPath( application ); if( args==NULL ) { arguments = ""; } else { len_arguments = FB_STRSIZE( args ); arguments = alloca( len_arguments + 1 ); DBG_ASSERT( arguments!=NULL ); arguments[len_arguments] = 0; if( len_arguments ) argc = fb_hParseArgs( arguments, args->data, len_arguments ); } FB_STRLOCK(); fb_hStrDelTemp_NoLock( args ); fb_hStrDelTemp_NoLock( program ); FB_STRUNLOCK(); if( argc == -1 ) return -1; argc++; /* add 1 for program name */ argv = alloca( sizeof(char*) * (argc + 1 )); DBG_ASSERT( argv!=NULL ); argv[0] = application; /* scan the processed args and set pointers */ p = arguments; for( i=1 ; i<argc; i++) { argv[i] = p; /* set pointer to current argument */ while( *p++ ); /* skip to 1 char past next null char */ } argv[argc] = NULL; /* Launch */ fb_hExitConsole(); if( do_fork ) { pid = fork(); if( pid != -1 ) { if (pid == 0) { /* execvp() only returns if it failed */ execvp( application, argv ); /* HACK: execvp() failed, this must be communiated to the parent process *somehow*, so fb_ExecEx() can return -1 there */ exit( 255 ); /* FIXME: won't be able to tell the difference if the exec'ed program returned 255. Maybe a pipe could be used instead of the 255 exit code? Unless that's too slow/has side-effects */ } else if( (waitpid(pid, &status, 0) > 0) && WIFEXITED(status) ) { res = WEXITSTATUS(status); if( res == 255 ) { /* See the HACK above */ res = -1; } } } } else { res = execvp( application, argv ); } fb_hInitConsole(); return res; }
int fb_DevFileOpenEncod ( FB_FILE *handle, const char *filename, size_t fname_len ) { FILE *fp = NULL; char *openmask; char *fname; FB_LOCK(); fname = (char*) alloca(fname_len + 1); memcpy(fname, filename, fname_len); fname[fname_len] = 0; /* Convert directory separators to whatever the current platform supports */ fb_hConvertPath( fname ); handle->hooks = &hooks_dev_file; openmask = NULL; switch( handle->mode ) { case FB_FILE_MODE_APPEND: /* will create the file if it doesn't exist */ openmask = "ab"; break; case FB_FILE_MODE_INPUT: /* will fail if file doesn't exist */ openmask = "rb"; break; case FB_FILE_MODE_OUTPUT: /* will create the file if it doesn't exist */ openmask = "wb"; break; default: FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } /* try opening */ if( (fp = fopen( fname, openmask )) == NULL ) { FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_FILENOTFOUND ); } fb_hSetFileBufSize( fp ); handle->opaque = fp; if ( handle->access == FB_FILE_ACCESS_ANY) handle->access = FB_FILE_ACCESS_READWRITE; /* handle BOM */ switch( handle->mode ) { case FB_FILE_MODE_APPEND: case FB_FILE_MODE_INPUT: if( !hCheckBOM( handle ) ) { fclose( fp ); FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_FILENOTFOUND ); } break; case FB_FILE_MODE_OUTPUT: if( !hWriteBOM( handle ) ) { fclose( fp ); FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_FILENOTFOUND ); } } /* calc file size */ handle->size = fb_DevFileGetSize( fp, handle->mode, handle->encod, TRUE ); if( handle->size == -1 ) { fclose( fp ); FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_OK ); }