This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch nm-vpn-username-capture
in repository enlightenment.

View the commit online.

commit 776def9935c5dc27c9f0afa9e26544d87f82aa0f
Author: [email protected] <[email protected]>
AuthorDate: Sun Jun 21 22:38:38 2026 -0600

    networkmanager: fix post-import username probe (single-line query)
    
    Root cause of the missing dialog: the probe queried three fields
    (connection.id, vpn.service-type, vpn.data) producing multi-line nmcli
    output, but ecore_exe delivered the process-exit event after only the first
    DATA line, so the parser saw just 20 bytes (the name) -> needed=0 -> no
    dialog. Query ONLY vpn.data (a single comma-joined line, immune to the
    race) and take the service short name from the import type instead. Thread
    the import type through enm_vpn_username_maybe_prompt.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
---
 src/modules/networkmanager/e_mod_main.c            | 11 +--
 .../networkmanager/e_networkmanager_vpn_username.c | 83 +++++++++-------------
 .../networkmanager/e_networkmanager_vpn_username.h |  7 +-
 3 files changed, 45 insertions(+), 56 deletions(-)

diff --git a/src/modules/networkmanager/e_mod_main.c b/src/modules/networkmanager/e_mod_main.c
index 326fcff0e..62e90fbf4 100644
--- a/src/modules/networkmanager/e_mod_main.c
+++ b/src/modules/networkmanager/e_mod_main.c
@@ -407,15 +407,16 @@ _enm_itc_bt_content_get(void *data, Evas_Object *obj, const char *part)
 /* ---- VPN item class callbacks --------------------------------------------- */
 
 static void
-_enm_vpn_import_done_cb(void *data EINA_UNUSED, Eina_Bool ok, const char *err,
+_enm_vpn_import_done_cb(void *data, Eina_Bool ok, const char *err,
                         const char *conn_name)
 {
+   const char *type = data;  /* import VPN type ("openvpn", ...); may be NULL */
    E_Dialog *err_dlg;
    if (ok)
      {
-        fprintf(stderr, "ENM-DBG import_done ok: conn(uuid)=%s\n",
-                conn_name ?: "(null)"); fflush(stderr);
-        if (conn_name) enm_vpn_username_maybe_prompt(conn_name);
+        fprintf(stderr, "ENM-DBG import_done ok: conn(uuid)=%s type=%s\n",
+                conn_name ?: "(null)", type ?: "(null)"); fflush(stderr);
+        if (conn_name) enm_vpn_username_maybe_prompt(conn_name, type);
         return;
      }
 
@@ -465,7 +466,7 @@ _enm_vpn_fs_done_cb(void *data, Evas_Object *fs EINA_UNUSED, void *event)
      }
    else
      {
-        enm_import_run(type, file, _enm_vpn_import_done_cb, NULL);
+        enm_import_run(type, file, _enm_vpn_import_done_cb, (void *)type);
      }
    e_object_del(E_OBJECT(dialog));
 }
diff --git a/src/modules/networkmanager/e_networkmanager_vpn_username.c b/src/modules/networkmanager/e_networkmanager_vpn_username.c
index 2ec911140..2ec3f7f5a 100644
--- a/src/modules/networkmanager/e_networkmanager_vpn_username.c
+++ b/src/modules/networkmanager/e_networkmanager_vpn_username.c
@@ -304,7 +304,8 @@ _nmcli_kv_find(const char *blob, const char *key)
 
 typedef struct _Username_Probe_Ctx
 {
-   char                *conn_name;
+   char                *conn_uuid;  /* unique id for nmcli ops */
+   char                *svc;        /* service short name, from import type */
    Ecore_Exe           *exe;
    Eina_Strbuf         *out;
    Ecore_Event_Handler *h_data;
@@ -335,8 +336,7 @@ _probe_on_del(void *data, int type EINA_UNUSED, void *event)
 {
    Username_Probe_Ctx *ctx = data;
    Ecore_Exe_Event_Del *ev = event;
-   char *id = NULL, *svc = NULL, *conn_type = NULL, *username = NULL;
-   const char *short_name = NULL;
+   char *conn_type = NULL, *username = NULL;
    const char *blob;
    Eina_Bool needed;
 
@@ -345,85 +345,72 @@ _probe_on_del(void *data, int type EINA_UNUSED, void *event)
    if (ctx->h_data) ecore_event_handler_del(ctx->h_data);
    if (ctx->h_del)  ecore_event_handler_del(ctx->h_del);
 
+   /* Single line: the vpn.data list (queried alone to avoid a multi-line
+    * ecore_exe data/exit race).  The service short name comes from the import
+    * type, so we never need vpn.service-type here. */
    blob = eina_strbuf_string_get(ctx->out);
-   /* Three lines: connection.id, vpn.service-type, then the vpn.data list. */
-   {
-      const char *l1 = blob;
-      const char *nl1 = strchr(l1, '\n');
-      if (nl1)
-        {
-           const char *l2 = nl1 + 1;
-           const char *nl2 = strchr(l2, '\n');
-           id = strndup(l1, (size_t)(nl1 - l1));
-           if (nl2)
-             {
-                const char *l3 = nl2 + 1;
-                svc = strndup(l2, (size_t)(nl2 - l2));
-                conn_type = _nmcli_kv_find(l3, "connection-type");
-                username  = _nmcli_kv_find(l3, "username");
-             }
-        }
-   }
-   if (svc) { char *d = strrchr(svc, '.'); short_name = d ? d + 1 : svc; }
+   conn_type = _nmcli_kv_find(blob, "connection-type");
+   username  = _nmcli_kv_find(blob, "username");
 
-   needed = enm_vpn_username_needed(short_name, conn_type, username);
-   fprintf(stderr, "ENM-DBG probe result: id=%s svc=%s conn_type=%s "
+   needed = enm_vpn_username_needed(ctx->svc, conn_type, username);
+   fprintf(stderr, "ENM-DBG probe result: svc=%s conn_type=%s "
            "username=%s needed=%d blob_len=%zu\n",
-           id ?: "(null)", short_name ?: "(null)", conn_type ?: "(null)",
+           ctx->svc ?: "(null)", conn_type ?: "(null)",
            username ?: "(null)", (int)needed, strlen(blob));
    fflush(stderr);
 
    if (needed)
      {
-        char *uuid_copy = strdup(ctx->conn_name);  /* ctx->conn_name is the UUID */
+        char *uuid_copy = strdup(ctx->conn_uuid);
         if (uuid_copy)
-          enm_vpn_username_dialog(id ?: ctx->conn_name,  /* display name */
-                                  short_name,            /* type label */
+          enm_vpn_username_dialog(NULL,        /* generic "VPN" header */
+                                  ctx->svc,     /* type label */
                                   username,
                                   _probe_username_entered,
                                   uuid_copy);
      }
 
-   free(id); free(svc); free(conn_type); free(username);
-   free(ctx->conn_name);
+   free(conn_type); free(username);
+   free(ctx->conn_uuid); free(ctx->svc);
    eina_strbuf_free(ctx->out);
    free(ctx);
    return ECORE_CALLBACK_DONE;
 }
 
 void
-enm_vpn_username_maybe_prompt(const char *conn_name)
+enm_vpn_username_maybe_prompt(const char *conn_uuid, const char *svc_short)
 {
    const char *nmcli;
-   char *esc_nmcli, *esc_name, cmd[4096];
+   char *esc_nmcli, *esc_uuid, cmd[4096];
    Username_Probe_Ctx *ctx;
 
-   fprintf(stderr, "ENM-DBG maybe_prompt: id=%s\n", conn_name ?: "(null)");
-   fflush(stderr);
-   if (!conn_name) return;
+   fprintf(stderr, "ENM-DBG maybe_prompt: uuid=%s svc=%s\n",
+           conn_uuid ?: "(null)", svc_short ?: "(null)"); fflush(stderr);
+   if (!conn_uuid) return;
    nmcli = enm_import_nmcli_path();
    if (!nmcli) { fprintf(stderr, "ENM-DBG maybe_prompt: nmcli NULL\n"); fflush(stderr); return; }
 
    esc_nmcli = _username_shell_escape(nmcli);
-   esc_name  = _username_shell_escape(conn_name);
-   if (!esc_nmcli || !esc_name) { free(esc_nmcli); free(esc_name); return; }
+   esc_uuid  = _username_shell_escape(conn_uuid);
+   if (!esc_nmcli || !esc_uuid) { free(esc_nmcli); free(esc_uuid); return; }
 
-   /* Query by UUID (conn_name here is the connection UUID — unique, unlike the
-    * display name).  LC_ALL=C for stable, non-localized -g output.  Fields:
-    * line1 connection.id (display name), line2 service-type, line3 vpn.data. */
+   /* Query ONLY vpn.data, by UUID (unique).  vpn.data prints as a single
+    * comma-joined line, which avoids the multi-line ecore_exe data/exit race
+    * that drops trailing lines.  The service short name comes from the import
+    * type, so vpn.service-type is not needed. */
    snprintf(cmd, sizeof(cmd),
-            "LC_ALL=C '%s' -g connection.id,vpn.service-type,vpn.data "
-            "connection show '%s'",
-            esc_nmcli, esc_name);
-   free(esc_nmcli); free(esc_name);
+            "LC_ALL=C '%s' -g vpn.data connection show '%s'",
+            esc_nmcli, esc_uuid);
+   free(esc_nmcli); free(esc_uuid);
    fprintf(stderr, "ENM-DBG probe spawn: %s\n", cmd); fflush(stderr);
 
    ctx = calloc(1, sizeof(*ctx));
    if (!ctx) return;
-   ctx->conn_name = strdup(conn_name);
+   ctx->conn_uuid = strdup(conn_uuid);
+   ctx->svc       = svc_short ? strdup(svc_short) : NULL;
    ctx->out = eina_strbuf_new();
-   if (!ctx->conn_name || !ctx->out)
-     { free(ctx->conn_name); if (ctx->out) eina_strbuf_free(ctx->out); free(ctx); return; }
+   if (!ctx->conn_uuid || !ctx->out)
+     { free(ctx->conn_uuid); free(ctx->svc); if (ctx->out) eina_strbuf_free(ctx->out); free(ctx); return; }
 
    ctx->exe = ecore_exe_pipe_run(cmd,
                                  ECORE_EXE_PIPE_READ |
@@ -431,7 +418,7 @@ enm_vpn_username_maybe_prompt(const char *conn_name)
                                  ECORE_EXE_NOT_LEADER |
                                  ECORE_EXE_TERM_WITH_PARENT, ctx);
    if (!ctx->exe)
-     { free(ctx->conn_name); eina_strbuf_free(ctx->out); free(ctx); return; }
+     { free(ctx->conn_uuid); free(ctx->svc); eina_strbuf_free(ctx->out); free(ctx); return; }
    ctx->h_data = ecore_event_handler_add(ECORE_EXE_EVENT_DATA, _probe_on_data, ctx);
    ctx->h_del  = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,  _probe_on_del,  ctx);
 }
diff --git a/src/modules/networkmanager/e_networkmanager_vpn_username.h b/src/modules/networkmanager/e_networkmanager_vpn_username.h
index 24b77b1e1..0335d1b87 100644
--- a/src/modules/networkmanager/e_networkmanager_vpn_username.h
+++ b/src/modules/networkmanager/e_networkmanager_vpn_username.h
@@ -44,8 +44,9 @@ void enm_vpn_username_dialog(const char *conn_name, const char *type_label,
                              const char *initial,
                              Enm_Username_Entered_Cb cb, void *data);
 
-/* Post-import orchestrator: query the connection, and if it needs a username,
- * prompt for one and persist it.  Fire-and-forget. */
-void enm_vpn_username_maybe_prompt(const char *conn_name);
+/* Post-import orchestrator: query the connection (by UUID), and if it needs a
+ * username, prompt for one and persist it.  svc_short is the VPN service short
+ * name ("openvpn", "vpnc", ...) from the import type.  Fire-and-forget. */
+void enm_vpn_username_maybe_prompt(const char *conn_uuid, const char *svc_short);
 
 #endif

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to