因为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;而是必选项。如果你是企业…