提取 exec 函数的参数
Extracting arguments for an exec function
我正在尝试为学校设计一个项目,而且我已经非常接近了。目标是使用终端进行模拟,本质上是使用管道输入一系列命令并让它们正确执行。
下面列出了我当前的代码和输出,但主要要点是到目前为止我已经能够将命令和参数分开,但是当尝试在第 83 行使用 strcat 时,我感觉出现了分段错误。
我尝试添加的行是:
strcat (allargs, print);
}
printf("\n %s -- ALLARGS\n ", allargs);
提取所有参数的字符串的最佳方法是什么?由于我正在寻找使用 execvp 或 execlp,有没有更好的方法来解决这个问题?
谢谢!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <wait.h>
#include <sys/types.h>
#include <unistd.h>
// count number of "|" in string
int count_cmds(char *str)
{
int count = 1; // always will be 1 cmd
for (int i = 0; i < strlen(str); i++)
{
if (str[i] == '|')
{
count++;
}
}
return count;
}
char *get_token_at(char *command, size_t n, char *delimiter)
{
size_t position = 0;
char *copy = strdup(command);
char *token = strtok(copy, delimiter);
char *output = NULL;
while (token && position < n)
{
token = strtok(NULL, delimiter);
position++;
}
if (token && position == n)
output = strdup(token);
free(copy);
return output;
}
// trim whitespace
char *trimwhitespace(char *str)
{
char *end;
while (isspace(*str))
str++;
if (*str == 0)
return str;
end = str + strlen(str) - 1;
while (end > str && isspace(*end))
end--;
// new end of string
*(end + 1) = 0;
return str;
}
// count spaces in a string
int count_spaces(char *str)
{
int count = 0;
for (int i = 0; i < strlen(str); i++)
{
if (str[i] == ' ')
{
count++;
}
}
return count;
}
int fd[2];
int x;
int execc(char *command, int i)
{
printf("--- NEW CALL TO EXECC ---------------- COMMAND PASSED: %s \t\t\t\t\t\t ---- NUMBER PASSED: %d\n", command, i);
char *text = trimwhitespace((get_token_at(command, i - 1, "|")));
char *textargs = text;
char *allargs = " ";
for (int k = 0; k < count_spaces(textargs); k++)
{
char *print = trimwhitespace((get_token_at(textargs, k + 1, " ")));
printf("\n %s -- TEXTARG\n ", print);
}
char *cmd_only = get_token_at(text, 0, " ");
printf("\n %s -- cmd only\n ", cmd_only);
int x = fork();
if (x < 0)
{
perror("fork error");
exit(1);
}
// parent
if (x > 0)
{
printf("IN PARTENT -- wait for child\n");
wait(&x);
return x;
}
// child
if (x == 0)
{
printf("NEW CHILD -- exec or call next \n");
dup2(fd[0], STDIN_FILENO);
if (i == 1)
{
dup2(fd[1], STDOUT_FILENO);
}
close(fd[0]);
close(fd[1]);
if (i == 1)
{
char *z1 = trimwhitespace((get_token_at(command, i - 1, "|")));
printf(" i=1 ---------------- \n%s\n %s \n %s ", z1, z1, trimwhitespace((get_token_at(command, i - 1, " "), NULL)));
// execlp(z1,z1, (trimwhitespace(get_token_at(command, i, " ")), NULL)); // if last command, exec
}
else
{
execc(command, --i); // if not last command, recurse
char *z2 = trimwhitespace(get_token_at(command, i - 1, "|"));
printf("i!=1 --------------------\n%s\n %s \n %s ", z2, z2, trimwhitespace((get_token_at(command, i - 1, " "), NULL)));
// execlp(z2,z2, trimwhitespace((get_token_at(command, i, " "), NULL)));
}
// char* z3 = trimwhitespace(get_token_at(command, i-1, "|"));
// printf("%s\n %s \n %s \n",z3,z3, trimwhitespace((get_token_at(command, i-1, " "), NULL)));
// execlp(z3,z3, trimwhitespace((get_token_at(command, i, " "), NULL)));
}
}
int main(int argc, char *argv[])
{
printf(" Enter Command>");
char cmd[50];
fgets(cmd, 50, stdin);
int num_cmds = count_cmds(cmd);
printf("\n");
printf("Command count: %d\n", num_cmds);
execc(cmd, num_cmds);
pipe(fd);
if (pipe(fd) == -1)
{
printf("Error pipe\n");
exit(1);
}
}
./current Enter Command>ls -l | sort -r | grep -h
Command count: 3
--- NEW CALL TO EXECC ---------------- COMMAND PASSED: ls -l | sort -r | grep -h
---- NUMBER PASSED: 3
-h -- TEXTARG
grep -- cmd only IN PARTENT NEW CHILD
--- NEW CALL TO EXECC ---------------- COMMAND PASSED: ls -l | sort -r | grep -h
---- NUMBER PASSED: 2
-r -- TEXTARG
sort -- cmd only IN PARTENT NEW CHILD
--- NEW CALL TO EXECC ---------------- COMMAND PASSED: ls -l | sort -r | grep -h
---- NUMBER PASSED: 1
-l -- TEXTARG
ls -- cmd only IN PARTENT NEW CHILD
应该将allargs
定义为字符数组,而不是指针,
像这样:
char allargs[64] = {0};
我正在尝试为学校设计一个项目,而且我已经非常接近了。目标是使用终端进行模拟,本质上是使用管道输入一系列命令并让它们正确执行。
下面列出了我当前的代码和输出,但主要要点是到目前为止我已经能够将命令和参数分开,但是当尝试在第 83 行使用 strcat 时,我感觉出现了分段错误。
我尝试添加的行是:
strcat (allargs, print);
}
printf("\n %s -- ALLARGS\n ", allargs);
提取所有参数的字符串的最佳方法是什么?由于我正在寻找使用 execvp 或 execlp,有没有更好的方法来解决这个问题?
谢谢!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <wait.h>
#include <sys/types.h>
#include <unistd.h>
// count number of "|" in string
int count_cmds(char *str)
{
int count = 1; // always will be 1 cmd
for (int i = 0; i < strlen(str); i++)
{
if (str[i] == '|')
{
count++;
}
}
return count;
}
char *get_token_at(char *command, size_t n, char *delimiter)
{
size_t position = 0;
char *copy = strdup(command);
char *token = strtok(copy, delimiter);
char *output = NULL;
while (token && position < n)
{
token = strtok(NULL, delimiter);
position++;
}
if (token && position == n)
output = strdup(token);
free(copy);
return output;
}
// trim whitespace
char *trimwhitespace(char *str)
{
char *end;
while (isspace(*str))
str++;
if (*str == 0)
return str;
end = str + strlen(str) - 1;
while (end > str && isspace(*end))
end--;
// new end of string
*(end + 1) = 0;
return str;
}
// count spaces in a string
int count_spaces(char *str)
{
int count = 0;
for (int i = 0; i < strlen(str); i++)
{
if (str[i] == ' ')
{
count++;
}
}
return count;
}
int fd[2];
int x;
int execc(char *command, int i)
{
printf("--- NEW CALL TO EXECC ---------------- COMMAND PASSED: %s \t\t\t\t\t\t ---- NUMBER PASSED: %d\n", command, i);
char *text = trimwhitespace((get_token_at(command, i - 1, "|")));
char *textargs = text;
char *allargs = " ";
for (int k = 0; k < count_spaces(textargs); k++)
{
char *print = trimwhitespace((get_token_at(textargs, k + 1, " ")));
printf("\n %s -- TEXTARG\n ", print);
}
char *cmd_only = get_token_at(text, 0, " ");
printf("\n %s -- cmd only\n ", cmd_only);
int x = fork();
if (x < 0)
{
perror("fork error");
exit(1);
}
// parent
if (x > 0)
{
printf("IN PARTENT -- wait for child\n");
wait(&x);
return x;
}
// child
if (x == 0)
{
printf("NEW CHILD -- exec or call next \n");
dup2(fd[0], STDIN_FILENO);
if (i == 1)
{
dup2(fd[1], STDOUT_FILENO);
}
close(fd[0]);
close(fd[1]);
if (i == 1)
{
char *z1 = trimwhitespace((get_token_at(command, i - 1, "|")));
printf(" i=1 ---------------- \n%s\n %s \n %s ", z1, z1, trimwhitespace((get_token_at(command, i - 1, " "), NULL)));
// execlp(z1,z1, (trimwhitespace(get_token_at(command, i, " ")), NULL)); // if last command, exec
}
else
{
execc(command, --i); // if not last command, recurse
char *z2 = trimwhitespace(get_token_at(command, i - 1, "|"));
printf("i!=1 --------------------\n%s\n %s \n %s ", z2, z2, trimwhitespace((get_token_at(command, i - 1, " "), NULL)));
// execlp(z2,z2, trimwhitespace((get_token_at(command, i, " "), NULL)));
}
// char* z3 = trimwhitespace(get_token_at(command, i-1, "|"));
// printf("%s\n %s \n %s \n",z3,z3, trimwhitespace((get_token_at(command, i-1, " "), NULL)));
// execlp(z3,z3, trimwhitespace((get_token_at(command, i, " "), NULL)));
}
}
int main(int argc, char *argv[])
{
printf(" Enter Command>");
char cmd[50];
fgets(cmd, 50, stdin);
int num_cmds = count_cmds(cmd);
printf("\n");
printf("Command count: %d\n", num_cmds);
execc(cmd, num_cmds);
pipe(fd);
if (pipe(fd) == -1)
{
printf("Error pipe\n");
exit(1);
}
}
./current Enter Command>ls -l | sort -r | grep -h
Command count: 3 --- NEW CALL TO EXECC ---------------- COMMAND PASSED: ls -l | sort -r | grep -h ---- NUMBER PASSED: 3
-h -- TEXTARG
grep -- cmd only IN PARTENT NEW CHILD --- NEW CALL TO EXECC ---------------- COMMAND PASSED: ls -l | sort -r | grep -h ---- NUMBER PASSED: 2
-r -- TEXTARG
sort -- cmd only IN PARTENT NEW CHILD --- NEW CALL TO EXECC ---------------- COMMAND PASSED: ls -l | sort -r | grep -h ---- NUMBER PASSED: 1
-l -- TEXTARG
ls -- cmd only IN PARTENT NEW CHILD
应该将allargs
定义为字符数组,而不是指针,
像这样:
char allargs[64] = {0};