【发布时间】:2020-02-05 04:24:28
【问题描述】:
我可以编译代码,将文件作为命令行参数执行,但没有任何反应。交互模式功能正常提示,batchMode功能不提示。
我正在尝试读取一行,然后执行该行。
示例文件
日期
ls -la
光盘
(行与行之间没有间距。我无法在此处获取格式。)
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#define bSize 1000
void driveLoop();
char *userInput(void);
void removeExit(char *original, char *subString); // removes string with substring "exit"
void batchMode(char *c);
int main(int argc, char **argv){
char *fTemp;
if (argc == 1)
driveLoop(); // calls the loop function that accepts input and executes commands.
else if (argc == 2)
batchMode(&argv[1][0]);
return 0;
}
void driveLoop(void){
char *comTokens[100];
char *tempTokens;
char *command;
char *cd;
char *cdDir;
char* cdTemp;
char cdBuf[bSize];
char checkExit[] = "exit";
for (;;){
printf("> ");
command = userInput(); // reads input
if (!*command) // allows for empty string error
break;
char *exitPtr = strstr(command, "exit"); // returns a value to a pointer if substring is found
removeExit(command, "exit");
puts(command); // updates the array after the function filter
int i = 0;
tempTokens = strtok(command, " \t\n"); // tokens are how the computer recognizes shell commands
while (tempTokens && i < 99){ // geeksforgeeks.com
comTokens[i++] = tempTokens;
tempTokens = strtok(NULL, "\t\n");
}
if (strcmp(comTokens[0], "exit") == 0) // exit if input is "exit" only
exit(0);
if(strcmp(comTokens[0], "cd") == 0){ // built in change directory command
cd = getcwd(cdBuf, sizeof(cdBuf));
cdDir = strcat(cd, "/");
cdTemp = strcat(cdDir, comTokens[1]); // cplusplus.com reference
chdir(cdTemp);
continue;
}
comTokens[i] = NULL;
pid_t cFork = fork(); // creates duplicate child process of parent
if (cFork == (pid_t) - 1){ // error check
perror("fork");
}
else if (cFork == 0) { // error codes found on cplusplus.com
execvp(comTokens[0], comTokens);
perror("exec");
}
else { // children are returned. parent executes
int status;
waitpid(cFork, &status, 0);
if (exitPtr != NULL){ // if substring exit was found, exit the program
exit(0);
}
}
}
}
char *userInput(void){ // referenced Linux man page - getline(3) (linux.die.net)
char *input = NULL;
size_t size = 0;
getline(&input, &size, stdin); // updates the size as it goes along
return input;
}
void removeExit(char *original, char *subString){ // removes exit from string
char *ex;
int len = strlen(subString);
while ((ex = strstr(original, subString))){ // Referenced from a Stack Overflow page.
*ex = '\0';
strcat(original, ex+len);
}
}
void batchMode(char *c){
char *tok[100];
char *batchTokens;
char *batchBuffer = NULL;
size_t batchSize = 0;
FILE *fp = fopen(c, "r");
unsigned int line = 1;
char buffer[bSize];
while(fgets(buffer, sizeof(buffer), fp)){
int i = 0;
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[i], tok);
perror("exec");
}
else {
int status;
waitpid(bFork, &status, 0);
}
}
}
旁注。这是对先前因信息不足而锁定的问题的重新尝试。我已经更新了我的代码并尝试尽可能详细。 我很乐意提供进一步的帮助来回答我的问题。
谢谢大家。
编辑 我放入了一个 fprintf 来验证它是否读取了文件,并且确实如此。
【问题讨论】:
-
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每次返回的token。您只需要提供存储来保存每个令牌,因为下次您调用toks = strtok(NULL, " \t\n");时,toks将指向一个新地址。所以只需分配存储空间,复制toks当前指向的内容,然后调用strtok(重复)直到你用完令牌。 -
好的,我更新了我的帖子和我的程序。既然它仍然什么都不做,那一定意味着我在其他地方也有问题,对吧?
-
让我看看。
-
我还添加了一个输入文件示例。它在帖子中并没有完美地显示出来,但它是每行一个命令。行与行之间没有间距。