@@ -995,4 +995,80 @@ int accounts_health_check(const gitswitch_ctx_t *ctx) { |
| 995 | 995 | printf("[ERROR]: Some accounts have issues\n\n"); |
| 996 | 996 | return -1; |
| 997 | 997 | } |
| 998 | +} |
| 999 | + |
| 1000 | +/* Detect current account from SSH socket symlink */ |
| 1001 | +int accounts_detect_current(gitswitch_ctx_t *ctx) { |
| 1002 | + char symlink_path[MAX_PATH_LEN]; |
| 1003 | + char target_path[MAX_PATH_LEN]; |
| 1004 | + ssize_t len; |
| 1005 | + const char *runtime_dir; |
| 1006 | + const char *account_name_start; |
| 1007 | + const char *account_name_end; |
| 1008 | + char account_name[MAX_NAME_LEN]; |
| 1009 | + size_t name_len; |
| 1010 | + |
| 1011 | + if (!ctx) { |
| 1012 | + return -1; |
| 1013 | + } |
| 1014 | + |
| 1015 | + /* Already have a current account set */ |
| 1016 | + if (ctx->current_account) { |
| 1017 | + return 0; |
| 1018 | + } |
| 1019 | + |
| 1020 | + /* Build path to symlink */ |
| 1021 | + runtime_dir = getenv("XDG_RUNTIME_DIR"); |
| 1022 | + if (!runtime_dir) { |
| 1023 | + log_debug("XDG_RUNTIME_DIR not set, cannot detect current account"); |
| 1024 | + return -1; |
| 1025 | + } |
| 1026 | + |
| 1027 | + if ((size_t)snprintf(symlink_path, sizeof(symlink_path), |
| 1028 | + "%s/gitswitch-ssh/current.sock", runtime_dir) >= sizeof(symlink_path)) { |
| 1029 | + return -1; |
| 1030 | + } |
| 1031 | + |
| 1032 | + /* Read symlink target */ |
| 1033 | + len = readlink(symlink_path, target_path, sizeof(target_path) - 1); |
| 1034 | + if (len < 0) { |
| 1035 | + log_debug("No current.sock symlink found, no active account"); |
| 1036 | + return -1; |
| 1037 | + } |
| 1038 | + target_path[len] = '\0'; |
| 1039 | + |
| 1040 | + /* Parse account name from target: ssh-agent.<name>.sock */ |
| 1041 | + account_name_start = strstr(target_path, "ssh-agent."); |
| 1042 | + if (!account_name_start) { |
| 1043 | + log_debug("Symlink target doesn't match expected format: %s", target_path); |
| 1044 | + return -1; |
| 1045 | + } |
| 1046 | + account_name_start += strlen("ssh-agent."); |
| 1047 | + |
| 1048 | + account_name_end = strstr(account_name_start, ".sock"); |
| 1049 | + if (!account_name_end) { |
| 1050 | + log_debug("Symlink target missing .sock suffix: %s", target_path); |
| 1051 | + return -1; |
| 1052 | + } |
| 1053 | + |
| 1054 | + name_len = (size_t)(account_name_end - account_name_start); |
| 1055 | + if (name_len == 0 || name_len >= sizeof(account_name)) { |
| 1056 | + log_debug("Invalid account name length in symlink target"); |
| 1057 | + return -1; |
| 1058 | + } |
| 1059 | + |
| 1060 | + memcpy(account_name, account_name_start, name_len); |
| 1061 | + account_name[name_len] = '\0'; |
| 1062 | + |
| 1063 | + /* Find matching account */ |
| 1064 | + for (size_t i = 0; i < ctx->account_count; i++) { |
| 1065 | + if (strcmp(ctx->accounts[i].name, account_name) == 0) { |
| 1066 | + ctx->current_account = &ctx->accounts[i]; |
| 1067 | + log_debug("Detected current account from symlink: %s", account_name); |
| 1068 | + return 0; |
| 1069 | + } |
| 1070 | + } |
| 1071 | + |
| 1072 | + log_debug("No matching account found for name: %s", account_name); |
| 1073 | + return -1; |
| 998 | 1074 | } |