检查程序是否安装在C中

时间:2016-12-19 20:32:43

标签: c

我想找到一种方法来确定是否使用C gnu11标准安装了一个程序,例如,如果使用C中的system函数执行命令'Rscript'将会工作吗? / p>

我不是训练的prorgrammer,所以我不确定我是否使用了正确的搜索词。

我希望C等价于

con@con-Inspiron-3521:~/Scripts$ which Rscript 
/usr/bin/Rscript

我怎么能在C中做到这一点?

3 个答案:

答案 0 :(得分:5)

通过类似的工作,您只需解析PATH变量并检查给定文件是否存在且是否可执行:

#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

bool can_run_command(const char *cmd) {
    if(strchr(cmd, '/')) {
        // if cmd includes a slash, no path search must be performed,
        // go straight to checking if it's executable
        return access(cmd, X_OK)==0;
    }
    const char *path = getenv("PATH");
    if(!path) return false; // something is horribly wrong...
    // we are sure we won't need a buffer any longer
    char *buf = malloc(strlen(path)+strlen(cmd)+3);
    if(!buf) return false; // actually useless, see comment
    // loop as long as we have stuff to examine in path
    for(; *path; ++path) {
        // start from the beginning of the buffer
        char *p = buf;
        // copy in buf the current path element
        for(; *path && *path!=':'; ++path,++p) {
            *p = *path;
        }
        // empty path entries are treated like "."
        if(p==buf) *p++='.';
        // slash and command name
        if(p[-1]!='/') *p++='/';
        strcpy(p, cmd);
        // check if we can execute it
        if(access(buf, X_OK)==0) {
            free(buf);
            return true;
        }
        // quit at last cycle
        if(!*path) break;
    }
    // not found
    free(buf);
    return false;
}

答案 1 :(得分:1)

程序可能会在PATH环境变量中指定的任何目录中搜索该文件。

有很多方法可以做到这一点,这就是一种方法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stddef.h>

#include <sys/stat.h>

int
main(int argc, char *argv[])
{
    const char *head;
    const char *command;
    size_t length;

    if (argc < 2) {
        fprintf(stderr, "insufficient number of arguments\n");
        return -1;
    }

    command = argv[1];
    length = strlen(command);
    // Get the PATH environment variable
    head = getenv("PATH");
    if (head == NULL) {
        fprintf(stderr, "the PATH variable was not set, what?\n");
        return -1;
    }
    // Find the first separator
    while (*head != '\0') {
        struct stat st;
        ptrdiff_t dirlen;        
        const char *tail;
        char *path;
        // Check for the next ':' if it's not found
        // then get a pointer to the null terminator
        tail = strchr(head, ':');
        if (tail == NULL)
            tail = strchr(head, '\0');
        // Get the length of the string between the head
        // and the ':'
        dirlen = tail - head;
        // Allocate space for the new string
        path = malloc(length + dirlen + 2);
        if (path == NULL)
            return -1;
        // Copy the directory path into the newly
        // allocated space
        memcpy(path, head, dirlen);
        // Append the directory separator
        path[dirlen] = '/';
        // Copy the name of the command            
        memcpy(path + dirlen + 1, command, length);
        // `null' terminate please
        path[dirlen + length + 1] = '\0';
        // Check if the file exists and whether it's
        // executable
        if ((stat(path, &st) != -1) && (S_ISREG(st.st_mode) != 0)) {
            if ((st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) {                
                fprintf(stdout, "found `%s' but it's not executable\n", path);
            } else {
                fprintf(stdout, "found at: %s\n", path);
            }                
        }
        // Don't forget to free!
        free(path);
        // Point to the next directory
        head = tail + 1;
    }
    return 0;
}

一般来说算法相同

  1. 获取PATH环境变量,该变量由一系列由:字符分隔的目录路径组成。
  2. 通过迭代获取此序列中的每个目录路径,这是您可以通过多种方式完成的。
  3. 检查是否,

    • 文件存在。
    • 具有来电者的执行权限。

答案 2 :(得分:-1)

根据@Paul_R的回答,我想出了以下内容:

#include <stdio.h>
#include <linux/limits.h>//PATH_MAX definition
#include <string.h>//strlen
#include <stdbool.h>

const bool is_program_installed( const char *restrict COMMAND) {

    FILE *restrict fp;
    fp = popen(COMMAND, "r");
    if (fp == NULL) {
        pclose(fp);
        return false;
    }
    char path[PATH_MAX];
    bool return_value = false;
    while (fgets(path, PATH_MAX, fp) != NULL) {
         if (strlen(path) > 0) {
            return_value = true;
            break;
         }
    }
    pclose(fp);
    return return_value;
}

int main() {

    printf("ls  %s\n", is_program_installed("ls") ? "true" : "false");
    printf("not_program %s\n", is_program_installed("not_program") ? "true" : "false");
    return 0;
}

如果没有打印“sh:1:not_program:not found”,工作会很好,但这已经足够了。