我正在设计一个简单的shell,但是高级重定向有问题。
我可以这样做:ls-al>a.txt
但我做不到:wcb.txt
我该怎么做?
这里是执行i/o重定向的位置:

char *inpu=NULL; //Inpu is a global variable.
#define CREATE_FLAGS (O_WRONLY | O_CREAT | O_TRUNC)
#define CREATE_FLAGS1 (O_WRONLY | O_CREAT | O_APPEND)
#define CREATE_FLAGS2 (O_RDONLY | O_CREAT | O_APPEND)
#define CREATE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
#define MAXCHARNUM 128
#define MAXARGNUM 32


char *argsexec[MAXARGNUM]; /*This stores my executable arguments like cd ls.*/

void ioredirection(int f){
   int k,i,m;
   int input=-1;
   int output=-1;
   int append=-1;
   int fdin,fdout;

        for(k=0; k<f; k++){
            if(strcmp(argsexec[k],"<")==0){
                input=k;  // argument place of "<"
                m=1;
        argsexec[k]=NULL;
           }
            else if(strcmp(argsexec[k],">")==0){
                output=k; // argument place of ">"
                m=2;
        argsexec[k]=NULL;
           }
            else if(strcmp(argsexec[k],">>")==0){
                append=k; // argument place of ">>"
                m=3;
        argsexec[k]=NULL;
           }
        }

           if(m==1){
            int inp1;
    fdin=open(argsexec[input+1],O_RDONLY,CREATE_MODE);
    dup2(fdin,STDIN_FILENO);
    close(fdin);
    inp1=execlp(argsexec[0],argsexec[0],NULL);
           }

           if(m==2){
            fdout = open(argsexec[output+1], CREATE_FLAGS, CREATE_MODE);
            dup2 (fdout, STDOUT_FILENO);
            close(fdout);
            execvp(argsexec[0],argsexec);
           }

           if(m==3){
        fdout = open(argsexec[append+1], CREATE_FLAGS1, CREATE_MODE) ;
            dup2 (fdout, STDOUT_FILENO);
        close(fdout);
        execvp(argsexec[0],argsexec);
           }
}

b是这样变化的:
inpu=strtok(str," ");
while(inpu!=NULL){
  argsexec[b]=inpu;
  b++;
  inpu = strtok(NULL, " ");
}

我称之为儿童过程。
if (pid==0){
   ioredirection(b);

我希望它是明白的,我的全部是代码真的很长,我试图削减它这样。任何建议都将不胜感激。

最佳答案

我在格式化程序中运行了您的代码,得到(大大简化了):

void ioredirection(int f) {
    for (k over all arguments) {
        set m based on argsexec[k]
    }
    test m against 1, 2, and 3
}

因此,如果有两个(或更多)“重新定向”操作,则循环(for k)将设置m两个(或更多)次。然后,循环结束,您(最后)对三个可能的值中的每一个值测试一次m
第一个问题现在应该很清楚了(但由于这是一个学校项目,我不打算为你解决这个问题:-)。
第二个问题只有在查看在m上执行的三个测试时才清楚。这里只看一个就足够了:
    if (m == 1) {
        int inp1;
        fdin = open(argsexec[input + 1], O_RDONLY, CREATE_MODE);
        dup2(fdin, STDIN_FILENO);
        close(fdin);
        inp1 = execlp(argsexec[0], argsexec[0], NULL);
    }

(另外两个使用execvp而不是execlp.1)如果exec*家族函数调用成功,当前进程将立即被替换,这样exec*就永远不会返回。因此,如果需要重定向两个(或更多)值,则最终的*_FILENO调用必须推迟,直到所有其他重定向都完成。
1其中一个不是适当的功能。好吧,不要在这里跳舞:exec*是正确的选择。:-)
如果重定向后面没有文件名,则会出现第三个问题(请参见下文)。
这个代码片段的最后两个潜在问题不太明显,需要看整个事情。一个是否是“真正的bug”取决于你的shell有多简单。
execvp数组最多可以容纳128个指针值。argsexec中的条目应该是要运行的二进制文件的名称,它毕竟是提供给char *的,要使用argsexec[0]execvp必须是按顺序排列的多个execvp中的第一个:
argsexec[0]变为char *(在您调用的程序中),
argsexec[0]变成argv[0](程序的第一个参数),
argsexec[1]变成argv[1]
等等。。。截止日期:
argsexec[2],对于最小的整数argv[2],是argsexec[i]:这告诉i函数族:“好的,现在可以停止复制了。”
让我们再跳过明确的错误3,讨论潜在的错误4:这里不清楚是否有NULL设置为execv*argsexec[i]NULL的参数是最后一个f参数,因此iodirection不能是i;从这个代码片段中,我们无法判断某些(可能是argsexec[i]th)NULL是否是f+1。要使用argsexec[i]函数,它需要NULL
如果有一些I/O重定向,您将把一些execvp设置为空这将终止数组并使NULL调用正常工作。如果不是。。。?
这会导致潜在的bug#5:在“真正的”Unix shell中,您可以在命令的“中间”放置I/O重定向:
prog > stdout arg1 2> stderr arg2 < stdin arg3

它使用三个参数(argsexec[i]execvpprog)运行arg1。实际上,您甚至可以将重定向放在第一位:
<stdin >stdout 2>stderr prog arg1 arg2 arg3

在某些shell中,您可以多次“重新定向”(如果不需要,甚至不必运行命令):
$ ls
$ > foo > bar > baz
$ ls
bar     baz     foo

(但其他炮弹禁止:
$ rm *; exec csh -f
% > foo > bar > baz
Ambiguous output redirect.

并不是说csh可以效仿。:-) )
如果这是一个很大的“If”-您想要允许这个或类似的东西,您将需要“执行并删除”每个I/O重定向,将剩余的参数向下移动,使arg2保持“密集填充”状态,其中包含要提供给程序的各种arg3值。例如,如果argsexec是数组中有效的非char *项的长度,因此lenNULL,您需要“删除”argsexec[len]NULL(它们分别包含类似“>”的重定向和文件名),则:
for (i = j + 2; i <= len; i++) {
    argsexec[i - 2] = argsexec[i];
}

就可以了(循环运行到argsexec[j]以便它也复制终止的argsexec[j + 1])。
最后,确定的错误3:如果重定向位于最后一个位置,会发生什么?i <= len循环从NULL运行到argsexec[f - 1]包含。如果for (k ...)k是重定向,则文件名必须在0中。
但我们刚刚注意到(上面)需要f - 1。也就是说,如果有人试图:
ls >

那么k == f - 1应该包含argsexec[k]argsexec[f]argsexec[f]
在这种情况下,“真壳”和“真壳”的作用如下:
$ ls >
Syntax error: newline unexpected

% ls >
Missing name for redirect.

如果重定向后的文件名丢失,则需要类似的方法:拒绝尝试。

关于c - C程序中的高级I/O重定向。(简单Shell),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20457727/

10-11 19:42