/** * Checks whether a kernel module is available for loading * * @param module_name The module name to be checked (filename) * @return 1 if the module is available for loading, 0 otherwise */ int module_is_available(char *module_name) { char *mod_argv[] = { "modinfo", "--field", "", module_name, NULL }; return bb_run_fork(mod_argv, 1) == EXIT_SUCCESS; }
/** * Checks whether a kernel module is available for loading * * @param module_name The module name to be checked (filename) * @return 1 if the module is available for loading, 0 otherwise */ int module_is_available(char *module_name) { /* HACK to support call from optirun */ char *modinfo_bin = "/sbin/modinfo"; if (access(modinfo_bin, X_OK)) { /* if /sbin/modinfo is not found, pray that PATH contains it*/ modinfo_bin = "modinfo"; } char *mod_argv[] = { modinfo_bin, module_name, NULL }; return bb_run_fork(mod_argv, 1) == EXIT_SUCCESS; }
/** * Starts a program with Bumblebee if possible * * @param argc The number of arguments * @param argv The values of arguments * @return The exitcode of the program on success, EXIT_FAILURE if the program * could not be started */ static int run_app(int argc, char *argv[]) { int exitcode = EXIT_FAILURE; char buffer[BUFFER_SIZE]; int r; int ranapp = 0; r = snprintf(buffer, BUFFER_SIZE, "Checking availability..."); socketWrite(&bb_status.bb_socket, buffer, r + 1); while (bb_status.bb_socket != -1) { r = socketRead(&bb_status.bb_socket, buffer, BUFFER_SIZE); if (r > 0) { bb_log(LOG_INFO, "Response: %s\n", buffer); switch (buffer[0]) { case 'N': //No, run normally. bb_log(LOG_ERR, "Cannot access secondary GPU%s\n", buffer+2); socketClose(&bb_status.bb_socket); if (!bb_config.fallback_start) { bb_log(LOG_ERR, "Aborting because fallback start is disabled.\n"); } break; case 'Y': //Yes, run through vglrun bb_log(LOG_INFO, "Running application through vglrun.\n"); ranapp = 1; //run vglclient if any method other than proxy is used if (strncmp(bb_config.vgl_compress, "proxy", BUFFER_SIZE) != 0) { char * vglclient_args[] = { "vglclient", "-detach", 0 }; bb_run_fork(vglclient_args, 1); } /* number of options passed to --vgl-options */ unsigned int vglrun_opts_count = 0; char *next_arg = bb_config.vglrun_options; /* read vglrun options only if there is an arguments list */ if (next_arg && next_arg[0]) { do { ++vglrun_opts_count; } while ((next_arg = strchr(next_arg + 1, ' '))); } /* position of next option */ unsigned int optno = 0; /* 7 for the first options, 1 for the -- and 1 for the trailing 0 */ char ** vglrun_args = malloc(sizeof (char *) * (9 + vglrun_opts_count + argc - optind)); vglrun_args[0] = "vglrun"; vglrun_args[1] = "-c"; vglrun_args[2] = bb_config.vgl_compress; vglrun_args[3] = "-d"; vglrun_args[4] = bb_config.x_display; vglrun_args[5] = "-ld"; vglrun_args[6] = bb_config.ld_path; optno = 7; next_arg = bb_config.vglrun_options; if (next_arg && next_arg[0]) { char *current_arg; do { current_arg = next_arg; next_arg = strchr(current_arg, ' '); /* cut the string if a space is found */ if (next_arg) { *next_arg = 0; /* the next argument starts at the position after the space */ next_arg++; } vglrun_args[optno++] = current_arg; } while (next_arg); } vglrun_args[optno++] = "--"; for (r = 0; r < argc - optind; r++) { vglrun_args[r + optno] = argv[optind + r]; } vglrun_args[optno+=r] = 0; exitcode = bb_run_fork(vglrun_args, 0); free(vglrun_args); socketClose(&bb_status.bb_socket); break; default: //Something went wrong - output and exit. bb_log(LOG_ERR, "Problem: %*s\n", r, buffer); socketClose(&bb_status.bb_socket); break; } } } if (!ranapp) { exitcode = run_fallback(argv + optind); } return exitcode; }
int main(int argc, char* argv[]) { /* Setup signal handling before anything else */ signal(SIGHUP, handle_signal); signal(SIGTERM, handle_signal); signal(SIGINT, handle_signal); signal(SIGQUIT, handle_signal); /* Initializing configuration */ init_config(argc, argv); /* set runmode depending on leftover arguments */ if (optind >= argc) { bb_status.runmode = BB_RUN_STATUS; } else { bb_status.runmode = BB_RUN_APP; } bb_init_log(); bb_log(LOG_DEBUG, "%s version %s starting...\n", bb_status.program_name, GITVERSION); /* Connect to listening daemon */ bb_status.bb_socket = socketConnect(bb_config.socket_path, SOCK_NOBLOCK); if (bb_status.bb_socket < 0) { bb_log(LOG_ERR, "Could not connect to bumblebee daemon - is it running?\n"); bb_closelog(); return EXIT_FAILURE; } char buffer[BUFFER_SIZE]; int r; /* Request status */ if (bb_status.runmode == BB_RUN_STATUS) { r = snprintf(buffer, BUFFER_SIZE, "Status?"); socketWrite(&bb_status.bb_socket, buffer, r); while (bb_status.bb_socket != -1) { r = socketRead(&bb_status.bb_socket, buffer, BUFFER_SIZE); if (r > 0) { printf("Bumblebee status: %*s\n", r, buffer); socketClose(&bb_status.bb_socket); } } } /* Run given application */ if (bb_status.runmode == BB_RUN_APP) { int ranapp = 0; r = snprintf(buffer, BUFFER_SIZE, "Checking availability..."); socketWrite(&bb_status.bb_socket, buffer, r); while (bb_status.bb_socket != -1) { r = socketRead(&bb_status.bb_socket, buffer, BUFFER_SIZE); if (r > 0) { bb_log(LOG_INFO, "Response: %*s\n", r, buffer); switch (buffer[0]) { case 'N': //No, run normally. socketClose(&bb_status.bb_socket); if (!bb_config.fallback_start){ bb_log(LOG_ERR, "Cannot access secondary GPU. Aborting.\n"); } break; case 'Y': //Yes, run through vglrun bb_log(LOG_INFO, "Running application through vglrun.\n"); ranapp = 1; //run vglclient if any method other than proxy is used if (strncmp(bb_config.vgl_compress, "proxy", BUFFER_SIZE) != 0) { char * vglclient_args[] = { "vglclient", "-detach", 0 }; bb_run_fork(vglclient_args); } char ** vglrun_args = malloc(sizeof (char *) * (9 + argc - optind)); vglrun_args[0] = "vglrun"; vglrun_args[1] = "-c"; vglrun_args[2] = bb_config.vgl_compress; vglrun_args[3] = "-d"; vglrun_args[4] = bb_config.x_display; vglrun_args[5] = "-ld"; vglrun_args[6] = bb_config.ld_path; vglrun_args[7] = "--"; for (r = 0; r < argc - optind; r++) { vglrun_args[8 + r] = argv[optind + r]; } vglrun_args[8 + r] = 0; bb_run_fork_wait(vglrun_args); socketClose(&bb_status.bb_socket); break; default: //Something went wrong - output and exit. bb_log(LOG_ERR, "Problem: %*s\n", r, buffer); socketClose(&bb_status.bb_socket); break; } } } if (!ranapp && bb_config.fallback_start) { bb_log(LOG_WARNING, "Running application normally.\n"); bb_run_exec(argv + optind); } } bb_closelog(); bb_stop_all(); //stop any started processes that are left return (EXIT_SUCCESS); }