我想找到一种方法来确定是否使用C gnu11标准安装了一个程序,例如,如果使用C中的system
函数执行命令'Rscript'将会工作吗? / p>
我不是训练的prorgrammer,所以我不确定我是否使用了正确的搜索词。
我希望C等价于
con@con-Inspiron-3521:~/Scripts$ which Rscript
/usr/bin/Rscript
我怎么能在C中做到这一点?
答案 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;
}
一般来说算法相同
PATH
环境变量,该变量由一系列由:
字符分隔的目录路径组成。检查是否,
答案 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”,工作会很好,但这已经足够了。