execl如何处理Linux中的“/bin/sh”?
How does execl deal with "/bin/sh" in Linux?
看了APUE 3rd, 8.13, system Function,看到一个没有signal handling.Code 的system function实现版本如下:
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>
int system(const char *cmdstring) /* version without signal handling */
{
pid_t pid;
int status;
if (cmdstring == NULL)
return(1); /* always a command processor with UNIX */
if ((pid = fork()) < 0) {
status = -1; /* probably out of processes */
} else if (pid == 0) { /* child */
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
_exit(127); /* execl error */
} else { /* parent */
while (waitpid(pid, &status, 0) < 0) {
if (errno != EINTR) {
status = -1; /* error other than EINTR from waitpid() */
break;
}
}
}
return(status);
}
测试该版本系统功能的代码如下:
int main(void)
{
int status;
if ((status = system("date")) < 0)
err_sys("system() error");
pr_exit(status);
if ((status = system("nosuchcommand")) < 0)
err_sys("system() error");
pr_exit(status);
if ((status = system("who; exit 44")) < 0)
err_sys("system() error");
pr_exit(status);
exit(0);
}
测试代码结果如图所示(看不懂就忽略结果中的中文):
我想知道如果将对 /bin/sh 无效的 "nosuchcommand" 提供给 /bin/sh,为什么会执行 return。在我看来,execl只是替换当前进程的代码,然后从入口点替换运行,即使"nosuchcommand"对/bin/sh无效,它与execl无关但是/bin/sh。那么,execl 是如何知道 "nosuchcommand" 对 /bin/sh 和 return 无效的呢? execl 是否通过在执行 /bin/sh 之前检查提供给 /bin/sh 的命令来区别对待 /bin/sh,以便它提前知道提供给 /bin/sh 的无效参数?我知道 execl 不会以不同的方式对待 /bin/sh,那么,execl 怎么知道 "nosuchcommand" 对 /bin/sh 和 return 无效?
sh -c nosuchcommand
本身 returns 127。它是其中之一 return codes with a special meaning。
所以我认为在这种情况下您没有看到 execl 实际返回。
它没有 "know"。它只是执行您告诉它的事情。 /bin/sh
然后报告找不到它,之后 /bin/sh
以非零退出代码退出,在本例中为 127
.
另请注意,您不能完全依赖它 returning 127
,因为它是 shell 特定的。某些 shell(包括某些操作系统上的 /bin/sh
)将 return 1
代替。
看了APUE 3rd, 8.13, system Function,看到一个没有signal handling.Code 的system function实现版本如下:
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>
int system(const char *cmdstring) /* version without signal handling */
{
pid_t pid;
int status;
if (cmdstring == NULL)
return(1); /* always a command processor with UNIX */
if ((pid = fork()) < 0) {
status = -1; /* probably out of processes */
} else if (pid == 0) { /* child */
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
_exit(127); /* execl error */
} else { /* parent */
while (waitpid(pid, &status, 0) < 0) {
if (errno != EINTR) {
status = -1; /* error other than EINTR from waitpid() */
break;
}
}
}
return(status);
}
测试该版本系统功能的代码如下:
int main(void)
{
int status;
if ((status = system("date")) < 0)
err_sys("system() error");
pr_exit(status);
if ((status = system("nosuchcommand")) < 0)
err_sys("system() error");
pr_exit(status);
if ((status = system("who; exit 44")) < 0)
err_sys("system() error");
pr_exit(status);
exit(0);
}
测试代码结果如图所示(看不懂就忽略结果中的中文):
sh -c nosuchcommand
本身 returns 127。它是其中之一 return codes with a special meaning。
所以我认为在这种情况下您没有看到 execl 实际返回。
它没有 "know"。它只是执行您告诉它的事情。 /bin/sh
然后报告找不到它,之后 /bin/sh
以非零退出代码退出,在本例中为 127
.
另请注意,您不能完全依赖它 returning 127
,因为它是 shell 特定的。某些 shell(包括某些操作系统上的 /bin/sh
)将 return 1
代替。