static void vpn_service_watch_cb (GPid pid, gint status, gpointer user_data) { NMVPNService *service = NM_VPN_SERVICE (user_data); NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (service); if (WIFEXITED (status)) { guint err = WEXITSTATUS (status); if (err != 0) { nm_log_warn (LOGD_VPN, "VPN service '%s' exited with error: %d", priv->name, WSTOPSIG (status)); } } else if (WIFSTOPPED (status)) { nm_log_warn (LOGD_VPN, "VPN service '%s' stopped unexpectedly with signal %d", priv->name, WSTOPSIG (status)); } else if (WIFSIGNALED (status)) { nm_log_warn (LOGD_VPN, "VPN service '%s' died with signal %d", priv->name, WTERMSIG (status)); } else { nm_log_warn (LOGD_VPN, "VPN service '%s' died from an unknown cause", priv->name); } priv->pid = 0; priv->child_watch = 0; clear_quit_timeout (service); nm_vpn_service_connections_stop (service, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); }
static gboolean nm_vpn_service_timeout (gpointer data) { NMVPNService *self = NM_VPN_SERVICE (data); NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (self); nm_log_warn (LOGD_VPN, "VPN service '%s' start timed out", priv->name); priv->start_timeout = 0; nm_vpn_service_connections_stop (self, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT); return FALSE; }
static void vpn_dir_changed (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data) { NMVPNManager *self = NM_VPN_MANAGER (user_data); NMVPNManagerPrivate *priv = NM_VPN_MANAGER_GET_PRIVATE (self); NMVPNService *service; char *path; path = g_file_get_path (file); if (!g_str_has_suffix (path, ".name")) { g_free (path); return; } switch (event_type) { case G_FILE_MONITOR_EVENT_DELETED: nm_log_dbg (LOGD_VPN, "service file %s deleted", path); service = get_service_by_namefile (self, path); if (service) { const char *service_name = nm_vpn_service_get_dbus_service (service); /* Stop active VPN connections and destroy the service */ nm_vpn_service_connections_stop (service, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED); nm_log_info (LOGD_VPN, "VPN: unloaded %s", service_name, service); g_hash_table_remove (priv->services, service_name); } break; case G_FILE_MONITOR_EVENT_CREATED: case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: nm_log_dbg (LOGD_VPN, "service file %s created or modified", path); try_add_service (self, path); break; default: nm_log_dbg (LOGD_VPN, "service file %s change event %d", path, event_type); break; } g_free (path); }
static gboolean nm_vpn_service_daemon_exec (NMVPNService *service, GError **error) { NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (service); char *vpn_argv[2]; gboolean success = FALSE; GError *spawn_error = NULL; g_return_val_if_fail (NM_IS_VPN_SERVICE (service), FALSE); g_return_val_if_fail (error != NULL, FALSE); g_return_val_if_fail (*error == NULL, FALSE); vpn_argv[0] = priv->program; vpn_argv[1] = NULL; success = g_spawn_async (NULL, vpn_argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, nm_vpn_service_child_setup, NULL, &priv->pid, &spawn_error); if (success) { nm_log_info (LOGD_VPN, "VPN service '%s' started (%s), PID %d", priv->name, priv->dbus_service, priv->pid); priv->child_watch = g_child_watch_add (priv->pid, vpn_service_watch_cb, service); priv->start_timeout = g_timeout_add_seconds (5, nm_vpn_service_timeout, service); } else { nm_log_warn (LOGD_VPN, "VPN service '%s': could not launch the VPN service. error: (%d) %s.", priv->name, spawn_error ? spawn_error->code : -1, spawn_error && spawn_error->message ? spawn_error->message : "(unknown)"); g_set_error (error, NM_VPN_MANAGER_ERROR, NM_VPN_MANAGER_ERROR_SERVICE_START_FAILED, "%s", spawn_error ? spawn_error->message : "unknown g_spawn_async() error"); nm_vpn_service_connections_stop (service, TRUE, NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED); if (spawn_error) g_error_free (spawn_error); } return success; }