我正在编写一个C程序,我想打开一个带有$EDITOR
变量的文件来对其进行更改。
假设我已经检查了$EDITOR
是否未设置且缺少的部分是打开要编辑的文件,execl()
是最佳选择还是我应该使用不同的功能?
我在Arch linux下工作。
答案 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();
}
}