Ejemplo n.º 1
0
/**
 * Check for the availability of a PM method, warn if no method is available
 */
void check_pm_method(void) {
  if (bb_config.pm_method == PM_DISABLED) {
    bb_log(LOG_INFO, "PM is disabled, not performing detection.\n");
  } else {
    struct switch_info info;
    memset(&info, 0, sizeof info);
    info.driver = bb_config.driver;
    info.configured_pm = bb_pm_method_string[bb_config.pm_method];

    const char *pm_method = NULL;
    if (bb_config.pm_method != PM_AUTO) {
      /* auto-detection override */
      pm_method = bb_pm_method_string[bb_config.pm_method];
    }

    switcher = switcher_detect(pm_method, info);
    if (switcher) {
      bb_log(LOG_INFO, "Switching method '%s' is available and will be used.\n",
              switcher->name);
    } else {
      bb_log(LOG_WARNING, "No switching method available. The dedicated card"
              " will always be on.\n");
    }
  }
}
Ejemplo n.º 2
0
/**
 *  Fork to the background, and exit parent.
 */
static void daemonize(void) {
  /* Fork off the parent process */
  pid_t bb_pid = fork();
  if (bb_pid < 0) {
    bb_log(LOG_ERR, "Could not fork to background\n");
    exit(EXIT_FAILURE);
  }

  /* If we got a good PID, then we can exit the parent process. */
  if (bb_pid > 0) {
    exit(EXIT_SUCCESS);
  }

  /* Create a new SID for the child process */
  pid_t bb_sid = setsid();
  if (bb_sid < 0) {
    bb_log(LOG_ERR, "Could not set SID: %s\n", strerror(errno));
    exit(EXIT_FAILURE);
  }

  /* Change the current working directory */
  if ((chdir("/")) < 0) {
    bb_log(LOG_ERR, "Could not change to root directory: %s\n", strerror(errno));
    exit(EXIT_FAILURE);
  }

  /* Close out the standard file descriptors */
  close(STDIN_FILENO);
  close(STDOUT_FILENO);
  close(STDERR_FILENO);
}
Ejemplo n.º 3
0
/**
 * Requests a key over the socket
 * @param key The key to be retrieved
 * @param target A pointer to a char to store the value in
 * @param max_len The maximum number of bytes to be written in target, must be
 * greater than 0
 * @return 0 on success, non-zero on failure
 */
int bbsocket_query(const char *key, char *target, size_t max_len) {
  char buff[BUFFER_SIZE];
  snprintf(buff, sizeof buff, "Query %s", key);
  if (!socketWrite(&bb_status.bb_socket, buff, strlen(buff) + 1)) {
    bb_log(LOG_DEBUG, "Write failed for query of %s\n", key);
    return 1;
  }
  while (bb_status.bb_socket != -1) {
    if (socketRead(&bb_status.bb_socket, buff, sizeof (buff))) {
      if (strncmp("Value: ", buff, strlen("Value: "))) {
        bb_log(LOG_DEBUG, "Failed to query for %s: %s\n", key, buff);
        return 1;
      }
      strncpy(target, buff + strlen("Value: "), max_len);
      target[max_len - 1] = 0;
      /* remove trailing newline */
      if (strlen(target)) {
        target[strlen(target) - 1] = 0;
      }
      return 0;
    }
  }
  bb_log(LOG_DEBUG, "Read failed for query of %s\n", key);
  return 1;
}
Ejemplo n.º 4
0
int socketConnect(char * address, int nonblock) {
  //create the socket itself
  int sock = socket(PF_UNIX, SOCK_STREAM, 0);
  if (sock < 0) {
    bb_log(LOG_ERR, "Could not create socket. Error: %s\n", strerror(errno));
    return -1;
  }
  //full our the address information for the connection
  struct sockaddr_un addr;
  addr.sun_family = AF_UNIX;
  strcpy(addr.sun_path, address);
  //attempt to connect
  int r = connect(sock, (struct sockaddr*) & addr, sizeof (addr));
  if (r == 0) {
    //connection success, set nonblocking if requested.
    if (nonblock == 1) {
      int flags = fcntl(sock, F_GETFL, 0);
      flags |= O_NONBLOCK;
      fcntl(sock, F_SETFL, flags);
    }
  } else {
    //connection fail
    bb_log(LOG_ERR, "Could not connect to %s! Error: %s\n", address, strerror(errno));
    //close the socket and set it to -1
    socketClose(&sock);
  }
  return sock;
}//socketConnect
Ejemplo n.º 5
0
/**
 * Forks and runs the given application, waits for a maximum of timeout seconds for process to finish.
 *
 * @param argv The arguments values, the first one is the application path or name
 */
void bb_run_fork_wait(char** argv, int timeout) {
  check_handler();
  // Fork and attempt to run given application
  pid_t ret = fork();
  if (ret == 0) {
    // Fork went ok, child process replace
    bb_run_exec(argv);
  } else {
    if (ret > 0) {
      // Fork went ok, parent process continues
      bb_log(LOG_DEBUG, "Process %s started, PID %i.\n", argv[0], ret);
      pidlist_add(ret);
      //sleep until process finishes or timeout reached
      int i = 0;
      while (bb_is_running(ret) && ((i < timeout) || (timeout == 0)) && dowait) {
        usleep(1000000);
        i++;
      }
      //make a single attempt to kill the process if timed out, without waiting
      if (bb_is_running(ret)) {
        bb_stop(ret);
      }
    } else {
      // Fork failed
      bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]);
      return;
    }
  }
  return;
}
Ejemplo n.º 6
0
/**
 * Runs a requested program if fallback mode was enabled
 * @param argv The program and param list to be executed
 * @return EXIT_FAILURE on failure and if fallback was disabled, -1 on failure
 * and if fallback was enabled and never on success
 */
static int run_fallback(char *argv[]) {
  if (bb_status.runmode == BB_RUN_APP && bb_config.fallback_start) {
    bb_log(LOG_WARNING, "The Bumblebee server was not available.\n");
    bb_run_exec(argv);
    bb_log(LOG_ERR, "Unable to start program in fallback mode.\n");
  }
  return EXIT_FAILURE;
}
Ejemplo n.º 7
0
int main(int argc, char *argv[]) {
  int exitcode = EXIT_FAILURE;

  init_early_config(argc, argv, BB_RUN_APP);

  /* Setup signal handling before anything else */
  signal(SIGHUP, handle_signal);
  signal(SIGTERM, handle_signal);
  signal(SIGINT, handle_signal);
  signal(SIGQUIT, handle_signal);

  bb_init_log();

  /* Initializing configuration */
  init_config(argc, argv);
  bbconfig_parse_opts(argc, argv, PARSE_STAGE_PRECONF);
  GKeyFile *bbcfg = bbconfig_parse_conf();
  /* XXX load the driver (or even better, the ldpath) through the protocol */
  bbconfig_parse_opts(argc, argv, PARSE_STAGE_DRIVER);
  driver_detect();
  if (bbcfg) {
    bbconfig_parse_conf_driver(bbcfg, bb_config.driver);
    g_key_file_free(bbcfg);
  }
  bbconfig_parse_opts(argc, argv, PARSE_STAGE_OTHER);
  config_dump();

  bb_log(LOG_DEBUG, "%s version %s starting...\n", "optirun", 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");
    run_fallback(argv + optind);
    bb_closelog();
    return exitcode;
  }

  /* Request status */
  if (bb_status.runmode == BB_RUN_STATUS) {
    exitcode = report_daemon_status();
  }

  /* Run given application */
  if (bb_status.runmode == BB_RUN_APP) {
    if (optind >= argc) {
      bb_log(LOG_ERR, "Missing argument: application to run\n");
      print_usage(EXIT_FAILURE);
    } else {
      exitcode = run_app(argc, argv);
    }
  }

  bb_closelog();
  bb_stop_all(); //stop any started processes that are left
  return exitcode;
}
Ejemplo n.º 8
0
static void bbswitch_write(char *msg) {
  FILE *bbs = fopen(BBSWITCH_PATH, "w");
  if (bbs == 0) {
    bb_log(LOG_ERR, "Could not open %s: %s\n", BBSWITCH_PATH, strerror(errno));
    return;
  }
  fwrite(msg, sizeof msg, strlen(msg) + 1, bbs);
  if (ferror(bbs)) {
    bb_log(LOG_WARNING, "Could not write to %s: %s\n", BBSWITCH_PATH,
            strerror(errno));
  }
  fclose(bbs);
}
Ejemplo n.º 9
0
/**
 * Attempts to run the given application, replacing the current process but hide
 * any stderr output from the executed program
 * @param argv The program to be run
 */
static void bb_run_exec_hide_stderr(char **argv) {
  int old_stderr, exec_err;

  bb_log(LOG_DEBUG, "Hiding stderr for execution of %s\n", argv[0]);
  /* stderr fd no = 2 */
  old_stderr = dup(2);
  close(2);
  execvp(argv[0], argv);
  /* note: the below lines are only executed if execvp fails */
  exec_err = errno;
  dup2(old_stderr, 2);
  close(old_stderr);
  bb_log(LOG_ERR, "Error running \"%s\": %s\n", argv[0], strerror(exec_err));
  exit(exec_err);
}
Ejemplo n.º 10
0
/**
 * Stops all the running processes, if any
 */
void bb_stop_all(void) {
  bb_log(LOG_DEBUG, "Killing all remaining processes.\n");
  /* keep killing the first program in the list until it's empty */
  while (pidlist_start) {
    bb_stop_wait(pidlist_start->PID);
  }
}
Ejemplo n.º 11
0
/**
 *  Handle recieved signals - except SIGCHLD, which is handled in bbrun.c
 */
static void handle_signal(int sig) {
  switch (sig) {
    case SIGHUP:
      bb_log(LOG_WARNING, "Received %s signal (ignoring...)\n", strsignal(sig));
      break;
    case SIGINT:
    case SIGQUIT:
    case SIGTERM:
      bb_log(LOG_WARNING, "Received %s signal.\n", strsignal(sig));
      socketClose(&bb_status.bb_socket); //closing the socket terminates the server
      break;
    default:
      bb_log(LOG_WARNING, "Unhandled signal %s\n", strsignal(sig));
      break;
  }
}
Ejemplo n.º 12
0
/**
 * Forks and runs the given application, using an optional LD_LIBRARY_PATH. The
 * function then returns immediately.
 * stderr and stdout of the ran application is redirected to the parameter redirect.
 * stdin is redirected to /dev/null always.
 *
 * @param argv The arguments values, the first one is the program
 * @param ldpath The library path to be used if any (may be NULL)
 * @param redirect The file descriptor to redirect stdout/stderr to. Must be valid and open.
 * @return The childs process ID
 */
pid_t bb_run_fork_ld_redirect(char **argv, char *ldpath, int redirect) {
  check_handler();
  // Fork and attempt to run given application
  pid_t ret = fork();
  if (ret == 0) {
    if (ldpath && *ldpath) {
      char *current_path = getenv("LD_LIBRARY_PATH");
      /* Fork went ok, set environment if necessary */
      if (current_path) {
        char *ldpath_new = malloc(strlen(ldpath) + 1 + strlen(current_path) + 1);
        if (ldpath_new) {
          strcpy(ldpath_new, ldpath);
          strcat(ldpath_new, ":");
          strcat(ldpath_new, current_path);
          setenv("LD_LIBRARY_PATH", ldpath_new, 1);
          free(ldpath_new);
        } else {
          bb_log(LOG_WARNING, "Could not allocate memory for LD_LIBRARY_PATH\n");
        }
      } else {
        setenv("LD_LIBRARY_PATH", ldpath, 1);
      }
    }
    //open /dev/null for stdin redirect
    int devnull = open("/dev/null", O_RDWR);
    //fail silently on error, nothing we can do about it anyway...
    if (devnull >= 0){dup2(devnull, STDIN_FILENO);}
    //redirect stdout and stderr to the given filenum.
    dup2(redirect, STDOUT_FILENO);
    dup2(redirect, STDERR_FILENO);
    close(devnull);
    //ok, all ready, now actually execute
    bb_run_exec(argv);
  } else {
    if (ret > 0) {
      // Fork went ok, parent process continues
      bb_log(LOG_DEBUG, "Process %s started, PID %i.\n", argv[0], ret);
      pidlist_add(ret);
    } else {
      // Fork failed
      bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]);
      return 0;
    }
  }
  return ret;
}
Ejemplo n.º 13
0
/**
 * Attempts to unload a module if loaded, for ten seconds before
 * giving up
 *
 * @param driver The name of the driver (not a filename)
 * @return 1 if the driver is succesfully unloaded, 0 otherwise
 */
int module_unload(char *driver) {
  if (module_is_loaded(driver) == 1) {
    bb_log(LOG_INFO, "Unloading %s driver\n", driver);
    char *mod_argv[] = {
      "rmmod",
      "--wait",
      driver,
      NULL
    };
    bb_run_fork_wait(mod_argv, 10);
    if (module_is_loaded(driver) == 1) {
      bb_log(LOG_ERR, "Unloading %s driver timed out.\n", driver);
      return 0;
    }
  }
  return 1;
}
Ejemplo n.º 14
0
/**
 * Attempts to load a module. If the module has not been loaded after ten
 * seconds, give up
 *
 * @param module_name The filename of the module to be loaded
 * @param driver The name of the driver to be loaded
 * @return 1 if the driver is succesfully loaded, 0 otherwise
 */
int module_load(char *module_name, char *driver) {
  if (module_is_loaded(driver) == 0) {
    /* the module has not loaded yet, try to load it */
    bb_log(LOG_INFO, "Loading driver %s (module %s)\n", driver, module_name);
    char *mod_argv[] = {
      "modprobe",
      module_name,
      NULL
    };
    bb_run_fork_wait(mod_argv, 10);
    if (module_is_loaded(driver) == 0) {
      bb_log(LOG_ERR, "Module %s could not be loaded (timeout?)\n", module_name);
      return 0;
    }
  }
  return 1;
}
Ejemplo n.º 15
0
/**
 * Change GID and umask of the daemon
 */
static int bb_chgid(void) {
  /* Change the Group ID of bumblebee */
  struct group *gp;
  errno = 0;
  gp = getgrnam(bb_config.gid_name);
  if (gp == NULL) {
    int error_num = errno;
    bb_log(LOG_ERR, "%s\n", strerror(error_num));
    bb_log(LOG_ERR, "There is no \"%s\" group\n", bb_config.gid_name);
    exit(EXIT_FAILURE);
  }
  if (setgid(gp->gr_gid) != 0) {
    bb_log(LOG_ERR, "Could not set the GID of bumblebee: %s\n", strerror(errno));
    exit(EXIT_FAILURE);
  }
  /* Change the file mode mask */
  umask(023);
  return 0;
}
Ejemplo n.º 16
0
/**
 * Attempts to load a module.
 *
 * @param module_name The filename of the module to be loaded
 * @param driver The name of the driver to be loaded
 * @return 1 if the driver is succesfully loaded, 0 otherwise
 */
int module_load(char *module_name, char *driver) {
  int err = 0;
  int flags = KMOD_PROBE_IGNORE_LOADED;
  struct kmod_list *l, *list = NULL;

  if (module_is_loaded(driver) == 0) {
    /* the module has not loaded yet, try to load it */

    bb_log(LOG_INFO, "Loading driver '%s' (module '%s')\n", driver, module_name);
    err = kmod_module_new_from_lookup(bb_status.kmod_ctx, module_name, &list);

    if (err < 0) {
      bb_log(LOG_DEBUG, "kmod_module_new_from_lookup(%s) failed (err: %d).\n",
        module_name, err);
      return 0;
    }

    if (list == NULL) {
      bb_log(LOG_ERR, "Module '%s' not found.\n", module_name);
      return 0;
    }

    kmod_list_foreach(l, list) {
      struct kmod_module *mod = kmod_module_get_module(l);

      bb_log(LOG_DEBUG, "Loading module '%s'.\n", kmod_module_get_name(mod));
      err = kmod_module_probe_insert_module(mod, flags, NULL, NULL, NULL, 0);

      if (err < 0) {
        bb_log(LOG_DEBUG, "kmod_module_probe_insert_module(%s) failed (err: %d).\n",
          kmod_module_get_name(mod), err);
      }

      kmod_module_unref(mod);

      if (err < 0) {
        break;
      }
    }

    kmod_module_unref_list(list);
  }
Ejemplo n.º 17
0
static void childsig_handler(int signum) {
  if (signum != SIGCHLD) {
    return;
  }
  int chld_stat = 0;
  /* Wait for the child to exit */
  pid_t ret = wait(&chld_stat);
  /* Log the child termination and return value */
  if (ret == -1) {
    bb_log(LOG_DEBUG, "SIGCHILD received, but wait failed with %s\n",
            strerror(errno));
  } else if (WIFEXITED(chld_stat)) {
    bb_log(LOG_DEBUG, "Process with PID %i returned code %i\n", ret,
            WEXITSTATUS (chld_stat));
  } else if (WIFSIGNALED(chld_stat)) {
    bb_log(LOG_DEBUG, "Process with PID %i terminated with %i\n", ret,
            WTERMSIG(chld_stat));
  }
  pidlist_remove(ret);
}//childsig_handler
Ejemplo n.º 18
0
/**
 * Forks and runs the given application and waits for the process to finish
 *
 * @param argv The arguments values, the first one is the program
 * @param detached non-zero if the std in/output must be redirected to /dev/null, zero otherwise
 * @return Exit code of the program (between 0 and 255) or -1 on failure
 */
int bb_run_fork(char **argv, int detached) {
  int exitcode = -1;

  check_handler();
  /* Fork and attempt to run given application */
  pid_t pid = fork();
  if (pid == 0) {
    /* child process after fork */
    if (detached) {
      bb_run_exec_detached(argv);
    } else {
      bb_run_exec(argv);
    }
  } else if (pid > 0) {
    /* parent process after fork */
    int status = 0;

    bb_log(LOG_DEBUG, "Process %s started, PID %i.\n", argv[0], pid);
    pidlist_add(pid);

    if (waitpid(pid, &status, 0) != -1) {
      if (WIFEXITED(status)) {
        /* program exited normally, return status */
        exitcode = WEXITSTATUS(status);
      } else if (WIFSIGNALED(status)) {
        /* program was terminated by a signal */
        exitcode = 128 + WTERMSIG(status);
      }
    } else {
      bb_log(LOG_ERR, "waitpid(%i) faild with %s\n", pid, strerror(errno));
    }
    pidlist_remove(pid);
  } else {
    /* Fork failed */
    bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]);
  }

  /* could not determine return value */
  return exitcode;
}
Ejemplo n.º 19
0
/**
 * Kill the second X server if any, turn card off if requested.
 */
void stop_secondary() {
  char driver[BUFFER_SIZE];
  // kill X if it is running
  if (bb_is_running(bb_status.x_pid)) {
    bb_log(LOG_INFO, "Stopping X server\n");
    bb_stop_wait(bb_status.x_pid);
  }

  if (bb_config.pm_method == PM_DISABLED && bb_status.runmode != BB_RUN_EXIT) {
    /* do not disable the card if PM is disabled unless exiting */
    return;
  }

  //if card is on and can be switched, switch it off
  if (switcher) {
    if (switcher->need_driver_unloaded) {
      /* do not unload the drivers nor disable the card if the card is not on */
      if (switcher->status() != SWITCH_ON) {
        return;
      }
      if (pci_config_save(pci_bus_id_discrete, &pci_config_state_discrete)) {
        bb_log(LOG_WARNING, "Could not save PCI configuration space: %s\n",
                strerror(errno));
      }
      /* unload the driver loaded by the graphica card */
      if (pci_get_driver(driver, pci_bus_id_discrete, sizeof driver)) {
        module_unload(driver);
      }

      //only turn card off if no drivers are loaded
      if (pci_get_driver(NULL, pci_bus_id_discrete, 0)) {
        bb_log(LOG_DEBUG, "Drivers are still loaded, unable to disable card\n");
        return;
      }
    }
    if (switch_off() != SWITCH_OFF) {
      bb_log(LOG_WARNING, "Unable to disable discrete card.");
    }
  }
}//stop_secondary
Ejemplo n.º 20
0
void socketClose(int * sock) {
  bb_log(LOG_INFO, "Socket closed.\n");
  // do not attempt to close closed or uninitialized sockets
  if (!sock || *sock == -1) {
    return;
  }
  //half-close the socket first
  shutdown(*sock, SHUT_RDWR);
  //fully close the socket
  close(*sock);
  //set to -1 to prevent usage
  *sock = -1;
}//socketClose
Ejemplo n.º 21
0
int socketServer(char * address, int nonblock) {
  //delete the file currently there, if any
  unlink(address);
  //create the socket
  int sock = socket(AF_UNIX, SOCK_STREAM, 0);
  if (sock < 0) {
    bb_log(LOG_ERR, "Could not create socket! Error: %s\n", strerror(errno));
    return -1;
  }
  //set to nonblocking if requested
  if (nonblock == 1) {
    int flags = fcntl(sock, F_GETFL, 0);
    flags |= O_NONBLOCK;
    fcntl(sock, F_SETFL, flags);
  }
  //fill address information
  struct sockaddr_un addr;
  addr.sun_family = AF_UNIX;
  // XXX this path is 107 bytes (excl. null) on Linux, a larger path is
  // truncated. bb_config.socket_path can therefore be shrinked as well
  strncpy(addr.sun_path, address, sizeof(addr.sun_path) - 1);
  addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
  //bind the socket
  int ret = bind(sock, (struct sockaddr*) & addr, sizeof (addr));
  if (ret == 0) {
    ret = listen(sock, 100); //start listening, backlog of 100 allowed
    //allow reading and writing for group and self
    chmod(address, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
    if (ret != 0) {
      bb_log(LOG_ERR, "Listen failed! Error: %s\n", strerror(errno));
      socketClose(&sock);
    }
  } else {
    bb_log(LOG_ERR, "Binding failed! Error: %s\n", strerror(errno));
    socketClose(&sock);
  }
  return sock;
}//socketServer
Ejemplo n.º 22
0
/**
 * Whether bbswitch is available for use
 *
 * @param info A struct containing information which would help with the
 * decision whether bbswitch is usable or not
 * @return 1 if available for use for PM, 0 otherwise
 */
int bbswitch_is_available(struct switch_info info) {
  (void) info; /* unused parameter */

  /* easy one: if the path is available, bbswitch is usable */
  if (access(BBSWITCH_PATH, F_OK | R_OK | W_OK) == 0) {
    /* file exists and read/write is allowed */
    bb_log(LOG_DEBUG, "bbswitch has been detected.\n");
    return 1;
  }
  /* module is not loaded yet. Try to load it, checking whether the device is
   * recognized by bbswitch. Assuming that vga_switcheroo was not told to OFF
   * the device */
  if (module_load("bbswitch", "bbswitch")) {
    bb_log(LOG_DEBUG, "succesfully loaded bbswitch\n");
    /* hurrah, bbswitch could be loaded which means that the module is
     * available and that the card is supported */
    return 1;
  }
  /* nope, we can't use bbswitch */
  bb_log(LOG_DEBUG, "bbswitch is not available, perhaps you need to insmod"
          " it?\n");
  return 0;
}
Ejemplo n.º 23
0
/**
 * Forks and runs the given application, using an optional LD_LIBRARY_PATH. The
 * function then returns immediately
 *
 * @param argv The arguments values, the first one is the program
 * @param ldpath The library path to be used if any (may be NULL)
 * @return The childs process ID
 */
pid_t bb_run_fork_ld(char **argv, char *ldpath) {
  check_handler();
  // Fork and attempt to run given application
  pid_t ret = fork();
  if (ret == 0) {
    if (ldpath && *ldpath) {
      char *current_path = getenv("LD_LIBRARY_PATH");
      /* Fork went ok, set environment if necessary */
      if (current_path) {
        char *ldpath_new = malloc(strlen(ldpath) + 1 + strlen(current_path) + 1);
        if (ldpath_new) {
          strcpy(ldpath_new, ldpath);
          strcat(ldpath_new, ":");
          strcat(ldpath_new, current_path);
          setenv("LD_LIBRARY_PATH", ldpath_new, 1);
          free(ldpath_new);
        } else {
          bb_log(LOG_WARNING, "Could not allocate memory for LD_LIBRARY_PATH\n");
        }
      } else {
        setenv("LD_LIBRARY_PATH", ldpath, 1);
      }
    }
    bb_run_exec(argv);
  } else {
    if (ret > 0) {
      // Fork went ok, parent process continues
      bb_log(LOG_INFO, "Process %s started, PID %i.\n", argv[0], ret);
      pidlist_add(ret);
    } else {
      // Fork failed
      bb_log(LOG_ERR, "Process %s could not be started. fork() failed.\n", argv[0]);
      return 0;
    }
  }
  return ret;
}
Ejemplo n.º 24
0
static void handle_socket(struct clientsocket * C) {
  static char buffer[BUFFER_SIZE];
  //since these are local sockets, we can safely assume we get whole messages at a time
  int r = socketRead(&C->sock, buffer, BUFFER_SIZE);
  if (r > 0) {
    switch (buffer[0]) {
      case 'S'://status
        if (bb_status.errors[0] != 0) {
          r = snprintf(buffer, BUFFER_SIZE, "Error (%s): %s\n", GITVERSION, bb_status.errors);
        } else {
          if (bb_is_running(bb_status.x_pid)) {
            r = snprintf(buffer, BUFFER_SIZE, "Ready (%s). X is PID %i, %i applications using bumblebeed.\n", GITVERSION, bb_status.x_pid, bb_status.appcount);
          } else {
            r = snprintf(buffer, BUFFER_SIZE, "Ready (%s). X inactive.\n", GITVERSION);
          }
        }
        socketWrite(&C->sock, buffer, r); //we assume the write is fully successful.
        break;
      case 'F'://force VirtualGL if possible
      case 'C'://check if VirtualGL is allowed
        /// \todo Handle power management cases and powering card on/off.
        //no X? attempt to start it
        if (!bb_is_running(bb_status.x_pid)) {
          start_secondary();
        }
        if (bb_is_running(bb_status.x_pid)) {
          r = snprintf(buffer, BUFFER_SIZE, "Yes. X is active.\n");
          if (C->inuse == 0) {
            C->inuse = 1;
            bb_status.appcount++;
          }
        } else {
          if (bb_status.errors[0] != 0) {
            r = snprintf(buffer, BUFFER_SIZE, "No - error: %s\n", bb_status.errors);
          } else {
            r = snprintf(buffer, BUFFER_SIZE, "No, secondary X is not active.\n");
          }
        }
        socketWrite(&C->sock, buffer, r); //we assume the write is fully successful.
        break;
      case 'D'://done, close the socket.
        socketClose(&C->sock);
        break;
      default:
        bb_log(LOG_WARNING, "Unhandled message received: %*s\n", r, buffer);
        break;
    }
  }
}
Ejemplo n.º 25
0
/**
 * Attempts to run the given application, replacing the current process but
 * redirect all standard in/outputs to /dev/null.
 * @param argv The program to be run
 */
static void bb_run_exec_detached(char **argv) {
  int old_stderr, exec_err;
  bb_log(LOG_DEBUG, "Hiding stderr for execution of %s\n", argv[0]);
  /* Redirect all three standard file descriptors to /dev/null.
   * If daemonized, this already happened - but doing it
   * again doesn't hurt since this fork won't run forever anyway.
   */
  int devnull = open("/dev/null", O_RDWR);
  if (devnull < 0){
    bb_log(LOG_ERR, "Could not open /dev/null: %s\n", strerror(errno));
  }
  old_stderr = dup(STDERR_FILENO);
  dup2(devnull, STDIN_FILENO);
  dup2(devnull, STDOUT_FILENO);
  dup2(devnull, STDERR_FILENO);
  close(devnull);
  //done redirecting, do the exec
  execvp(argv[0], argv);
  /* note: the below lines are only executed if execvp fails */
  exec_err = errno;
  dup2(old_stderr, STDERR_FILENO);
  bb_log(LOG_ERR, "Error running \"%s\": %s\n", argv[0], strerror(exec_err));
  exit(exec_err);
}
Ejemplo n.º 26
0
/**
 * Checks whether a kernel module is loaded
 *
 * @param driver The name of the driver (not a filename)
 * @return 1 if the module is loaded, 0 otherwise
 */
int module_is_loaded(char *driver) {
  int err, state;
  struct kmod_module *mod;

  err = kmod_module_new_from_name(bb_status.kmod_ctx, driver, &mod);
  if (err < 0) {
    bb_log(LOG_DEBUG, "kmod_module_new_from_name(%s) failed (err: %d).\n",
      driver, err);
    return 0;
  }

  state = kmod_module_get_initstate(mod);
  kmod_module_unref(mod);

  return state == KMOD_MODULE_LIVE;
}
Ejemplo n.º 27
0
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);

  bb_init_log();

  check_secondary();
  init_config(argc, argv);

  /* Change GID and mask according to configuration */
  if ((bb_config.gid_name != 0) && (bb_config.gid_name[0] != 0)){
    bb_chgid();
  }

  bb_log(LOG_DEBUG, "%s version %s starting...\n", bb_status.program_name, GITVERSION);

  /* Daemonized if daemon flag is activated */
  if (bb_status.runmode == BB_RUN_DAEMON) {
    daemonize();
  }

  /* Initialize communication socket, enter main loop */
  bb_status.bb_socket = socketServer(bb_config.socket_path, SOCK_NOBLOCK);
  stop_secondary();//turn off card, nobody is connected right now.
  main_loop();
  unlink(bb_config.socket_path);
  bb_status.runmode = BB_RUN_EXIT;//make sure all methods understand we are shutting down
  if (bb_config.card_shutdown_state) {
    //if shutdown state = 1, turn on card
    start_secondary();
  } else {
    //if shutdown state = 0, turn off card
    stop_secondary();
  }
  bb_closelog();
  bb_stop_all(); //stop any started processes that are left
  return (EXIT_SUCCESS);
}
Ejemplo n.º 28
0
int socketAccept(int * sock, int nonblock) {
  if (*sock < 0) {
    return -1;
  }
  int r = accept(*sock, 0, 0);
  //set the socket to be nonblocking, if requested.
  //we could do this through accept4 with a flag, but that call is non-standard...
  if ((r >= 0) && (nonblock == 1)) {
    int flags = fcntl(r, F_GETFL, 0);
    flags |= O_NONBLOCK;
    fcntl(r, F_SETFL, flags);
  }

  if (r < 0) {
    if ((errno != EWOULDBLOCK) && (errno != EAGAIN) && (errno != EINTR)) {
      bb_log(LOG_ERR, "Error during accept - closing server socket: %s\n", strerror(errno));
      socketClose(sock);
    }
  }
  return r;
}
Ejemplo n.º 29
0
int socketRead(int * sock, void * buffer, int len) {
  if (*sock < 0) {
    return 0;
  }
  int r = recv(*sock, buffer, len, 0);
  if (r < 0) {
    switch (errno) {
      case EWOULDBLOCK: return 0;
        break;
      default:
        bb_log(LOG_WARNING, "Could not read data! Error: %s\n", strerror(errno));
        socketClose(sock);
        return 0;
        break;
    }
  }
  if (r == 0) {
    socketClose(sock);
  }
  return r;
}//socketRead
Ejemplo n.º 30
0
/**
 * Substitutes DRIVER in the passed path
 * @param x_conf_file A path to be processed
 * @param driver The replacement for each occurence of DRIVER
 * @return A path to xorg.conf with DRIVER substituted for the driver
 */
static char *xorg_path_w_driver(char *x_conf_file, char *driver) {
  static char *path;
  const char *driver_keyword = "DRIVER";
  unsigned int driver_occurences = 0;
  int path_length;
  char *pos, *next;

  /* calculate the path buffer size */
  pos = x_conf_file;
  while ((next = strstr(pos, driver_keyword)) != 0) {
    driver_occurences++;
    pos = next + strlen(driver_keyword);
  }
  path_length = strlen(x_conf_file) +
          driver_occurences * (strlen(driver_keyword) - 1);

  /* allocate some memory including null byte and make it an empty string */
  path = malloc(path_length + 1);
  if (!path) {
    bb_log(LOG_WARNING, "Could not allocate memory for xorg conf path\n");
    return NULL;
  }
  path[0] = 0;

  /* now replace for real */
  pos = x_conf_file;
  while ((next = strstr(pos, driver_keyword)) != 0) {
    int len = next - pos;
    strncat(path, pos, len);
    strncat(path, driver, path_length);

    /* the next search starts at the position after %s */
    pos = next + strlen(driver_keyword);
  }
  /* append the remainder after the last %s if any and overwrite the setting */
  strncat(path, pos, path_length);
  return path;
}