Chinaunix首页 | 论坛 | 博客
  • 博客访问: 929081
  • 博文数量: 177
  • 博客积分: 8613
  • 博客等级: 中将
  • 技术积分: 2835
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-12 04:16
文章分类
文章存档

2012年(12)

2011年(24)

2010年(24)

2009年(75)

2008年(42)

我的朋友

分类: C/C++

2009-11-02 22:41:52

     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) |
给主人留下些什么吧!~~