I';我试图在shell环境中执行C中文件的读入行
我可以编译代码,将文件作为命令行参数执行,但什么也没发生。交互模式功能提示正常,但batchMode功能不提示 我试图读入一行,然后执行该行 示例文件 日期 ls-la 光盘 (行间没有间距。我无法在此处获取格式。)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
#包括
#包括
#包括
#包括
#包括
#定义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