【问题标题】:Open a file for edit with $EDITOR variable from a C program使用 C 程序中的 $EDITOR 变量打开文件进行编辑
【发布时间】:2013-09-04 22:33:47
【问题描述】:

我正在编写一个 C 程序,我想打开一个带有 $EDITOR 变量的文件以对其进行更改。

假设我已经检查了$EDITOR 是否未设置并且缺少的部分是打开文件进行编辑,execl() 是最佳选择还是应该使用不同的功能?

我在 Arch linux 下工作。

【问题讨论】:

    标签: c file-io io


    【解决方案1】:

    如果你有理由确定你在一个单线程程序中,你有标准输入和标准输出(可能还有标准错误)到一个终端,并且你不会被信号处理打扰system()强加给你,你可以使用system()通过shell执行命令。

    如果您不想信任system(),那么exec*() 系列函数之一(加上fork())将满足您的需求。您仍然需要合理地确定标准 I/O 通道——一些编辑器对随机文件或管道输入反应不佳。您可以选择要使用的信号处理方式以及安装方式。您可以处理任何线程安全问题。工作量适中。

    您可能需要仔细考虑是否将“真实”文件提供给用户进行编辑或提供副本。您的代码应该可以识别编辑器是否成功退出(如果没有成功退出,则应该忽略输出文件)。您可能还想检查文件的新版本的大小是否合理(例如,不是零字节 - 但这可能无关紧要;这取决于上下文)。如果正在编辑的文件是一个珍贵的配置文件,你会担心这个;如果是重新执行之前的一些命令(一种历史机制),你就不用担心其中的一些细节了。


    这是我的一个程序中的历史“编辑”命令。它允许用户指定要复制到文件中的命令范围,然后对其进行编辑,然后执行结果(可能为空)。它是逐字代码。大多数函数调用都是针对特定于程序的函数,但大多数名称应该是可解释的(我认为)。 ctxt_*() 系列函数处理“上下文”,即程序的当前设置。它适用于比您需要的更多的环境变量。 sql_file() 函数在当前上下文中执行来自输入文件的命令——这段代码创建了一个新的上下文来运行命令。

    /* Edit history command(s) */
    static void do_edit(char *s)
    {
        FILE           *fp;
        long            c1;
        long            c2;
        char            tmpfname[BUFSIZ];
        char            sys[BUFSIZ];
        const char     *editor;
    
        if (ctxt_gethistory() != OP_ON)
        {
            cmd_warning(E_HISTORYOFF, "");
            return;
        }
    
        s = skipblanks(s);
        c1 = c2 = 0;
        if (sscanf(s, "%ld%ld", &c1, &c2) != 2)
            c2 = c1;
    
        if ((fp = fopen_namedtmpfile(tmpfname, sizeof(tmpfname))) == 0)
        {
            cmd_warning(E_FAILCREATETMPFILE, "");
            return;
        }
    
        hist_output(fp, c1, c2, H_COMMAND);
        fclose(fp);
    
        if ((editor = getenv("DBEDIT")) == NIL(char *) &&
            (editor = getenv("VISUAL")) == NIL(char *) &&
            (editor = getenv("EDITOR")) == NIL(char *))
            editor = DEF_EDITOR;
        esnprintf(sys, sizeof(sys), "%s %s", editor, tmpfname);
        system(sys);
    
        fp = fopen(tmpfname, "r");
        unlink(tmpfname);
        if (fp == 0)
        {
            cmd_warning(E_FAILREOPENTMPFILE, tmpfname);
        }
        else
        {
            /* Copy file to history log */
            if ((c1 = hist_input(fp)) > 0)
                cmd_set_promptnum(c1);
            fseek(fp, 0L, SEEK_SET);
            ctxt_newcontext();
            ctxt_newinput(fp, "<<temp>>");
            ctxt_sethistory(op_off);
            sql_file();
            ctxt_endcontext();
        }
    }
    

    【讨论】:

    • 由于我编写的程序主要是为使用终端的人编写的,我认为如果它适用于 vi(m) 和 mg 现在就可以了。是的,我认为我应该在打开文件进行编辑之前复制文件。我将阅读 system 和 exec* 手册页,看看什么最适合我。顺便说一句,它只是一个备忘单处理程序,不会编辑任何配置文件。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    相关资源
    最近更新 更多