Exemple #1
0
/*
   Returns:
   NSSM_HOOK_STATUS_SUCCESS  if the hook ran successfully.
   NSSM_HOOK_STATUS_NOTFOUND if no hook was found.
   NSSM_HOOK_STATUS_ABORT    if the hook failed and we should cancel service start.
   NSSM_HOOK_STATUS_ERROR    on error.
   NSSM_HOOK_STATUS_NOTRUN   if the hook didn't run.
   NSSM_HOOK_STATUS_TIMEOUT  if the hook timed out.
   NSSM_HOOK_STATUS_FAILED   if the hook failed.
*/
int nssm_hook(hook_thread_t *hook_threads, nssm_service_t *service, TCHAR *hook_event, TCHAR *hook_action, unsigned long *hook_control, unsigned long deadline, bool async) {
  int ret = 0;

  hook_t *hook = (hook_t *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(hook_t));
  if (! hook) {
    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_OUT_OF_MEMORY, _T("hook"), _T("nssm_hook()"), 0);
    return NSSM_HOOK_STATUS_ERROR;
  }

  FILETIME now;
  GetSystemTimeAsFileTime(&now);

  EnterCriticalSection(&service->hook_section);

  /* Set the environment. */
  if (service->env) duplicate_environment(service->env);
  if (service->env_extra) set_environment_block(service->env_extra);

  /* ABI version. */
  TCHAR number[16];
  _sntprintf_s(number, _countof(number), _TRUNCATE, _T("%lu"), NSSM_HOOK_VERSION);
  SetEnvironmentVariable(NSSM_HOOK_ENV_VERSION, number);

  /* Event triggering this action. */
  SetEnvironmentVariable(NSSM_HOOK_ENV_EVENT, hook_event);

  /* Hook action. */
  SetEnvironmentVariable(NSSM_HOOK_ENV_ACTION, hook_action);

  /* Control triggering this action.  May be empty. */
  if (hook_control) SetEnvironmentVariable(NSSM_HOOK_ENV_TRIGGER, service_control_text(*hook_control));
  else SetEnvironmentVariable(NSSM_HOOK_ENV_TRIGGER, _T(""));

  /* Last control handled. */
  SetEnvironmentVariable(NSSM_HOOK_ENV_LAST_CONTROL, service_control_text(service->last_control));

  /* Path to NSSM. */
  TCHAR path[PATH_LENGTH];
  GetModuleFileName(0, path, _countof(path));
  SetEnvironmentVariable(NSSM_HOOK_ENV_IMAGE_PATH, path);

  /* NSSM version. */
  SetEnvironmentVariable(NSSM_HOOK_ENV_NSSM_CONFIGURATION, NSSM_CONFIGURATION);
  SetEnvironmentVariable(NSSM_HOOK_ENV_NSSM_VERSION, NSSM_VERSION);
  SetEnvironmentVariable(NSSM_HOOK_ENV_BUILD_DATE, NSSM_DATE);

  /* NSSM PID. */
  _sntprintf_s(number, _countof(number), _TRUNCATE, _T("%lu"), GetCurrentProcessId());
  SetEnvironmentVariable(NSSM_HOOK_ENV_PID, number);

  /* NSSM runtime. */
  set_hook_runtime(NSSM_HOOK_ENV_RUNTIME, &service->nssm_creation_time, &now);

  /* Application PID. */
  if (service->pid) {
    _sntprintf_s(number, _countof(number), _TRUNCATE, _T("%lu"), service->pid);
    SetEnvironmentVariable(NSSM_HOOK_ENV_APPLICATION_PID, number);
    /* Application runtime. */
    set_hook_runtime(NSSM_HOOK_ENV_APPLICATION_RUNTIME, &service->creation_time, &now);
    /* Exit code. */
    SetEnvironmentVariable(NSSM_HOOK_ENV_EXITCODE, _T(""));
  }
  else {
    SetEnvironmentVariable(NSSM_HOOK_ENV_APPLICATION_PID, _T(""));
    if (str_equiv(hook_event, NSSM_HOOK_EVENT_START) && str_equiv(hook_action, NSSM_HOOK_ACTION_PRE)) {
      SetEnvironmentVariable(NSSM_HOOK_ENV_APPLICATION_RUNTIME, _T(""));
      SetEnvironmentVariable(NSSM_HOOK_ENV_EXITCODE, _T(""));
    }
    else {
      set_hook_runtime(NSSM_HOOK_ENV_APPLICATION_RUNTIME, &service->creation_time, &service->exit_time);
      /* Exit code. */
      _sntprintf_s(number, _countof(number), _TRUNCATE, _T("%lu"), service->exitcode);
      SetEnvironmentVariable(NSSM_HOOK_ENV_EXITCODE, number);
    }
  }

  /* Deadline for this script. */
  _sntprintf_s(number, _countof(number), _TRUNCATE, _T("%lu"), deadline);
  SetEnvironmentVariable(NSSM_HOOK_ENV_DEADLINE, number);

  /* Service name. */
  SetEnvironmentVariable(NSSM_HOOK_ENV_SERVICE_NAME, service->name);
  SetEnvironmentVariable(NSSM_HOOK_ENV_SERVICE_DISPLAYNAME, service->displayname);

  /* Times the service was asked to start. */
  _sntprintf_s(number, _countof(number), _TRUNCATE, _T("%lu"), service->start_requested_count);
  SetEnvironmentVariable(NSSM_HOOK_ENV_START_REQUESTED_COUNT, number);

  /* Times the service actually did start. */
  _sntprintf_s(number, _countof(number), _TRUNCATE, _T("%lu"), service->start_count);
  SetEnvironmentVariable(NSSM_HOOK_ENV_START_COUNT, number);

  /* Times the service exited. */
  _sntprintf_s(number, _countof(number), _TRUNCATE, _T("%lu"), service->exit_count);
  SetEnvironmentVariable(NSSM_HOOK_ENV_EXIT_COUNT, number);

  /* Throttled count. */
  _sntprintf_s(number, _countof(number), _TRUNCATE, _T("%lu"), service->throttle);
  SetEnvironmentVariable(NSSM_HOOK_ENV_THROTTLE_COUNT, number);

  /* Command line. */
  TCHAR app[CMD_LENGTH];
  _sntprintf_s(app, _countof(app), _TRUNCATE, _T("\"%s\" %s"), service->exe, service->flags);
  SetEnvironmentVariable(NSSM_HOOK_ENV_COMMAND_LINE, app);

  TCHAR cmd[CMD_LENGTH];
  if (get_hook(service->name, hook_event, hook_action, cmd, sizeof(cmd))) {
    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_GET_HOOK_FAILED, hook_event, hook_action, service->name, 0);
    duplicate_environment_strings(service->initial_env);
    LeaveCriticalSection(&service->hook_section);
    HeapFree(GetProcessHeap(), 0, hook);
    return NSSM_HOOK_STATUS_ERROR;
  }

  /* No hook. */
  if (! _tcslen(cmd)) {
    duplicate_environment_strings(service->initial_env);
    LeaveCriticalSection(&service->hook_section);
    HeapFree(GetProcessHeap(), 0, hook);
    return NSSM_HOOK_STATUS_NOTFOUND;
  }

  /* Run the command. */
  STARTUPINFO si;
  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof(si);
  PROCESS_INFORMATION pi;
  ZeroMemory(&pi, sizeof(pi));
  unsigned long flags = 0;
#ifdef UNICODE
  flags |= CREATE_UNICODE_ENVIRONMENT;
#endif
  ret = NSSM_HOOK_STATUS_NOTRUN;
  if (CreateProcess(0, cmd, 0, 0, false, flags, 0, service->dir, &si, &pi)) {
    hook->name = (TCHAR *) HeapAlloc(GetProcessHeap(), 0, HOOK_NAME_LENGTH * sizeof(TCHAR));
    if (hook->name) _sntprintf_s(hook->name, HOOK_NAME_LENGTH, _TRUNCATE, _T("%s (%s/%s)"), service->name, hook_event, hook_action);
    hook->process_handle = pi.hProcess;
    hook->pid = pi.dwProcessId;
    hook->deadline = deadline;
    if (get_process_creation_time(hook->process_handle, &hook->creation_time)) GetSystemTimeAsFileTime(&hook->creation_time);

    unsigned long tid;
    HANDLE thread_handle = CreateThread(NULL, 0, await_hook, (void *) hook, 0, &tid);
    if (thread_handle) {
      if (async) {
        ret = 0;
        await_hook_threads(hook_threads, service->status_handle, &service->status, 0);
        add_thread_handle(hook_threads, thread_handle, hook->name);
      }
      else {
        await_single_handle(service->status_handle, &service->status, thread_handle, hook->name, _T(__FUNCTION__), deadline + NSSM_SERVICE_STATUS_DEADLINE);
        unsigned long exitcode;
        GetExitCodeThread(thread_handle, &exitcode);
        ret = (int) exitcode;
        CloseHandle(thread_handle);
      }
    }
    else {
      log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_CREATETHREAD_FAILED, error_string(GetLastError()), 0);
      await_hook(hook);
      if (hook->name) HeapFree(GetProcessHeap(), 0, hook->name);
      HeapFree(GetProcessHeap(), 0, hook);
    }
  }
  else {
    log_event(EVENTLOG_ERROR_TYPE, NSSM_EVENT_HOOK_CREATEPROCESS_FAILED, hook_event, hook_action, service->name, cmd, error_string(GetLastError()), 0);
    HeapFree(GetProcessHeap(), 0, hook);
  }

  /* Restore our environment. */
  duplicate_environment_strings(service->initial_env);

  LeaveCriticalSection(&service->hook_section);

  return ret;
}
Exemple #2
0
/* Callback function, called when a new device has been inserted. */
static void
device_added(LibHalContext *context, const char *did)
{
    const char *dudi, *fstype;
    char *dev, *mountp, *mountable, *label, *locked_reason;
    LibHalVolume *volume;
    LibHalDrive *drive;
    struct device_t *device;

    if (libhal_device_property_exists(context, did, "info.locked",
                                      (DBusError *)NULL)
            && libhal_device_get_property_bool(context, did, "info.locked",
                                               (DBusError *)NULL)) {
        if (debug_mode_flag) {
            locked_reason = libhal_device_get_property_string(
                                context, did, "info.locked.reason",
                                (DBusError *)NULL);
            if (locked_reason) {
                if (debug_mode_flag)
                    printf("%s%d: %s\n", __FILE__, __LINE__, locked_reason);
                libhal_free_string(locked_reason);
            }
        }
        return;
    }

    if (!libhal_device_query_capability(context, did, "volume",
                                        (DBusError *)NULL))
        return;
    label = libhal_device_get_property_string(context, did, "volume.label",
                                              (DBusError *)NULL);
    if (!(mountable = libhal_device_get_property_string(
                          context, did, "volume.fsusage", (DBusError *)NULL))
            || strcmp(mountable, "filesystem"))
        goto out;
    if (!(volume = libhal_volume_from_udi(context, did)))
        goto out;
    if (!(dudi = libhal_volume_get_storage_device_udi(volume)))
        goto out;
    if (!(drive = libhal_drive_from_udi(context, dudi)))
        goto out;
    if (!libhal_drive_is_hotpluggable(drive)
            && !libhal_drive_uses_removable_media(drive))
        goto out;
    if (!(fstype = libhal_volume_get_fstype(volume)))
        goto out;
    if (!(dev = libhal_device_get_property_string(context, did, "block.device",
                                                  (DBusError *)NULL)))
        goto out;
    mountp = get_mount_point(dev, label);
    if (!mountp)
        goto out;
    device = get_device(mountp, did, dev, label, fstype, volume, drive);
    if(!is_mounted(device)) {
        free_device(device);
        goto out;
    }
    if (!device)
        goto out;
    consider_fstab(device);

    device->hook = malloc(2*sizeof(char*)); 
    if(!file_exists(HOOK_PATH)) {
        device->hook[0] = get_hook(device, "mount");
        device->hook[1] = get_hook(device, "umount");
    }
    else {
        device->hook[0] = NULL;
        device->hook[1] = NULL;
    }

    if (file_exists(device->mountp) < 0)
        mkdir(device->mountp, 0750);
    do_mount(device) < 0 ? free_device(device) : add_to_device_list(device);

    if (device) {
        if (!add_fstab_entry(device))
            device->should_remove_entry = 1;
        if (debug_mode_flag)
            debug_dump_device(device);
    }

    if (device->hook[0]) run_hook(0, device);

out:
    if (mountable)
        libhal_free_string(mountable);
    if (label)
        libhal_free_string(label);
}