I';我试图在shell环境中执行C中文件的读入行

I';我试图在shell环境中执行C中文件的读入行,c,shell,fork,C,Shell,Fork,我可以编译代码,将文件作为命令行参数执行,但什么也没发生。交互模式功能提示正常,但batchMode功能不提示 我试图读入一行,然后执行该行 示例文件 日期 ls-la 光盘 (行间没有间距。我无法在此处获取格式。) #包括 #包括 #包括 #包括 #包括 #定义bSize 1000 void drivelop(); 字符*用户输入(无效); void removeExit(char*原始,char*子字符串);//删除子字符串为“exit”的字符串 无效批处理模式(char*c); int m

我可以编译代码,将文件作为命令行参数执行,但什么也没发生。交互模式功能提示正常,但batchMode功能不提示

我试图读入一行,然后执行该行

示例文件

日期

ls-la

光盘

(行间没有间距。我无法在此处获取格式。)

#包括
#包括
#包括
#包括
#包括
#定义bSize 1000
void drivelop();
字符*用户输入(无效);
void removeExit(char*原始,char*子字符串);//删除子字符串为“exit”的字符串
无效批处理模式(char*c);
int main(int argc,字符**argv){
char*fTemp;
如果(argc==1)
driveLoop();//调用接受输入并执行命令的循环函数。
else if(argc==2)
batchMode(&argv[1][0]);
返回0;
}
void驱动循环(void){
char*comTokens[100];
char*Tentokens;
char*命令;
char*cd;
char*cdDir;
char*cdTemp;
char-cdBuf[bSize];
char checkExit[]=“退出”;
对于(;;){
printf(“>”);
command=userInput();//读取输入
if(!*命令)//允许空字符串错误
打破
char*exitpttr=strstrstr(命令,“exit”);//如果找到子字符串,则向指针返回一个值
removeExit(命令,“退出”);
puts(命令);//在函数筛选器之后更新数组
int i=0;
testokens=strtok(command,“\t\n”);//令牌是计算机识别shell命令的方式
而(TETELTOKENS&&i<99){//geeksforgeks.com
comTokens[i++]=Tentokens;
testokens=strtok(空,“\t\n”);
}
if(strcmp(comTokens[0],“exit”)==0)//如果输入仅为“exit”,则退出
出口(0);
if(strcmp(comTokens[0],“cd”)==0{//内置的更改目录命令
cd=getcwd(cdBuf,sizeof(cdBuf));
cdDir=strcat(cd,“/”);
cdTemp=strcat(cdDir,comTokens[1]);//cplusplus.com参考
chdir(cdTemp);
继续;
}
comTokens[i]=NULL;
pid_t cFork=fork();//创建父进程的重复子进程
如果(cFork==(pid_t)-1{//错误检查
佩罗尔(“福克”);
}
else如果(cFork==0){//在cplusplus.com上找到错误代码
execvp(comTokens[0],comTokens);
perror(“执行董事”);
}
否则{//返回子级。父级执行
智力状态;
waitpid(cWork和status,0);
如果(exitPtr!=NULL){//如果找到子字符串exit,则退出程序
出口(0);
}
}
}
}
char*userInput(void){//引用的Linux手册页-getline(3)(Linux.die.net)
char*input=NULL;
大小\u t大小=0;
getline(&input,&size,stdin);//随着时间的推移更新大小
返回输入;
}
void removeExit(char*原始,char*子字符串){//从字符串中删除退出
char*ex;
int len=strlen(子串);
而((ex=strstrstr(original,subString)){//是从堆栈溢出页引用的。
*ex='\0';
strcat(原件,ex+len);
}
}
无效批处理模式(字符*c){
char*tok[100];
char*batchTokens;
char*batchBuffer=NULL;
大小\u t批次大小=0;
文件*fp=fopen(c,“r”);
无符号整数行=1;
字符缓冲区[bSize];
while(fgets(buffer,sizeof(buffer),fp)){
int i=0;
char*toks=strtok(缓冲区“\t\n”);
而(toks&i<99){
tok[i]=malloc(strlen(toks)+1);
strcpy(tok[i++],toks);
toks=strtok(空,“\t\n”);
}
tok[i]=NULL;
pid_t bFork=fork();
如果(bFork==(pid_t)-1)
佩罗尔(“福克”);
else if(bFork==0){
execvp(tok[i],tok);
perror(“执行董事”);
}
否则{
智力状态;
waitpid(b工作和状态,0);
}
}
}
旁注。这是前一个问题的重新尝试,该问题因信息不足而被锁定。我已经更新了我的代码,并试图尽可能详细。 我很乐意提供任何进一步的帮助来回答我的问题

谢谢大家

编辑
我输入了一个fprintf来验证它是否读入了文件,它确实读入了文件。

首先注意,在输入文件中,最后一个命令
cd
不是一个系统命令,它是一个shell构建的,因此您可能会认为它会失败(除非经过特殊处理)

按照与
strdup
(如果可用)或简单地
malloc(strlen(toks)+1讨论的方式分配每个令牌(
tok[i]
允许您将当前令牌复制到分配的内存块。现在,每个
tok[i]
将引用保存的单个标记(而不是所有标记都指向最后一个标记——因为所有标记都被分配了相同的指针)

使用
execvp调用
execvp时,
batchMode
中最大的逻辑错误(tok[i],tok)
而不是正确地提供要作为
tok[0]
执行的文件。请注意,如果要执行的文件不在
路径中,则必须在输入文件中提供绝对路径

进行更改后,您的
batchMode
可以按如下方式编写(删除所有未使用的变量,并在
while
循环中移动
char*tok[100];
,以便在该范围内声明):

示例使用/输出

$ ./bin/shellorbatch dat/toksfile.txt
hello
goodbye

$ ./bin/shellorbatch dat/toksfile2.txt
Tue Feb  4 23:47:00 CST 2020
-rw-r--r-- 1 david david 24 Feb  4 23:24 dat/toksfile.txt
exec: No such file or directory

仔细检查一下,如果有问题请告诉我:

tok[i++]=toks
为每个
tok[i]
分配非常相同的指针,因此在循环结束时,每个
tok[i]
都指向最后一个
toks
。您需要分配存储空间。如果您有
strdup
,那么
tok[i++]=strdup(toks)如果不是,则
tok[i]=malloc(strlen(toks)+1)(验证)然后
strcpy(tok[i++],toks)否。只有一个
toks
。它是strtok每次返回的令牌。您只需要提供存储来保存每个令牌,因为下次调用
toks=strtok(NULL,“\t\n”)#include <sys/types.h>
#include <sys/wait.h>
...
void batchMode(char *c)
{
    char buffer[bSize];
    FILE *fp = fopen (c, "r");

    if (!fp) {
        perror ("fopen-c");
        return;
    }

    while (fgets (buffer, sizeof(buffer), fp)) {

        int i = 0;
        char *tok[100];
        char *toks = strtok(buffer, " \t\n");

        while (toks && i < 99){
            tok[i] = malloc (strlen(toks) + 1);
            strcpy(tok[i++], toks);
            toks = strtok(NULL, " \t\n");
        }

        tok[i] = NULL;
            pid_t bFork = fork();

        if (bFork == (pid_t) - 1)
            perror("fork");
        else if (bFork == 0){
            execvp (tok[0], tok);
            perror("exec");
        }
        else {
            int status;
            waitpid(bFork, &status, 0);
        }
    }
}
$ cat dat/toksfile.txt
echo hello
echo goodbye

$ cat dat/toksfile2.txt
date
ls -al dat/toksfile.txt
cd
$ ./bin/shellorbatch dat/toksfile.txt
hello
goodbye

$ ./bin/shellorbatch dat/toksfile2.txt
Tue Feb  4 23:47:00 CST 2020
-rw-r--r-- 1 david david 24 Feb  4 23:24 dat/toksfile.txt
exec: No such file or directory