我正在编写一个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语句感到抱歉。
答案 0 :(得分:2)
myshell.h
。countcmd()
和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;
或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
阅读stdin
(又名fgets()
)。总的来说,这很好(优于gets()
),但您需要注意fgets()
包含gets()
没有的换行符,您需要检查返回状态(你可能没有读过任何东西)。您还应该使用sizeof()
:
if (fgets(buff, sizeof(buff), stdin) == 0)
...error - read failed...
内存分配非常复杂。对于像char buff[100];
这样的固定大小输入,您可以使用非动态分配。总共不超过50个参数,因为它们是空白的。
等
答案 1 :(得分:0)
没有查看整个代码,因此可能存在其他错误,但是对于'ls'问题,您需要将以下内容添加到解析代码中:
while (buff[j] != '\0' && buff[j] != '\n')
这可确保您不会在*ptr1++ = (char) buff[j];
注意fgets如果遇到新行会停止阅读,但会将其作为字符串的一部分包含在内。