Я пишу базовую оболочку на c, которая позволит мне выполнять простые команды (меня не просят проверять необязательные аргументы), такие как «ls» на сервере (localhost). Программа должна быть способна работать с несколькими клиентами.
Я сделал все, вплоть до выполнения команды с помощью execve() (Я ДОЛЖЕН ИСПОЛЬЗОВАТЬ ЭТУ ФУНКЦИЮ). Я обнаружил, что execve() возвращает -1 в случае ошибки и ничего не возвращает в случае успеха, поэтому я делаю fork() для выполнения команды в этом процессе.
Теперь к проблеме. Как узнать, успешно ли выполнено execve()? Кажется, я не могу найти проблему, мой код всегда возвращает клиенту «ОК». «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 часов.
wait(&status);
вы не посмотрели статус ошибкиwait()
, плюс не используйтеwait()
, он устарел, используйтеwaitpid()
, чтобы обязательно дождаться хорошего ребенка. - person Stargateur   schedule 10.08.2018if((execPID = fork()) > pid)
не имеет никакого смысла, вы должны убедиться, чтоfork()
является успешным, а затем просто сравнить его с0
сейчас, если это ребенок, как вы сделали в своем первомfork()
- person Stargateur   schedule 10.08.2018errno
, используйтеperror("wait():");
для печати. - person Stargateur   schedule 10.08.2018wait()
, делает правильныйfork()
, как я сказал в своем третьем комментарии. - person Stargateur   schedule 10.08.2018execPID
это0
, а не когда> 0
- person Stargateur   schedule 10.08.2018