-2

我正在编写一个 shell 程序,当将值传递给我时,execv()我需要一个指向程序名称的 char 指针(即ls),并且我需要一个指向参数的 char 指针数组的指针。

我通过并解析用户的输入,如果我输入ls,如果我打印我的char *printf()打印出“ls”。所以我正确地解析了这条线并存储了正确的信息。当我将它传递给 时execv(),它会显示错误的路径名,但是如果我手动将指针更改为progs[0] = "ls",那么它就可以工作。如果我比较这两个字符串,strcmp(mypointer, "ls"),它表明虽然 mypointer 打印出"ls",但它并不等同于"ls"

有谁知道为什么?

这是我的shell进程代码:

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>

char **progs;
char ***arguments;
char **mode;
char pathname[] = "/bin/";

int main(int argc, char ** argv){

//printf("\n %s \n", progs);
//fflush(stdout);

char buff[100];
FILE *p;

p = fdopen(0, "r");  //opens FD 0 (Stdin) as a stream

char * pathname;

while(1){

    //printf("I'm at the top");

    if(isatty(1) == 1){ //check to see if stdout is going to the terminal
    printstart();       //if so, print 
    }

    fgets(buff, 100, p); // Gets the input from the stdin and puts it in buff

    int processid = fork();  //fork into child to complete task

    if(processid == 0){

        //initialize all variables

        int numcmd = countcmd(buff);
        int pipes = countpipes(buff);
        int i;
        int j;

        //allocate memory for tokenization

        progs = malloc(numcmd * sizeof(char *));
        arguments = malloc((numcmd) * sizeof(char *));
        mode = malloc((numcmd*2) * sizeof(char *));

        for(i = 0; i < numcmd; i++){
            progs[i] = malloc(10* sizeof(char *));
            mode[i] = malloc(10 * sizeof(char *));
            mode[2*numcmd-1-i] = malloc(10 * sizeof(char*));
            arguments[i] = malloc(15 * sizeof(char *));
                for(j = 0; j < 15; j++){
                arguments[i][j] = malloc(15 * sizeof(char*));
                }
            }

        /////////////////////////////////////////////////////////////////////

        parse(buff); //parses input and places it in the static progs

        for(i = 0; i < 1; i++){

        printf("\n This is progs %s", arguments[0][0]);

        char temp[25];
        //strcpy(temp, "/bin/");
        strcpy(temp, progs[0]);
        //strcat(temp, ' \0');

        //*progs = "ls";
        char * ptr = progs[0];
        for(;*ptr != '\0';){
            printf("This is what pointer poitns to %c \n", *ptr++);
            }
        printf("This is the program: <<%s>>", progs[0]);
        fflush(stdout);
        char * argument[2];
        argument[0] = "ls";
        argument[1] = '\0';
        char * hell = "l\0";

        printf("This is the value of comparison %d\n", strcmp(progs[0], hell));

        char **temparg = arguments[0];
        //char temp[20] = progs[0];

        errno = 0;
        execvp("ls", *argument);

        char * error = strerror(errno);
        printf("This is the error %s", error);
        return;
        }

    }       
        else{
        int status;
        waitpid(processid, &status, WIFEXITED(status));

        }
}

return 0;
}

这是我的 parse() 代码:

#include <string.h>
#include <stdio.h>
#include "myshell.h"

int parse(char * buff){

//Initialize all variables and pointers
int cmd = 0;
int argument = 0;
int mod = 0;
int j = 0;
int hitargs = 0;
int gotcommand = 0;
int multiarg = 0;

char ** argptr = arguments[cmd];
char * ptr1 = progs[cmd];
char * argptr2 = argptr[argument];
char * ptr2 = mode[mod];

while(buff[j] != '\0'){

    switch(buff[j]){

        case ';':
            cmd++;
            argument = 0;
            multiarg = 1;
            *argptr2++ = '\0';

            argptr = arguments[cmd];
            argptr2 = argptr[argument];
            ptr1 = progs[cmd];

            *ptr2 = buff[j];
            mod += 2;
            ptr2 = mode[mod];

        case ' ':
            if(gotcommand == 0){
            break;
            }
            else{
                if(hitargs == 0){
                hitargs = 1;
                *ptr1++ = '\0';
                argument++;
                argptr2 = argptr[argument];
                }
                else{
                argument++;
                argptr2 = argptr[argument];
                }
                break;
            }
        default:
            if(gotcommand == 0){
                *ptr1++ = (char) buff[j];
                *argptr2++ = buff[j];
                gotcommand = 1;
            }
            else if(gotcommand == 1 && hitargs == 0){
                *ptr1++ = (char) buff[j];
                *argptr2++ = buff[j];
            }
            else if(gotcommand == 1 && hitargs == 1){
                *argptr2++ = buff[j];
            }
    }

j++;
}

*argptr2++ = '\0';
*ptr1++ = '\0';

int cmdflag = 0;
int spaceflag = 0;
int argflag = 0;
int cmdct = 1; //account for null
int argumentct = 1; //account for null termination

return 1;
}

对随机 printf 语句感到抱歉。

4

2 回答 2

2
  • 你的主程序应该myshell.h像你的解析代码一样包含。
  • 拥有缺失的函数会很有帮助(例如countcmd()and countpipes()——虽然我们可以从它们的名字中猜到一点,但并不清楚它们的确切作用)。
  • 你应该<unistd.h>在你的主程序中包含。
  • 您应该已经收到有关未声明函数(例如fork())的警告,并且您应该注意并修复这些警告。
    • 如果您没有收到这些警告,则需要在编译中添加更多警告选项。
    • 如果你使用gcc,使用-Wall是一个很好的起点。

启用警告后,您将看到:

shex.c:95: warning: passing argument 2 of ‘execvp’ from incompatible pointer type
shex.c:99: warning: ‘return’ with no value, in function returning non-void
  • 后者最好通过return EXIT_FAILURE;or处理exit(EXIT_FAILURE);
  • 前者由 触发execvp("ls", *argument);
  • 对于包含许多参数的东西,最好使用复数词(参数?)。
  • ...哦,我明白了,有一个全局变量arguments
  • 你声明char ***arguments;. 哎哟! 我偶尔会使用三重指针,但只是非常偶尔。大多数时候,这是一个太多级别的指针,尤其是对于这个练习。
  • 然后还有一个局部变量char *argument[2];
  • 因此,正确的调用是execvp("ls", argument);

我会立即扩展等待代码以至少打印信息:

    else
    {   
        int status;
        int corpse = waitpid(processid, &status, WIFEXITED(status));
        printf("Command exited: PID = %d; status = 0x%.4X\n", corpse, status);
    } 

在您的解析代码中,case ';':插入到case ' ':. 如果这是故意的,请将其记录下来(带有注释,例如/* DROP THROUGH */);如果没有,请插入缺少的中断。你的default:案子可能也应该休息一下。这不是很重要,但它是传统的,如果需要处理新案件,它可以保护您免遭遗漏。

末尾声明的五个变量的字符串parse()是多余的;它们是从未使用过的局部变量(正如编译器告诉你的那样)。

main()你做的顶部:

FILE *p;
p = fdopen(0, "r");  //opens FD 0 (Stdin) as a stream

这不是必需的;stdin已作为流打开。

您从p(aka stdin) 中读取fgets(). 总的来说,这很好(比 更好gets()),但是您需要注意其中fgets()包含一个不包含的换行符gets(),并且您需要检查返回状态(您可能什么都没有阅读)。您还应该使用sizeof()

if (fgets(buff, sizeof(buff), stdin) == 0)
    ...error - read failed...

内存分配异常复杂。对于固定大小的输入,例如char buff[100];,您可以使用非动态分配。总共不能超过 50 个参数,因为它们是空格分隔的。

等等。

于 2012-04-15T22:57:03.327 回答
0

没有查看整个代码,因此可能存在其他错误,但关于“ls”问题,您需要在解析代码中添加以下内容:

      while (buff[j] != '\0' && buff[j]  != '\n')

这确保您不会在命令指针中添加“换行符”*ptr1++ = (char) buff[j];

注意fgets如果遇到新行将停止读取,但会将其作为字符串的一部分包含在内。

于 2012-04-15T21:40:25.853 回答