0

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

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

我在 Arch linux 下工作。

4

1 回答 1

1

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

如果您不想 trust 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();
    }
}
于 2013-09-04T22:53:23.327 回答