implement libwhich for Windows

因為windows沒有類似unix的which命令

  • 現在實現盡量跨平臺,且stb 風格的libwhich
// which.h
#ifndef LIBWHICH_H
#define LIBWHICH_H#ifdef __cplusplus
extern "C" {
#endif/** 查找可執行文件在系統中的路徑* 參數:*   filename - 要查找的可執行文件名*   buffer   - 用于存儲結果的緩沖區*   bufsize  - 緩沖區大小* 返回值:*   成功返回指向buffer的指針,失敗返回NULL*/
char* libwhich(const char* filename, char* buffer, int bufsize);#ifdef __cplusplus
}
#endif#endif // LIBWHICH_H#ifdef LIBWHICH_IMPLEMENTATION#include <stdlib.h>
#include <string.h>
#include <stdio.h>#ifdef _WIN32
#include <windows.h>
#include <io.h>
#define access _access
#define F_OK 0
#else
#include <unistd.h>
#include <sys/stat.h>
#endif// 輔助函數:檢查文件是否存在且可執行
static int is_executable(const char* path) {
#ifdef _WIN32// Windows系統檢查文件是否存在return access(path, F_OK) == 0;
#else// Unix-like系統檢查文件是否存在且可執行struct stat st;if (stat(path, &st) != 0)return 0;return (st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH);
#endif
}// 輔助函數:獲取路徑分隔符(PATH環境變量中分隔目錄的符號)
static char get_path_separator() {
#ifdef _WIN32return ';';
#elsereturn ':';
#endif
}// 輔助函數:獲取目錄分隔符(路徑中分隔目錄的符號)
static char get_dir_separator() {
#ifdef _WIN32return '\\';
#elsereturn '/';
#endif
}// 檢查文件名是否包含擴展名
static int has_extension(const char* filename) {const char* dot = strrchr(filename, '.');return dot != NULL && dot != filename && *(dot + 1) != '\0';
}char* libwhich(const char* filename, char* buffer, int bufsize) {if (!filename || !buffer || bufsize <= 0)return NULL;// 獲取PATH環境變量const char* path_env = getenv("PATH");if (!path_env)return NULL;// 復制PATH以便處理char* path = strdup(path_env);if (!path)return NULL;char* result = NULL;char sep[2] = {get_path_separator(), '\0'};char dir_sep = get_dir_separator();// 拆分PATH中的各個目錄char* dir = strtok(path, sep);while (dir != NULL) {size_t dir_len = strlen(dir);size_t file_len = strlen(filename);int need_sep = (dir_len > 0 && dir[dir_len - 1] != dir_sep) ? 1 : 0;// 檢查緩沖區是否足夠if (dir_len + need_sep + file_len + 1 > (size_t)bufsize) {dir = strtok(NULL, sep);continue;}// 構建完整路徑strcpy(buffer, dir);if (need_sep) {buffer[dir_len] = dir_sep;strcpy(buffer + dir_len + 1, filename);} else {strcpy(buffer + dir_len, filename);}// 檢查文件是否存在且可執行if (is_executable(buffer)) {result = buffer;break;}#ifdef _WIN32// Windows系統需要檢查常見的可執行文件擴展名if (!has_extension(filename)) {const char* exts[] = {".exe", ".com", ".bat", ".cmd", ".ps1", NULL};for (int i = 0; exts[i] != NULL; i++) {size_t ext_len = strlen(exts[i]);if (dir_len + need_sep + file_len + ext_len + 1 > (size_t)bufsize)continue;// 構建帶擴展名的路徑strcpy(buffer, dir);if (need_sep) {buffer[dir_len] = dir_sep;strcpy(buffer + dir_len + 1, filename);} else {strcpy(buffer + dir_len, filename);}strcat(buffer, exts[i]);if (is_executable(buffer)) {result = buffer;goto cleanup; // 找到后跳出所有循環}}}
#endifdir = strtok(NULL, sep);}cleanup:free(path);return result;
}#endif // LIBWHICH_IMPLEMENTATION// 示例主程序,定義LIBWHICH_MAIN可編譯為獨立工具
#ifdef LIBWHICH_MAIN
#include <stdio.h>int main(int argc, char* argv[]) {if (argc != 2) {fprintf(stderr, "用法: %s <命令名>\n", argv[0]);return 1;}char buffer[1024];char* path = libwhich(argv[1], buffer, sizeof(buffer));if (path) {printf("%s\n", path);return 0;} else {fprintf(stderr, "%s: 未找到命令\n", argv[1]);return 1;}
}
#endif

build as program (view .h file as .c file)

> gcc -x c which.h -DLIBWHICH_MAIN -DLIBWHICH_IMPLEMENTATION> cl /DLIBWHICH_IMPLEMENTATION /DLIBWHICH_MAIN /Tcwhich.h /Fe:which.exe

build as lib (msvc for example)

> cl /DLIBWHICH_IMPLEMENTATION /Tcwhich.h /Fo:libwhich.obj> lib libwhich.obj /OUT:libwhich.lib

as lib usage

// probe.c#define LIBWHICH_IMPLEMENTATION
#include "which.h"
#include <stdio.h>int main() {char buffer[1024];char* path = libwhich("python", buffer, sizeof(buffer));if (path) {printf("找到python: %s\n", path);} else {printf("未找到python\n");}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/93511.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/93511.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/93511.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

記與客戶端的一次“無謂之爭”

一、沖突今天&#xff0c;流程收尾時&#xff0c;客戶端為了統計時延&#xff0c;連發兩個接口&#xff1a;一個報開始時間&#xff0c;一個報結束時間。我因性能考慮&#xff0c;說&#xff1a;“明明一個接口能搞定&#xff01;”客戶端負責人說&#xff1a;“發送兩次更合理…

Java Condition 對象 wait 方法使用與修復方案

在 Java 中&#xff0c;java.util.concurrent.locks.Condition 接口提供了類似監視器的方法&#xff08;await(), signal(), signalAll()&#xff09;來實現線程間的協調。正確使用 Condition 對象需要遵循特定模式以避免常見問題。常見問題及修復方案1. 虛假喚醒問題問題&…

??金倉數據庫KingbaseES V9R1C10安裝教程 - Windows版詳細指南?

文章目錄一、前言二、軟件下載2.1 下載安裝包2.2 下載授權文件三. 安裝KingbaseES數據庫3.1 解壓安裝包3.2 運行安裝程序3.3 安裝步驟詳解步驟1&#xff1a;歡迎界面步驟2&#xff1a;許可協議步驟3&#xff1a;添加授權文件步驟4&#xff1a;選擇安裝路徑步驟5&#xff1a;選擇…

論文推薦|遷移學習+多模態特征融合

來gongzhonghao【圖靈學術計算機論文輔導】&#xff0c;快速拿捏更多計算機SCI/CCF發文資訊&#xff5e;在Cvpr、NeurIPS、AAAI等頂會中&#xff0c;遷移學習多模態特征融合正以“降成本、提性能、省標注”的絕對優勢成為最熱賽道。面對超大模型全量微調天價算力、異構模態對齊…

接口芯片斷電高阻態特性研究與應用分析

摘要&#xff1a; 本文以國科安芯推出的ASM1042 系列通訊接口芯片為例&#xff0c;深入探討接口芯片斷電高阻態特性&#xff0c;涵蓋其定義、原理、應用及設計注意事項。通過對相關技術資料的梳理與分析&#xff0c;結合具體芯片實例&#xff0c;闡述高阻態在電路穩定性、設備兼…

數據結構初階(17)排序算法——非比較排序(計數排序·動圖演示)、排序算法總結

2.0 十大排序算法2.5 非比較排序 之前學習的排序算法都是比較排序——借助比較大小&#xff0c;來實現排序。非比較就是不借助比較大小&#xff0c;來實現排序。——小眾的、局限的非比較排序大致有這些&#xff1a;計數排序、桶排序、基數排序。桶排序、基數排序在實踐中意義不…

VisualStudio2022調試Unity C#代碼步驟

一.VS安裝Unity開發組件按下圖所示安裝Unity開發組件二.附加Unity調試程序2.1 先將Unity進入Play模式2.2 VS選擇附加Unity調試程序菜單2.3 選擇附加的實例三.加入斷點測試Update方法中成功進入斷點

Zabbix【部署 01】Zabbix企業級分布式監控系統部署配置使用實例(在線安裝及問題處理)程序安裝+數據庫初始+前端配置+服務啟動+Web登錄

Zabbix使用 1.下載 2.安裝 2.1 程序安裝 2.2 數據庫初始化 2.3 前端配置 2.4 服務啟動 3.Web登錄 4.總結 安裝說明: 本次安裝為在線安裝,使用數據庫為PostgreSQL。 1.下載 由于是在線安裝,這次不涉及離線安裝包的下載,僅做參考用,點擊跳轉【下載頁面】,下載說明: 版本…

爬機 驗證服務器是否拒絕請求

當訪問XX網站時返回 418 狀態碼時&#xff0c;說明服務器識別到了爬蟲行為并拒絕了請求。這是網站的反爬機制在起作用&#xff0c;我們可以通過模擬瀏覽器行為來繞過基礎反爬。import requestsurl https://cn.bing.com/# 模擬瀏覽器的完整請求頭&#xff0c;包含更多瀏覽器標識…

GaussDB 數據庫架構師修煉(十三)安全管理(3)-數據庫審計

1 數據庫審計作用數據庫審計機制主要通過對SQL操作或其他操作記錄審計日志的方式 &#xff0c;增強數據庫系統對非法操作的追溯及舉證能力 。高斯數據庫提供兩種審計特性 &#xff1a;傳統審計 &#xff0c;統一審計。2 傳統審計傳統審計通過GUC參數配置需要對數據庫的哪些操作…

C語言(11)—— 數組(超絕詳細總結)

Hi&#xff01;冒險者&#x1f60e;&#xff0c;歡迎闖入 C 語言的奇幻異世界&#x1f30c;&#xff01; 我是 ankleless&#x1f9d1;?&#x1f4bb;&#xff0c;和你一樣的闖蕩者&#xff5e; 這是我的冒險筆記打怪升級之路——C語言之路&#x1f4d6;&#xff0c;里面有踩過…

【AI生成+補充】高頻 hql的面試問題 以及 具體sql

以下是高頻HQL面試題及對應SQL示例&#xff0c;涵蓋核心語法、優化技巧和典型場景&#xff0c;可直接用于面試準備&#xff1a; 一、基礎操作與DDL 1. 創建分區表 & 動態插入分區 sql -- 創建外部分區表&#xff08;按日期分區&#xff09; CREATE EXTERNAL TABLE logs…

開源 Arkts 鴻蒙應用 開發(十七)通訊--http多文件下載

文章的目的為了記錄使用Arkts 進行Harmony app 開發學習的經歷。本職為嵌入式軟件開發&#xff0c;公司安排開發app&#xff0c;臨時學習&#xff0c;完成app的開發。開發流程和要點有些記憶模糊&#xff0c;趕緊記錄&#xff0c;防止忘記。 相關鏈接&#xff1a; 開源 Arkts …

Cloudflare Tunnel 使用SAAS回源加速配置教程

在使用 Cloudflare Tunnel 時,通過“主域名+加速域名”的聯動配置,既能隱藏內網 IP,又能優化訪問速度。本文以實際部署場景為例(主域名 zhuyuming.dpdns.org、加速域名 jiasu.dpdns.org),帶你一步步完成內網服務穿透(以 192.168.1.6:5555 網頁服務為例),實操性強,可直…

C++實戰

Ref deepwiki vuecruddllamma.cpp 目標 計劃實現一個C項目&#xff0c;前端用vue&#xff0c;后端用C和llama.cpp。實現可以進行邏輯功能和AI推理。

dify 調用本地的 stable diffusion api生成圖片的工作流搭建

Dify調用本地Stable Diffusion API的工作流搭建指南 核心架構 #mermaid-svg-ce029i4XFKrDzRgU {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ce029i4XFKrDzRgU .error-icon{fill:#552222;}#mermaid-svg-ce029i4XFK…

【Web后端】Django、flask及其場景——以構建系統原型為例

一、Django 和 Flask 簡介 Django 是一個高級 Python Web 框架&#xff0c;提供了完整的“開箱即用”功能&#xff0c;包括 ORM、認證、管理后臺等&#xff0c;便于快速開發安全且可維護的網站。Flask 是一個輕量級 Python Web 框架&#xff0c;核心功能比較簡單&#xff0c;但…

飛算JavaAI:從智能調度到出行服務的全鏈路技術升級

免責聲明&#xff1a;此文章所有內容都是實驗測試數據 目錄一、智慧交通核心場景的技術突破1.1 交通態勢感知與智能預警系統1.2 公共交通智能調度系統1.3 一體化出行服務系統二、智慧交通系統效能升級實踐2.1 交通數據中臺構建結語&#xff1a;重新定義智慧交通技術邊界一、智慧…

vscode的wsl環境,ESP32驅動0.96寸oled屏幕

注意大小寫&#xff0c;wsl&#xff08;也就是linux環境&#xff09;嚴格區分大小寫。有幫助記得訂閱專欄點贊&#xff0c;當前不定期持續更新。 一、文件夾格式&#xff1a; project/ # 項目根目錄 ├─ main/ # 主程序文件夾 │ ├─ mai…

CodeBuddy AI Coding 企業場景落地實踐與思考

&#x1f449;目錄1 引言2 診斷團隊研發流程3 選擇合適的 AI CODING 工具4 團隊 AI 研發流程落地實踐5 全面 CodeBuddy &#xff0c;深入 CodeBuddy6 誠邀共建在 AI 浪潮席卷全球的今天&#xff0c;AI CODING 已經不是企業研發團隊的可選項&#xff0c;而是必選項。如果你是企業…