gpt4 book ai didi

c - Execve 没有按预期工作

转载 作者:太空宇宙 更新时间:2023-11-04 06:13:16 25 4
gpt4 key购买 nike

我正在用 c 编写一个基本的 shell,它将允许我执行简单的命令(我不需要检查可选参数),比如服务器(本地主机)中的“ls”。该程序必须能够处理多个客户端。

我已经完成了我必须使用 execve() 执行命令的部分(我必须使用这个函数)。我发现 execve() 在失败时返回 -1,在成功时不返回任何内容,因此我正在创建一个 fork() 来执行该进程中的命令。

现在,问题来了。我怎么知道 execve() 是否执行成功?我似乎找不到问题,我的代码总是向客户端返回“OK”。“csapp.h”它只是一个包含一些函数包装器的源文件。

#include "csapp.h"

void echo(int connfd, pid_t pid);

int main(int argc, char **argv)
{
int listenfd, connfd;
unsigned int clientlen;
struct sockaddr_in clientaddr;
struct hostent *hp;
char *haddrp, *port;
pid_t pid;

if (argc != 2) {
fprintf(stderr, "usage: %s <port>\n", argv[0]);
exit(0);
}
port = argv[1];

listenfd = Open_listenfd(port);
while (1) {
clientlen = sizeof(clientaddr);
while(1){
connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);
if((pid=Fork())==-1){
Close(connfd);
}
if(pid > 0){
break;
}
}

/* Determine the domain name and IP address of the client */
hp = Gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
haddrp = inet_ntoa(clientaddr.sin_addr);
printf("server connected to %s (%s)\n", hp->h_name, haddrp);

echo(connfd, pid);
Close(connfd);
}
exit(0);
}

void trim(char *string){
string[strlen(string)-1]=0;

}

char* concat(const char *s1, const char *s2)
{
char *result = malloc(strlen(s1) + strlen(s2) + 1); // +1 for the null-terminator
// in real code you would check for errors in malloc here
strcpy(result, s1);
strcat(result, s2);
return result;
}

void echo(int connfd, pid_t pid)
{
size_t n;
char buf[MAXLINE];
rio_t rio;

char *args[2];

args[1] = NULL;

Rio_readinitb(&rio, connfd);
while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) {
trim(buf);
args[0] = concat("/bin/", buf);
printf("server received %lu bytes\n", n);
printf("Command: %s\n",buf);
pid_t execPID;
int status;
if((execPID = fork()) > pid){
execve(args[0],args,NULL);
}else{

wait(&status);
if(WIFEXITED(status)){
if (WEXITSTATUS(status) == 0){
printf("status: %d\n", status);
printf("WIFEXITED: %d\n", WIFEXITED(status));
printf("WEXITSTATUS: %d\n", WEXITSTATUS(status));
Rio_writen(connfd, "OK\n", 3);
}
else
Rio_writen(connfd, "ERROR\n", 6);

}
}
/*if(status == -1){
Rio_writen(connfd, "ERROR\n", 6);

}
else{
Rio_writen(connfd, "OK\n", 3);
printf("%d\n", status);
}*/


}

}

客户端发送的“m”和“ls”的输出:

server received 2 bytes
Command: m
status: 0
WIFEXITED: 1
WEXITSTATUS: 0
server received 3 bytes
Command: ls
status: 0
WIFEXITED: 1
WEXITSTATUS: 0
Makefile client csapp.c csapp.o server.c
README.md client.c csapp.h server

非常感谢您的帮助,在过去的 14 个小时里,我一直坚持这一点。

最佳答案

How do I know if execve() executed successfully?

首先,正如您已经观察到的,服务器知道 execve() 调用本身已经失败,如果它返回的话。

其次,在子进程终止后,wait()waitpid() 可以告诉您它的退出状态。你似乎也解决了这个问题。

所以当你继续说,

I can't seem to find the problem, my code always returns "OK" to the client.

,这让我相信您的实际问题更像是“如何获取命令的输出?”答案:通过 child 的标准输出和(可能)标准错误流。不然怎么办?

默认情况下,子级从其父级继承其标准输入、标准输出和标准错误,但您可以通过调用 dup2() 为其指定不同的标准输入、标准输出和标准错误。在 execve() 之前的子进程中。通过将子流连接到父进程或其他进程可以读取的 pipe(),您可以用它做各种相当复杂的事情,但最简单的事情是使用 dup2() 简单地将 child 的输出和错误流定向到套接字:

// standard output:
if (dup2(connfd, 1) == -1) { /* handle error */ }

// standard error:
if (dup2(connfd, 2) == -1) { /* handle error */ }

然后命令的输出(如果有的话)将直接通过线路发送到客户端。

关于c - Execve 没有按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51777853/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com