我一直在努力工作几个小时,当我输入“ls”并将参数args传递给execvp()函数时,我收到错误消息“ls:无法访问'':没有这样的文件或目录”。当我在args中打印char数组时,它似乎都正确,但是当我手动输入args [0] =“ls”和args [1] =“ - l”时,一切正常。这是代码:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/*
*
*/
int main() {
char buffer[25];
char exit[5] = {'e', 'x', 'i', 't', '\0'};
while(strcmp(buffer, exit) != 0){
//save stdin to buffer
int i = 0, numwords = 0, k = 0, l = 0, j =0;
char ** args;
memset(buffer, 0, strlen(buffer));
printf("?: ");
while((buffer[i] = getchar()) != '\n'){
i++;
}
buffer[i] = '\0';
i = 0;
printf("%s", buffer);
//start parsing and save to a char[][] args
//get the number of words
while( buffer[i] != '\0'){
if(buffer[i] == ' '){
i++;
}
else if(buffer[i] != ' ' && buffer[i] != '\0'){
numwords++;
while(buffer[i] != ' ' && buffer[i] != '\0'){
i++;
}
}
else{
i++;
}
}
numwords += 1; //for the null char '\0'
args = malloc((sizeof(char*))*numwords);
i = 0;
while(i < numwords){
args[i] = malloc((sizeof(char))*(50));
i++;
}
i = 0;
printf("%d", numwords);
//get each word from buffer and save it to temp then save temp to the array
while( buffer[i] != '\0'){
char temp[15];
if(buffer[i] == ' '){
i++;
}
else if(buffer[i] != ' ' && buffer[i] != '\0'){
while(buffer[i] != ' ' && buffer[i] != '\0'){
temp[k] = buffer[i];
k++;
i++;
}
}
else{
i++;
}
if(k != 0){
int j = 0;
while(j < k){
(args)[l][j] = temp[j];
j++;
}
(args)[l][j] = '\0';
memset(temp, 0 , strlen(temp));
k = 0;
l++;
}
}
(args)[l][0] = '\0';
execvp(args[0], args);
//check printing!
// for(i = 0; i< numwords; i++){
// for(j = 0; j< numwords-1; j++){
// printf("%s", args[j]);
// }
// printf("%s", args[1]);
// printf("%s", args[0]);
}
printf("Logout Success\n");
return 0;
}
答案 0 :(得分:0)
简单的回答,当我将空字符添加到我放入的数组列表的末尾时:
args[l][0] = '\0'.
我需要放的只是
args[l] = '\0'.
我做到了这一点并且有效!
答案 1 :(得分:0)
static void free_string_list(char** strings) {
if (!strings)
return;
for (char** p = strings; *p; ++p)
free(*p);
free(strings);
}
// Correctly handles leading spaces.
// Correctly handles trailing spaces.
// Correctly handles multiple spaces.
// Return NULL and sets errno on error.
// Free result with free_string_list otherwise.
static char** split_into_words(const char* s) {
size_t count = 0;
{
const char *src = s;
while (1) {
while (*src && *src == ' ')
++src;
if (!*src)
break;
while (*src && *src != ' ')
++src;
++count;
}
}
char** words = malloc(sizeof(char*) * (count+1));
if (!words)
goto ERROR;
{
const char *src = s;
char** dst = words;
while (1) {
while (*src && *src == ' ')
++src;
if (!*src)
break;
const char* src_s = src;
while (*src && *src != ' ')
++src;
const char* src_e = src;
size_t len = src_e - src_s;
char* dst_word = *dst = malloc(len+1);
if (!dst_word)
goto ERROR;
memcpy(dst_word, src_s, len);
dst_word[len] = 0;
++dst;
}
*dst = NULL;
}
return words;
ERROR:
free_string_list(words);
return NULL;
}
// Correctly handles exec failures (e.g. command not found and permission errors).
// Outputs error message on error.
// -1 = Error creating child or executing command.
// 0 = ok.
// 1 = Child killed or program returned an error.
int execute_command(char** cmd) {
int pipefd[2]; // r,w
pipefd[0] = -1;
pipefd[1] = -1;
if (pipe(pipefd) == -1) {
perror("pipe");
goto EXEC_ERROR;
}
{
int flags = fcntl(pipefd[1], F_GETFD, 0);
if (flags == -1) {
perror("fcntl F_GETFD");
goto EXEC_ERROR;
}
if (fcntl(pipefd[1], F_SETFD, flags | FD_CLOEXEC) == -1) {
perror("fcntl F_SETFD");
goto EXEC_ERROR;
}
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
goto EXEC_ERROR;
}
if (pid == 0) {
close(pipefd[0]);
execvp(cmd[0], cmd);
int exec_errno = errno;
perror("exec");
write(pipe, &exec_errno, sizeof(exec_errno));
_exit(1);
}
close(pipefd[1]);
pipefd[1] = -1;
{
int exec_errno;
ssize_t bytes_read = read(pipefd[0], &exec_errno, sizeof(exec_errno));
if (bytes_read == -1) {
perror("read");
goto EXEC_ERROR;
}
if (bytes_read != 0) {
errno = exec_errno;
perror("exec");
goto EXEC_ERROR;
}
}
close(pipefd[0]);
pipefd[0] = -1;
int status;
if (waitpid(pid, &status, 0) == -1) {
perror("waitpid");
goto EXEC_ERROR;
}
if (WIFSIGNALED(status)) {
fprintf(stderr, "Child killed by signal %d\n", WTERMSIG(status));
goto PROGRAM_ERROR;
}
if (WEXITSTATUS(status) > 0) {
fprintf(stderr, "Child exited with error %d\n", WEXITSTATUS(status));
goto PROGRAM_ERROR;
}
return 0;
EXEC_ERROR:
if (pipefd[0] != -1) close(pipefd[0]);
if (pipefd[1] != -1) close(pipefd[1]);
return -1;
PROGRAM_ERROR:
return 1;
}
int main(void) {
int rv = 1;
char* line = NULL;
size_t line_size = 0;
char** cmd = NULL;
while (1) {
ssize_t num_read = getline(&line, &line_size, stdin);
if (num_read == -1) {
if (errno) {
perror("getline");
goto ERROR;
}
break;
}
if (line[num_read-1] == '\n')
line[num_read-1] = 0;
char** cmd = split_into_words(line);
if (!cmd) {
perror("malloc");
goto ERROR;
}
if (strcmp(cmd[0], "exit") == 0)
break;
if (execute_command(cmd) == -1)
goto ERROR;
free_string_list(cmd);
cmd = NULL;
}
rv = 0;
ERROR:
free_string_list(cmd);
free(line);
return rv;
}
未测试。