chroot这个系统调用还是相当有用处的,如apache等软件的根目录,应当都是通过这种方式来实现的,具体使用一下可以发现:
[root@bjxdurs235 20091101]# chroot /tmp/
chroot: cannot run command `/bin/bash': No such file or directory
报错的原因是/tmp/下面没有/bin/sh这个文件,这个文件是默认要执行的程序。
下面是代码分析:
/* chroot -- run command or shell with special root directory
在特别指定的根目录运行命令或shell
Copyright (C) 95, 96, 1997, 1999-2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Written by Roland McGrath. */
//包含进来4个标准的头文件
#include
#include
#include
#include
//包含进来4个本地的头文件
#include "system.h"
#include "error.h"
#include "long-options.h"
#include "quote.h"
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "chroot"//定义宏PROGRAM_NAME,其值是一个字符串,意义是程序名称
#define AUTHORS "Roland McGrath"//定义宏AUTHORS,其值也是一个字符串,意思是作者
/* The name this program was run with, for error messages. */
char *program_name;//声明一个字符指针变量
void
usage (int status)//帮助函数
{
if (status != EXIT_SUCCESS)//如果形参status的值不等于EXIT_SUCCESS,则向标准错误输出一个串,提示用户使用帮助
fprintf (stderr, _("Try `%s --help' for more information.\n"),
program_name);
else//否则,如果status等于EXIT_SUCCESS,则打印下面的这些内容
{
printf (_("\
Usage: %s NEWROOT [COMMAND...]\n\
or: %s OPTION\n\
"), program_name, program_name);
fputs (_("\
Run COMMAND with root directory set to NEWROOT.\n\
\n\
"), stdout);//这句话说明了程序的用途,将新的目录设置成根目录,然后运行命令
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
fputs (_("\
\n\
If no command is given, run ``${SHELL} -i'' (default: /bin/sh).\n\
"), stdout);//如果没有指定命令,则默认运行/bin/sh
printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
}
exit (status);
}
int
main (int argc, char **argv)//标准的main函数
{
initialize_main (&argc, &argv);//初始化命令行选项
program_name = argv[0];//将程序名字符串的地址赋值给全局字符指针变量program_name
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
initialize_exit_failure (EXIT_FAIL);
/*
这个函数的原型定义在system.h里面,代码段如下:
initialize_exit_failure (int status)
{
if (status != EXIT_FAILURE)
exit_failure = status;
}
如果形参不等于EXIT_FAILURE,则设置exit_failure变量的值为形参的值
*/
atexit (close_stdout);//登记出口函数
parse_long_options (argc, argv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
usage, AUTHORS, (char const *) NULL);//解析命令行参数
if (getopt_long (argc, argv, "+", NULL, NULL) != -1)
usage (EXIT_FAIL);//如果调用getopt_long函数解析命令行选项的结果失败,则调用usage函数
if (argc <= optind)//如果调用getopt_long函数后,argc的值小于或者等于optind的值,则调用error函数,并调用usage函数
{
error (0, 0, _("missing operand"));
usage (EXIT_FAIL);
}
if (chroot (argv[optind]) != 0)//这里调用了系统调用chroot,将根目录设置为命令行参数里的最后一个字符串指定的字符串
error (EXIT_FAIL, errno, _("cannot change root directory to %s"), argv[1]);//如果系统调用返回失败,则调用error函数
if (chdir ("/"))//调用chdir系统调用,将当前目录设置为根目录
error (EXIT_FAIL, errno, _("cannot chdir to root directory"));//如果系统调用失败,则调用error函数,程序继续执行
if (argc == optind + 1)//如果argc的值等于optind+1的值
{
/* No command. Run an interactive shell. */
char *shell = getenv ("SHELL");//初始化一个字符指针变量shell,其值是通过库函数getenv得到的环境变量里的SHELL所等于的那个值
if (shell == NULL)//如果没有得到环境变量里的SHELL
shell = "/bin/sh";//则将字符指针shell的值指向字符串/bin/sh
argv[0] = shell;//下面这3句话,分别设置了命令行的3个参数值
argv[1] = "-i";
argv[2] = NULL;
}
else//否则,如果argc的值不等于optind+1的值,则改变argv的值
{
/* The following arguments give the command. */
argv += optind + 1;
}
/* Execute the given command. */
execvp (argv[0], argv);//调用execvp库函数,来运行给定的命令
{
int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);//根据errno的值,得到exit_status的值
error (0, errno, _("cannot run command %s"), quote (argv[0]));
exit (exit_status);//退出状态为上面得到的exit_status的值
}
}
这个程序使用了2个系统调用(chroot、chdir)、2个库函数(getenv、execvp),内容还是挺丰富的。
阅读(1550) | 评论(0) | 转发(0) |