【问题标题】:printing agruments using text interpreter and execl使用文本解释器和 execl 打印 agruments
【发布时间】:2014-05-10 14:38:29
【问题描述】:

我正在尝试使用执行文本解释器的 execl 函数打印命令行参数,但我无法打印第一个参数。

这是我的主程序

    #include<unistd.h>
    #include<stdio.h>
    #include<fcntl.h>
    #include<sys/types.h>
    #include<sys/stat.h>

   int main(int argc,char *argv[])
   {
      pid_t pid;
      if((pid=fork())<0)
          printf("error\n");
      else if(pid==0)
      if((execl("textinterpreter","this","is","usp","lab",(char*)0))<0)
            perror("error in execl\n");

      if(waitpid(pid,NULL,0) !=pid)
          printf("error1\n");
      system("ls > list");
      return 0;
    }  

这是我的文本解释器文件

      #!/home/chirag/echoarg1 my1

这是我的 echoarg1.c 文件

     #include<stdio.h>
     #include<unistd.h>
     #include<fcntl.h>
     #include<sys/types.h>
     #include<sys/stat.h>
    main(int argc,char *argv[])
    {
       int i;
       for(i=0;i<argc;i++)
           printf("argv[%d]=%s\n",i,argv[i]);
     }

我得到的输出是

        argv[0]=/home/chirag/echoarg1
        argv[1]=my1
        argv[2]=textinterpreter
        argv[3]=is
        argv[4]=usp
        argv[5]=lab

预期输出在哪里

        argv[0]=/home/chirag/echoarg1
        argv[1]=my1
        argv[2]=textinterpreter
        argv[3]=this
        argv[4]=is
        argv[5]=usp
        argv[6]=lab

谁能指出错误。

【问题讨论】:

  • 我本来希望 argv[2] 是 "this" 和 "textinterpreter" 已被跳过。 execp 的第一个参数是不应在 argv 中传递的 file-path。剩下的参数,直到 NULL 指针,被填充到 argv[0]...
  • 那么你能说出为什么会这样吗?
  • 正如我所说,我对 execp 的理解是第一个参数不会传递到新程序的 argv 中。这与您报告的第二个参数未传入的情况不符。您使用的是哪种 Linux/Unix?
  • #34~precise1-Ubuntu 3.11.0-20-generic
  • 看来 bash 解释器使用的是可执行路径,而不是传递的 arg0。

标签: c unix


【解决方案1】:

来自 execl 手册页:

int execl(const char *path, const char arg0, ... /, (char *)0 */);

这些函数的初始参数是文件的路径名 将被执行。

execl()、execlp() 中的 const char *arg0 和后续省略号, 和 execle() 函数可以被认为是 arg0, arg1, ..., argn。 它们一起描述了一个或多个指向空终止指针的列表 表示已执行程序可用的参数列表的字符串。按照惯例,第一个参数应该指向文件名 与正在执行的文件相关联。参数列表必须是 由 NULL 指针终止。


所以在你的行中:

  if((execl("textinterpreter","this","is","usp","lab",(char*)0))<0)

"textinterpreter" 是要执行的文件的路径,但 execl 期望下一个参数 arg0 来“指向与正在执行的文件关联的文件名”。

换句话说,它应该看起来更像:

  if((execl("textinterpreter","textinterpreter","this","is","usp","lab",(char*)0))<0)

通常执行的前两个 args 可能相同,但它允许您灵活地指定一个 arg 来查找要执行的文件,另一个参数作为 argv[0] 传递。


作为实验,尝试将您的execl 更改为直接调用echoarg1,如下所示:

if((execl("echoarg1","FAKEPATH","this","is","usp","lab",(char*)0))<0)

你应该看到如下输出:

argv[0]=FAKEPATH
argv[1]=this
argv[2]=is
argv[3]=usp
argv[4]=lab

在您的示例中,由于 bash 解释器如何处理您的“textinterpreter”脚本,它似乎显示“this”而不是“textinterpreter”。 bash 解释器的行为如下:

  • 采用 hash-bang 行并运行 /home/chirag/echoarg1
  • 通过argv[0]=/home/chirag/echoarg1
  • 将 hashbang 行的其余部分作为附加参数传递(在本例中为 argv[1]=my1
  • 当它附加原始 argv 列表时,它使用可执行路径 ("textinterpreter") 而不是实际的 argv[0] ("this"),然后继续使用 argv[1] ("is") 和其余部分...

【讨论】:

  • arg0 是要对要执行的文件可用的参数。它不必指向文件。您的解决方案将提供我想要的输出,但它没有解释为什么会发生这种情况。
  • 它在手册页部分进行了解释。第一个 execl arg 是加载和运行的路径,但下一个 arg 是作为 argv[0] 传递的内容。
  • 第一个参数是 const char *path。 arg0 将根据手册页传递给 ad argv[0]。
  • 是的,如果您进行上面的“实验”,它将直接按照手册页的建议工作。由于 bash 解释器,该切换似乎正在发生。
  • execl 在这里做的是正确的事情。通常execl 的前两个参数是相同的。但是正如execl 的手册页在上面的sn-p 中指出的那样,这是按照惯例execl 不会强制您为 patharg0 传递相同的值。在您的示例中,您需要为两者传递“textinterpreter”。这有意义吗?
【解决方案2】:

不是 bash 解释器(不管这应该是什么意思 - 这里不涉及 bash)丢弃 arg0,而是带有语句的内核函数 load_script()

         retval = remove_arg_zero(bprm);

上面有评论说

* 拼接 (1) argv[0] 的解释器名称 * (2) (可选) 解释器的参数 * (3) shell 脚本的文件名(替换 argv[0])

- 在你的情况下,(1)/home/chirag/echoarg1,(2)my1,(3)textinterpreter(替换this)。

【讨论】:

    猜你喜欢
    • 2014-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    相关资源
    最近更新 更多