Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 了解xdg开放式数据库的可用性_C_Linux_Availability_Xdgutils - Fatal编程技术网

C 了解xdg开放式数据库的可用性

C 了解xdg开放式数据库的可用性,c,linux,availability,xdgutils,C,Linux,Availability,Xdgutils,我想打开一个图像,在Windows中我会: #include <windows.h> .. ShellExecute(NULL, "open", "https://gsamaras.files.wordpress.com/2018/11/chronosgod.png", NULL, NULL, SW_SHOWNORMAL); 在我的Ubuntu中,它是有效的。但是,在Wandbox或任何其他联机编译器中运行时,我很可能会遇到错误: sh:1:xdg打开:未找到 尽管这些在线编译器似

我想打开一个图像,在Windows中我会:

#include <windows.h>
..
ShellExecute(NULL, "open", "https://gsamaras.files.wordpress.com/2018/11/chronosgod.png", NULL, NULL, SW_SHOWNORMAL);
在我的Ubuntu中,它是有效的。但是,在Wandbox或任何其他联机编译器中运行时,我很可能会遇到错误:

sh:1:xdg打开:未找到

尽管这些在线编译器似乎生活在Linux中。我不希望在线编译器为我打开浏览器,但我希望代码运行时不会出错。啊,忘了个人笔记本电脑,限制我的机器

因为我没有其他的Linux机器可以检查,所以我的问题是:我能期望这段代码能在大多数主要的Linux发行版中工作吗

也许它在在线编译器上失败的事实是误导

附:这是我在上的帖子,所以不用担心安全问题。

xdg open是。它们几乎总是与任何Linux发行版的GUI桌面一起安装

Linux发行版可以在没有任何图形用户界面的情况下安装在服务器上,并且很可能在服务器上没有xdg open

您可以(并且应该)使用fork+exec代替system,如果exec失败,那么xdg open将无法执行


在线编译器很可能没有安装任何桌面GUI,因此缺少该实用程序。

虽然Antti Haapala已经完全解决了这个问题,但我认为有关该方法的一些评论,以及使安全使用变得微不足道的示例函数可能会有用

xdg open是freedesktop.org中桌面集成实用程序的一部分,是的一部分。人们可以期望它们可以在任何运行桌面环境的计算机上使用。这包括GNOME、KDE和Xfce

简单地说,当桌面环境正在使用时,无论用户喜欢什么应用程序,这都是打开资源(无论是文件还是URL)的推荐方法

如果没有正在使用的桌面环境,那么也没有理由期望xdg open可用

对于Linux,我建议使用一个专用的函数,也许可以遵循以下几点。首先,有两个内部助手函数:

#define  _POSIX_C_SOURCE  200809L
#define  _GNU_SOURCE
//
// SPDX-License-Identifier: CC0-1.0
//
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

/* Number of bits in an unsigned long. */
#define  ULONG_BITS  (CHAR_BIT * sizeof (unsigned long))

/* Helper function to open /dev/null to a specific descriptor.
*/
static inline int devnullfd(const int fd)
{
    int  tempfd;

    /* Sanity check. */
    if (fd == -1)
        return errno = EINVAL;

    do {
        tempfd = open("/dev/null", O_RDWR | O_NOCTTY);
    } while (tempfd == -1 && errno == EINTR);
    if (tempfd == -1)
        return errno;

    if (tempfd != fd) {
        if (dup2(tempfd, fd) == -1) {
            const int  saved_errno = errno;
            close(tempfd);
            return errno = saved_errno;
        }
        if (close(tempfd) == -1)
            return errno;
    }

    return 0;
}

/* Helper function to close all except small descriptors
   specified in the mask. For obvious reasons, this is not
   thread safe, and is only intended to be used in recently
   forked child processes. */
static void closeall(const unsigned long  mask)
{
    DIR           *dir;
    struct dirent *ent;
    int            dfd;

    dir = opendir("/proc/self/fd/");
    if (!dir) {
        /* Cannot list open descriptors.  Just try and close all. */
        const long  fd_max = sysconf(_SC_OPEN_MAX);
        long        fd;

        for (fd = 0; fd < ULONG_BITS; fd++)
            if (!(mask & (1uL << fd)))
                close(fd);

        for (fd = ULONG_BITS; fd <= fd_max; fd++)
            close(fd);

        return;
    }

    dfd = dirfd(dir);

    while ((ent = readdir(dir)))
        if (ent->d_name[0] >= '0' && ent->d_name[0] <= '9') {
            const char *p = &ent->d_name[1];
            int         fd = ent->d_name[0] - '0';

            while (*p >= '0' && *p <= '9')
                fd = (10 * fd) + *(p++) - '0';

            if (*p)
                continue;

            if (fd == dfd)
                continue;

            if (fd < ULONG_MAX && (mask & (1uL << fd)))
                continue;

            close(fd);
        }

    closedir(dir);
}
如前所述,它努力关闭所有打开的文件描述符,将标准流重定向到/dev/null,确保在setuid二进制文件中使用有效和真实的标识匹配,并使用子进程退出状态传递成功/失败

setresuid和setresgid调用仅在保存了用户和组ID的操作系统上可用。在其他情况下,请改用seteuiduid和setegid

此实现试图平衡用户可配置性和安全性。用户可以设置路径,以便执行他们喜爱的xdg open,但该函数会尝试确保没有敏感信息或权限泄漏到该进程

环境变量可以被过滤,但它们首先不应该包含敏感信息,我们也不知道桌面环境使用的是哪些。所以最好不要弄乱它们,以尽量减少用户的惊喜

作为最小测试干线,请尝试以下操作:

int main(int argc, char *argv[])
{
    int  arg, status;

    if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
        fprintf(stderr, "\n");
        fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
        fprintf(stderr, "       %s FILE-OR-URL ...\n", argv[0]);
        fprintf(stderr, "\n");
        fprintf(stderr, "This example program opens each specified file or URL\n");
        fprintf(stderr, "xdg-open(1), and outputs success or failure for each.\n");
        fprintf(stderr, "\n");
        return EXIT_SUCCESS;
    }

    status = EXIT_SUCCESS;

    for (arg = 1; arg < argc; arg++)
        if (xdg_open(argv[arg])) {
            printf("%s: %s.\n", argv[arg], strerror(errno));
            status = EXIT_FAILURE;
        } else
            printf("%s: Opened.\n", argv[arg]);

    return status;
}

正如SPDX许可证标识符所述,此示例代码在下获得许可。无论你想用什么方式,在任何代码中使用它。

你知道为什么在线编译器没有它,尽管他们的操作系统是Linux吗?谢谢你的回答和提示,这是正确的。@gsamaras因为他们没有安装任何桌面GUI:P为什么要安装。在没有xdg打开的情况下,可以尝试使用其他程序,但默认情况下很少安装这些程序。我对此不感兴趣,因为我想要的是在我的Chronos帖子中有代码,可以很容易地复制粘贴编译执行!如果你愿意,你也可以自己试试!无论如何,很高兴知道,因为未来的读者可能会感兴趣@gsamaras您希望xdg open在在线服务上做什么?在你的网络浏览器中打开一个窗口?啊,通常,当涉及到低级别C时,你知道很多!什么是POSIXy?我在网上搜索了一下,发现了几个含义。@gsamaras:我所说的POSIXy是指那些实现了大部分或全部IEEE标准1003.1的系统™, 也称为。至少包括Linux和BSD;我不确定其他人,因为我不是最新的。很多Unix都非常时髦,尽管您可能需要安装额外的库和实用程序。@gsamaras:我后来注意到我没有足够强调它只适用于桌面环境,在非DEs环境中不可用,并在第二节中添加了一条关于这一点的说明。我希望我没有误导任何人。。。
/* Launch the user-preferred application to open a file or URL.
   Returns 0 if success, an errno error code otherwise.
*/ 
int xdg_open(const char *file_or_url)
{
    pid_t  child, p;
    int    status;

    /* Sanity check. */
    if (!file_or_url || !*file_or_url)
        return errno = EINVAL;

    /* Fork the child process. */
    child = fork();
    if (child == -1)
        return errno;
    else
    if (!child) {
        /* Child process. */

        uid_t  uid = getuid();  /* Real, not effective, user. */
        gid_t  gid = getgid();  /* Real, not effective, group. */

        /* Close all open file descriptors. */
        closeall(0);

        /* Redirect standard streams, if possible. */
        devnullfd(STDIN_FILENO);
        devnullfd(STDOUT_FILENO);
        devnullfd(STDERR_FILENO);

        /* Drop elevated privileges, if any. */
        if (setresgid(gid, gid, gid) == -1 ||
            setresuid(uid, uid, uid) == -1)
            _Exit(98);

        /* Have the child process execute in a new process group. */
        setsid();

        /* Execute xdg-open. */
        execlp("xdg-open", "xdg-open", file_or_url, (char *)0);

        /* Failed. xdg-open uses 0-5, we return 99. */
        _Exit(99);
    }

    /* Reap the child. */
    do {
        status = 0;
        p = waitpid(child, &status, 0);
    } while (p == -1 && errno == EINTR);
    if (p == -1)
        return errno;

    if (!WIFEXITED(status)) {
        /* Killed by a signal. Best we can do is I/O error, I think. */
        return errno = EIO;
    }

    switch (WEXITSTATUS(status)) {
    case 0: /* No error. */
        return errno = 0; /* It is unusual, but robust to explicitly clear errno. */
    case 1: /* Error in command line syntax. */
        return errno = EINVAL;      /* Invalid argument */
    case 2: /* File does not exist. */
        return errno = ENOENT;      /* No such file or directory */
    case 3: /* A required tool could not be found. */
        return errno = ENOSYS;      /* Not implemented */
    case 4: /* Action failed. */
        return errno = EPROTO;      /* Protocol error */
    case 98: /* Identity shenanigans. */
        return errno = EACCES;      /* Permission denied */
    case 99: /* xdg-open does not exist. */
        return errno = ENOPKG;      /* Package not installed */
    default:
        /* None of the other values should occur. */
        return errno = ENOSYS;      /* Not implemented */
    }
}
int main(int argc, char *argv[])
{
    int  arg, status;

    if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
        fprintf(stderr, "\n");
        fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
        fprintf(stderr, "       %s FILE-OR-URL ...\n", argv[0]);
        fprintf(stderr, "\n");
        fprintf(stderr, "This example program opens each specified file or URL\n");
        fprintf(stderr, "xdg-open(1), and outputs success or failure for each.\n");
        fprintf(stderr, "\n");
        return EXIT_SUCCESS;
    }

    status = EXIT_SUCCESS;

    for (arg = 1; arg < argc; arg++)
        if (xdg_open(argv[arg])) {
            printf("%s: %s.\n", argv[arg], strerror(errno));
            status = EXIT_FAILURE;
        } else
            printf("%s: Opened.\n", argv[arg]);

    return status;
}