使用C程序中的$ EDITOR变量打开要编辑的文件

时间:2013-09-04 22:33:48

标签: c file-io io

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

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

我在Arch linux下工作。

1 个答案:

答案 0 :(得分:1)

如果您确信自己处于单线程程序中,那么您可以将标准输入和标准输出(也可能是标准错误)发送到终端,您不会对信号处理感到不安system()强加给你,你可以使用system()通过shell执行命令。

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

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


这是我的程序中的历史'编辑'命令。它允许用户指定要复制到文件中的一系列命令,然后对其进行编辑,然后执行结果(可能为空)。它是逐字的代码。大多数函数调用是针对特定于程序的函数,但大多数名称应该是可解释的(我认为)。 ctxt_*()函数系列处理'context',即程序的当前设置。它适用于比您需要的环境变量更多的环境变量。 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();
    }
}