C written HTTP server resets connection after repling - c

I've read all the related answers but could not find the reason why this is happening. I've tried replacing close() to shutdown and then close and more but still the same.
All I need is to be able to browse to my server and when asking a file it'll return its content and when asking a directory it will return a list of whats in it. this all WORKS, except for the RST packet.
Can anyone help?
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <signal.h>
#define HTTP_BAD_REQUEST "HTTP/1.1 404 Not Found\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>File Not Found</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_GOOD_REQUEST "HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Results</TITLE>\n</HEAD>\n<BODY>\n"
#define HTTP_ERROR "HTTP/1.1 500 Internal Server Error\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Internal Server Error!</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_NOT_IMPLEMENTED "HTTP/1.1 501 Not Implemented\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Method Not Implemented</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_END "<br/></BODY></HTML>\n\0"
#define MAX_REQUEST_SIZE 1024
int send_response(int fd, char* filepath)
{
struct stat statbuf;
int iofd;
int check = 1;
char buf[1024];
if ( stat(filepath,&statbuf) < 0 )
{
printf("Path not found\n");
send(fd, HTTP_BAD_REQUEST, strlen(HTTP_BAD_REQUEST), 0);
return -1;
}
else
{
if(S_ISDIR(statbuf.st_mode))
{
//directory
DIR *dp;
struct dirent *ep;
dp = opendir (filepath);
if (dp == NULL)
{
printf("Error opening directory\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
send(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST), 0);
ep = readdir (dp);
while (ep != NULL)
{
send(fd, ep->d_name, strlen(ep->d_name), 0);
send(fd, "<br/>", strlen("<br/>"), 0);
ep = readdir (dp);
}
send(fd, HTTP_END, strlen(HTTP_END), 0);
(void) closedir (dp);
return 0;
}
else if (S_ISREG(statbuf.st_mode))
{
//regular file
iofd = open(filepath, O_RDONLY);
if( iofd < 0 )
{
printf("Error opening file\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
send(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST), 0);
while ( check > 0)
{
check = read(iofd,buf,sizeof(buf));
if (check < 0)
{
printf("Error reading file\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
close(iofd);
return -1;
}
else if (check == 0)
break;
else
send(fd, buf, strlen(buf), 0);
}
send(fd, HTTP_END, strlen(HTTP_END), 0);
close(iofd);
return 0;
}
}
}
int process(int fd, char* header)
{
char npath[MAX_REQUEST_SIZE];
char *eol = strchr(header, '\r');
// split header to get path and method
char *method = strtok(header, " ");
char *path = strtok(NULL, " ");
char *http = strtok(NULL, " ");
if( eol != NULL )
*eol = '\0';
if( strcmp(method, "GET") || (strcmp(method, "POST")))
{
if( path[0] == '/' && path[1] == '\0' )
{
path ="/";
}
else if( path[0] == '/' )
{
snprintf(npath, MAX_REQUEST_SIZE, "%s", path);
path = npath;
}
return send_response(fd, path);
}
else
{
send(fd, HTTP_NOT_IMPLEMENTED, strlen(HTTP_NOT_IMPLEMENTED), 0);
return -1;
}
}
int get_line(int sock, char *buf, int size)
{
int i = 0;
char c = '\0';
int n;
while ((i < size - 1) && (c != '\n'))
{
n = recv(sock, &c, 1, 0);
if (n > 0)
{
if (c == '\r')
{
n = recv(sock, &c, 1, MSG_PEEK);
if ((n > 0) && (c == '\n'))
recv(sock, &c, 1, 0);
else
c = '\n';
}
buf[i] = c;
i++;
}
else
c = '\n';
}
buf[i] = '\0';
return(i);
}
int service(int fd)
{
char buffer[MAX_REQUEST_SIZE];
if (get_line(fd, buffer, MAX_REQUEST_SIZE) <= 0)
{
printf("Error reading from socket");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
return process(fd, buffer);
}
void cleanup( int signal )
{
int pid;
while(1)
{
pid = waitpid(-1, NULL, WNOHANG);
if( pid < 0 )
break;
else if( pid == 0 )
break;
}
exit(0);
}
int main(int argc, char *argv[])
{
int port = 80;
int max_requests;
struct sigaction finish;
finish.sa_handler = &cleanup;
sigaction( SIGINT, &finish, NULL );
if ((argc == 1) || (argc > 3))
{
printf("Usage Error: wrong amount of arguments to main");
return -1;
}
else if (argc == 3)
{
max_requests = strtol(argv[1], NULL, 0);
port = strtol(argv[2], NULL, 0);
}
else
max_requests = strtol(argv[1], NULL, 0);
struct sockaddr_in servaddr;
int serversock = socket(AF_INET, SOCK_STREAM, 0);
int on = 1;
if( serversock < 0 )
{
printf("Error creating socket: %s\n", strerror(errno));
return 1;
}
if( setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0 )
printf("Error tweaking socket options: %s\n", strerror(errno));
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
if( bind(serversock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
{
printf("Error binding to server address: %s\n", strerror(errno));
return 1;
}
if( listen(serversock, max_requests) < 0 )
{
printf("Error using listen(): %s\n", strerror(errno));
return 1;
}
while(1)
{
int clientsock, pid, childstatus;
//server shall now wait for a new connection
clientsock = accept(serversock, NULL, NULL);
if( clientsock < 0 )
{
printf("Error using accept(): %s\n", strerror(errno));
return 1;
}
pid = fork();
if( pid < 0 )
{
printf("Error using fork(): %s\n", strerror(errno));
send(clientsock, HTTP_ERROR, strlen(HTTP_ERROR), 0);
close(clientsock);
continue;
}
else if( pid == 0 )
{
shutdown(serversock, 2);
if (service(clientsock) != 0 )
printf("error in service\n");
if (shutdown(clientsock, SHUT_WR) != 0)
{
printf("Error shutting the socket down: %s\n", strerror(errno));
return -1;
}
close(clientsock);
return 0;
}
pid = waitpid(-1, NULL, WNOHANG);
if( pid < 0 )
{
printf("Error using waitpid(): %s\n", strerror(errno));
break;
}
close(clientsock);
}
return 999;
}

the following code:
cleanly compiles
properly outputs error messages to stderr
properly outputs a 'usage' message when not correct number of command line parameters
'should' operate correctly with connections after the first
caveat: not thoroughly tested.
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <signal.h>
#define HTTP_BAD_REQUEST "HTTP/1.1 404 Not Found\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>File Not Found</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_GOOD_REQUEST "HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Results</TITLE>\n</HEAD>\n<BODY>\n"
#define HTTP_ERROR "HTTP/1.1 500 Internal Server Error\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Internal Server Error!</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_NOT_IMPLEMENTED "HTTP/1.1 501 Not Implemented\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Method Not Implemented</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_END "<br/></BODY></HTML>\n\0"
#define MAX_REQUEST_SIZE 1024
int send_response(int fd, char* filepath)
{
struct stat statbuf;
int iofd; // file descriptor
ssize_t readStatus = 1;
char buf[ MAX_REQUEST_SIZE ];
if ( stat(filepath,&statbuf) < 0 )
{
perror( "stat for file failed" );
//printf("Path not found\n");
send(fd, HTTP_BAD_REQUEST, strlen(HTTP_BAD_REQUEST), 0);
return -1;
}
else
{ // path found
if(S_ISDIR(statbuf.st_mode))
{
//directory
DIR *dp;
struct dirent *ep;
dp = opendir (filepath);
if (dp == NULL)
{
fprintf( stderr, "Error opening directory\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
// implied else, opendir successful
send(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST), 0);
ep = readdir (dp);
while (ep != NULL)
{
send(fd, ep->d_name, strlen(ep->d_name), 0);
send(fd, "<br />", strlen("<br />"), 0);
ep = readdir (dp);
}
send(fd, HTTP_END, strlen(HTTP_END), 0);
closedir (dp);
return 0;
}
else if (S_ISREG(statbuf.st_mode))
{ //regular file
iofd = open(filepath, O_RDONLY);
if( iofd < 0 )
{
//fprintf(stderr, "Error opening file\n");
perror( "open failed" );
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
// implied else, open successful
send(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST), 0);
while ( readStatus > 0)
{
readStatus = read(iofd,buf,sizeof(buf));
if (readStatus < 0)
{
perror( "read of file failed");
//printf("Error reading file\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
close(iofd);
return -1;
}
else if (readStatus == 0) // EOF or signal
break;
else // transmit line from file
send(fd, buf, strlen(buf), 0);
} // end while
send(fd, HTTP_END, strlen(HTTP_END), 0);
close(iofd);
return 0;
}
}
return -2;
}
int process(int fd, char* header)
{
// split header to get path and method
char *method = strtok(header, " ");
char *path = strtok(NULL, " ");
//char *http = strtok(NULL, " ");
// if trailing newline, replace with NUL byte
char *eol = NULL;
if( NULL == (eol = strchr(header, '\r') ) )
*eol = '\0';
if( strcmp(method, "GET") || (strcmp(method, "POST")))
{
return send_response(fd, path);
}
else
{
send(fd, HTTP_NOT_IMPLEMENTED, strlen(HTTP_NOT_IMPLEMENTED), 0);
return -1;
}
} // end function: process
int get_line(int sock, char *buf, int size)
{
int i = 0;
char c = '\0';
ssize_t recvStatus;
while ( (i < (size - 1)) && (c != '\n') )
{
recvStatus = recv(sock, &c, 1, 0);
if ( recvStatus > 0)
{ // then some bytes read
if (c == '\r')
{
recvStatus = recv(sock, &c, 1, MSG_PEEK);
if ((recvStatus > 0) && (c == '\n'))
recv(sock, &c, 1, 0);
else
c = '\n';
} // endif
buf[i] = c;
i++;
}
else
{
c = '\n';
} // endif
} // end while
// terminate the char array
buf[i] = '\0';
return(i);
} // end function: get_line
int service(int fd)
{
char buffer[MAX_REQUEST_SIZE];
if (get_line(fd, buffer, MAX_REQUEST_SIZE) <= 0)
{
fprintf( stderr, "Error reading from socket");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
return process(fd, buffer);
} // end function: service
void cleanup( int signal )
{
(void)signal;
pid_t pid;
while(1)
{
pid = waitpid(-1, NULL, WNOHANG);
if( pid <= 0 )
break;
}
exit(0);
} // end function: cleanup
int main(int argc, char *argv[])
{
uint16_t port = 80;
int max_requests;
struct sigaction finish;
finish.sa_handler = &cleanup;
sigaction( SIGINT, &finish, NULL );
if ( (argc != 3) && (argc != 2) )
{
fprintf( stderr, "USAGE: %s <maxConnections> [<portToUse>]\n", argv[0]);
//printf("Usage Error: wrong amount of arguments to main");
return -1;
}
max_requests = (int)strtol(argv[1], NULL, 0);
if( 3 == argc )
{
port = (uint16_t)strtol(argv[2], NULL, 0);
}
int serversock = socket(AF_INET, SOCK_STREAM, 0);
if( serversock < 0 )
{
printf("Error creating socket: %s\n", strerror(errno));
return 1;
}
int on = 1;
if( setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0 )
{
perror( "setsockopt for SO_REUSEADDR failed" );
//printf("Error tweaking socket options: %s\n", strerror(errno));
}
if( setsockopt(serversock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0 )
{
perror( "setsockopt for SO_KEEPALIVE failed" );
//printf("Error tweaking socket options: %s\n", strerror(errno));
}
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
if( bind(serversock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
{
perror( "bind failed" );
//printf("Error binding to server address: %s\n", strerror(errno));
return 1;
}
if( listen(serversock, max_requests) < 0 )
{
perror( "listen failed" );
//printf("Error using listen(): %s\n", strerror(errno));
return 1;
}
while(1)
{
int clientsock;
pid_t pid;
//int childstatus;
//server shall now wait for a new connection
clientsock = accept(serversock, NULL, NULL);
if( clientsock < 0 )
{
perror( "accept failed" );
//printf("Error using accept(): %s\n", strerror(errno));
close( serversock );
return 1;
}
pid = fork();
switch( pid )
{
case -1: // fork failed
fprintf(stderr, "Error using fork(): %s\n", strerror(errno));
send(clientsock, HTTP_ERROR, strlen(HTTP_ERROR), 0);
close(clientsock);
break;
case 0: // in child process
//shutdown(serversock, 2);
if (service(clientsock) != 0 )
{
fprintf( stderr, "error in service\n");
}
close(clientsock);
return 0;
break;
default: // in parent process
pid = waitpid( -1, NULL, WNOHANG);
close(clientsock);
break;
} // end switch
} // end while
return 0;
} // end function: main

Related

multiple client process connect to 1 server process

I'm making C socket program that 1 server process communicates to 1 client process of all 4 processes in turn.
More specifically, when the client and the server talk to each other 10 messages(5 messages for each), the other client who's waiting for connecting to the server connects and do the same thing. Each clients must have different ports (8000-8003) when connecting.
I think my program below communicates to only 1 client which matches to the same port with the server(8000).
What should I do with this when there should be just 1 server process and 4 client processes using different ports?
screentshot from client
screenshot from server
client.c
#define _POSIX_SOURCE
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
int main(int argc, const char * argv[]) {
int c_socket_fd;
struct sockaddr_in server_address;
char fromServer[100];
int str_len;
int PORT = 8000;
int count = 0;
int status;
pid_t wait_pid;
pid_t pid = fork();
if (pid < 0) {
printf("fork failed!\n");
return 0;
} else if (pid == 0) {
// P-C1
pid = fork();
if (pid < 0) {
printf("fork failed!\n");
return 0;
} else if (pid == 0) {
// P-C1-C3
PORT = 8003;
} else if (pid > 0) {
// P-C1
PORT = 8001;
}
} else if (pid > 0) {
// P
pid = fork();
if (pid < 0) {
printf("fork failed!\n");
return 0;
} else if (pid == 0) {
// P-C2
PORT = 8002;
} else if (pid > 0) {
// P
PORT = 8000;
}
}
printf("pid: %d ppid: %d\n", pid, getppid());
c_socket_fd = socket(PF_INET, SOCK_STREAM, 0);
printf("Created Client Socket\n");
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
server_address.sin_port = htons(PORT);
if(connect(c_socket_fd, (struct sockaddr*)&server_address, sizeof(server_address)) == 0) {
printf("Connected Server\n");
while (1) {
char toServer[100] = "Hello Server, this is message No. ";
char* ch = toServer;
while (*ch != '\0') {
ch++;
}
*ch = ('0' + count);
ch++;
char temp[7] = " from ";
char* temp_ch = temp;
while(*temp_ch != '\0') {
*ch = *temp_ch;
temp_ch++;
ch++;
}
int process_id = pid;
if (process_id >= 10000) {
char temp[6] = {0,};
sprintf(temp, "%d", process_id);
char* temp_ch = temp;
while(*temp_ch != '\0') {
*ch = *temp_ch;
temp_ch++;
ch++;
}
} else if (process_id >= 1000) {
char temp[5] = {0,};
sprintf(temp, "%d", process_id);
char* temp_ch = temp;
while(*temp_ch != '\0') {
*ch = *temp_ch;
temp_ch++;
ch++;
}
} else if (process_id >= 100) {
char temp[4] = {0,};
sprintf(temp, "%d", process_id);
char* temp_ch = temp;
while(*temp_ch != '\0') {
*ch = *temp_ch;
temp_ch++;
ch++;
}
} else if (process_id >= 10) {
char temp[3] = {0,};
sprintf(temp, "%d", process_id);
char* temp_ch = temp;
while(*temp_ch != '\0') {
*ch = *temp_ch;
temp_ch++;
ch++;
}
} else {
char temp[2] = {0,};
sprintf(temp, "%d", process_id);
char* temp_ch = temp;
while(*temp_ch != '\0') {
*ch = *temp_ch;
temp_ch++;
ch++;
}
}
ch++;
*ch = '\0';
count++;
if (count > 5) {
if (pid > 0)
wait_pid = wait(&status);
if (wait_pid != -1)
break;
}
write(c_socket_fd, toServer, sizeof(toServer));
read(c_socket_fd, fromServer, sizeof(fromServer));
printf("From Server: %s\n", fromServer);
}
close(c_socket_fd);
}
return 0;
}
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#define PORT 8000
int main() {
int s_socket_fd, c_socket_fd;
struct sockaddr_in server_address, client_address;
socklen_t client_address_size = sizeof(client_address);
char toClient[100] = "Hello Client, this is my reply for your message No. ";
char fromClient[100];
s_socket_fd = socket(PF_INET, SOCK_STREAM, 0);
if (s_socket_fd == -1) {
printf("socket create failed!\n");
close(s_socket_fd);
return 0;
}
printf("Server Socket Created!\n");
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(PORT);
if ((bind(s_socket_fd, (struct sockaddr*) &server_address, sizeof(server_address))) == -1) {
printf("bind failed!\n");
close(s_socket_fd);
return 0;
}
if ((listen(s_socket_fd, 10) == -1)) {
printf("listen failed!\n");
close(s_socket_fd);
return 0;
}
printf("Waiting Client...\n");
client_address_size = sizeof(client_address);
c_socket_fd = accept(s_socket_fd, (struct sockaddr*) &client_address, &client_address_size);
if (c_socket_fd == -1) {
printf("accept failed!\n");
close(c_socket_fd);
close(s_socket_fd);
return 0;
}
printf("Client Connected!\n");
while(1) {
read(c_socket_fd, fromClient, sizeof(fromClient));
printf("From Client message: %s\n", fromClient);
char* count = strstr(fromClient, " from");
count--;
char* temp_ch = toClient;
while (*temp_ch != '\0') {
temp_ch++;
}
*(temp_ch-1) = *count;
write(c_socket_fd, toClient, sizeof(toClient));
}
close(c_socket_fd);
close(s_socket_fd);
return 0;
}

Linux c network programming) I cannot Connect to 2nd socket

To send simple message was working correctly in this program.
But it has some problem when I send a file.
There are another socket which has different port.
I made another socket.
But after binding, When listen method was called in server,
it just halt.
And client occurs connect error.
please let me know how can I fix it.
server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/_default_fcntl.h>
#include <sys/reent.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <string.h>
#include <grp.h>
#include <dirent.h>
#include <pwd.h>
void error_handling(char *message);
void inst_list();
void inst_pwd();
void inst_cwd(char *target);
void inst_nlst();
void inst_dele();
void inst_mkd(char *target);
void inst_handling();
void inst_rmd(char *target);
void inst_retr(char *target);
char sendMsg[500] = "";
char workingPath[500]="/";
char homePath[500]="../../usr/ftp";
struct sockaddr_in clnt_adr;
int clnt_sock;
int main(int argc, char *argv[])
{
int serv_sock, data_sock, clnt_dataSock;
char message[BUF_SIZE];
int str_len, i;
char dataPort[] = "13000";
char welcomeMsg[30] = "Hello dataPort: ";
char dataConnectMsg[30] = "Data Connected!";
char method[10] = "";
char target[100] = "";
struct sockaddr_in serv_adr;
struct sockaddr_in data_adr;
struct sockaddr_in datcl_adr;
socklen_t clnt_adr_sz;//
socklen_t datcl_adr_sz;//
if(argc!=2) {
printf("Usage : %s <port>\n", argv[0]);
exit(1);
}
serv_sock=socket(PF_INET, SOCK_STREAM, 0);
data_sock = socket(PF_INET, SOCK_STREAM,0);
if(serv_sock==-1)
error_handling("socket() error");
if(data_sock == -1)
error_handling("Data socket() error");
memset(&serv_adr, 0, sizeof(serv_adr));
memset(&data_adr, 0, sizeof(data_adr));
serv_adr.sin_family=AF_INET;
serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_adr.sin_port=htons(atoi(argv[1]));
data_adr.sin_family = AF_INET;
data_adr.sin_addr.s_addr=htonl(INADDR_ANY);
data_adr.sin_port=htons(13230);
if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
error_handling("bind() error");
// if(bind(data_sock, (struct sockaddr*)&data_adr, sizeof(data_adr))==-1)
// error_handling("data bind() error");
if(listen(serv_sock, 5)==-1)
error_handling("listen() error");
// if(listen(data_sock, 5)==-1)
// error_handling("listen() error");
clnt_adr_sz=sizeof(clnt_adr);
// datcl_adr_sz=sizeof(datcl_adr);
for(i=0; i<5; i++)
{
clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz);
if(clnt_sock==-1)
error_handling("accept() error");
else
printf("Connected client %d \n", i+1);
strcat(welcomeMsg , dataPort);
write(clnt_sock, welcomeMsg, strlen(welcomeMsg));
while((str_len=read(clnt_sock, message, BUF_SIZE))!=0)
{
message[str_len] = 0;
sscanf(message, "%s %s",method, target);
if(strcmp(method, "QUIT") == 0)
{
strcat(sendMsg, "Disconnected");
write(clnt_sock, sendMsg, strlen(sendMsg));
close(clnt_sock);
}
inst_handling(method, target);
write(clnt_sock, sendMsg, strlen(sendMsg));
memset(method, 0 , sizeof(char)*10);
memset(target, 0 , sizeof(char)*100);
memset(sendMsg, 0, sizeof(char)*500);
}
}
close(serv_sock);
return 0;
}
void inst_handling(char *method, char *target)
{
char cpyMessage[2048] = "";
char *token;
char protocol[100];
char host[200];
if(strcmp(method,"PWD") == 0)//작업 디렉토리 표시
inst_pwd();
else if(strcmp(method, "CWD") == 0)//작업 디렉토리 변경
inst_cwd(target);
else if(strcmp(method, "LIST") == 0)//원격지 파일 목록 보기
inst_list();
else if(strcmp(method, "NLST") == 0)///원격지 디렉토리 목록 보기
inst_nlst();
// else if(strcmp(method, "STOR") == 0)//원격지에 파일 저장
// inst_put(target,body);
else if(strcmp(method, "RETR") == 0)//원격지 파일 가져오기
inst_retr(target);
else if(strcmp(method, "DELE") == 0)//원격지 파일 삭제
inst_dele(target);
else if(strcmp(method, "MKD") == 0)//원격지 디렉토리 생성
inst_mkd(target);
else if(strcmp(method, "RMD") == 0)//원격지 디렉토리 제거
inst_rmd(target);
else
{
fputs("\n\n nowhere", stderr);
fputc('\n', stderr);
strcat(sendMsg, "Wrong Message");
}
}
void inst_pwd()
{
strcat(sendMsg,"Working Directory : ");
strcat(sendMsg, workingPath);
return;
}
void inst_cwd(char *target)
{
char fullPath[500] = "";
strcat(fullPath, homePath);
strcat(fullPath, target);
DIR *dir_ptr;
if ( ( dir_ptr = opendir( fullPath ) ) == NULL )
{
strcat(sendMsg, "Please enter correct path");
return;
}
memset(workingPath, 0 , sizeof(char)*500);
strcat(workingPath, target);
strcat(sendMsg, workingPath);
return;
}
void inst_list()
{
char fileList[200] = "";
char fullPath[500] = "";
strcat(fullPath, homePath);
strcat(fullPath, workingPath);
DIR *dir_ptr;
struct dirent *direntp; /* each entry */
struct stat info;
if ( ( dir_ptr = opendir( fullPath ) ) == NULL )
printf("ls1: cannot open %s\n", fullPath);
else
{
while ( ( direntp = readdir( dir_ptr ) ) != NULL )
{
if( stat(fullPath, &info) != -1 )
{
if(direntp->d_type != DT_DIR)
{
strcat(fileList, direntp->d_name);
strcat(fileList, "\n");
}
}
}
closedir(dir_ptr);
}
strcat(sendMsg,"File List : \n");
strcat(sendMsg,fileList);
return;
}
void inst_nlst()
{
char fileList[200] = "";
char fullPath[500] = "";
strcat(fullPath, homePath);
strcat(fullPath, workingPath);
DIR *dir_ptr;
struct dirent *direntp; /* each entry */
struct stat info;
if ( ( dir_ptr = opendir( fullPath ) ) == NULL )
printf("ls1: cannot open %s\n", fullPath);
else
{
while ( ( direntp = readdir( dir_ptr ) ) != NULL )
{
if( stat(fullPath, &info) != -1 )
{
if(direntp->d_type == DT_DIR)
{
strcat(fileList, direntp->d_name);
strcat(fileList, "\n");
}
}
}
closedir(dir_ptr);
}
strcat(sendMsg,"Directory List : \n");
strcat(sendMsg,fileList);
return;
}
void inst_dele(char *target)
{
char inst[1024] = "";
char path[1024] = "";
FILE *file = NULL;
mode_t file_mode;
struct stat file_info;
strcat(path, homePath);
strcat(path, target);
if(stat(path,&file_info) == -1)
{
strcat(sendMsg, "No such a file\n");
return;
}
file_mode = file_info.st_mode;
if (S_ISDIR(file_mode))
{//디렉토리 파일인 경우
strcat(sendMsg, "Error: The target is Directory\n");
return;
}
else if (S_ISREG(file_mode))
{//일반 파일인 경우
strcat(inst, "rm ");
strcat(inst, path);
if( system(inst) != -1 )
strcat(sendMsg, "The file is removed");
else
strcat(sendMsg, "Fail to remove the file\n");
return;
}
}
void inst_rmd(char *target)
{
char inst[1024] = "";
char path[1024] = "";
FILE *file = NULL;
mode_t file_mode;
struct stat file_info;
strcat(path, homePath);
strcat(path, target);
if(stat(path,&file_info) == -1)
{
strcat(sendMsg, "No such a file\n");
return;
}
file_mode = file_info.st_mode;
if (S_ISDIR(file_mode))//디렉토리 파일인 경우
{
int n=0;
struct dirent* d;
DIR* dir = opendir(path);
while((d = readdir(dir))!=NULL) n++;
if(n>2)
{
strcat(sendMsg, "The Directory is not empty\n");
return;
}
closedir(dir);
strcat(inst, "rmdir ");
strcat(inst, path);
if( system(inst) != -1 )
strcat(sendMsg, "The directory is removed");
else
strcat(sendMsg, "Fail to remove the Directory\n");
return;
}
else if (S_ISREG(file_mode))
{//일반 파일인 경우
strcat(sendMsg, "Error: The target is File\n");
return;
}
}
void inst_mkd(char *target)
{
char path[100] = "";
char inst[200] = "";
strcat(path, homePath);
strcat(path, target);//home path와 사용자가 입력한 path를 더해준다
strcat(inst, "mkdir -p ");//중간 폴더까지 모두 생성하도록 -p 옵션 사용
strcat(inst, path);
if(system(inst) != -1)
{
strcat(sendMsg, "The Directory is created");
}
return;
}
void inst_retr(char *target)
{
int read_cnt;
char buf[BUF_SIZE];
FILE * fp;
fp=fopen("../../usr/ftp/test.c", "rb");
while(1)
{
read_cnt=fread((void*)buf, 1, BUF_SIZE, fp);
if(read_cnt<BUF_SIZE)
{
write(clnt_sock, buf, read_cnt);
break;
}
write(clnt_sock, buf, BUF_SIZE);
}
puts("fin file data");
fclose(fp);
strcat(sendMsg,"END");
}
//int inst_delete(char *target)
//{
// char inst[1024] = "";
// char path[1024] = "../../usr/http";
// FILE *file = NULL;
// mode_t file_mode;
// struct stat file_info;
//
// strcat(path, target);
//
// if(stat(path,&file_info) == -1)
// {
// strcat(sendMessage, "HTTP/1.1 404 Not Found\n");
// return 0;
// }
//
// file_mode = file_info.st_mode;
// if (S_ISDIR(file_mode))
// {//디렉토리 파일인 경우
// strcat(inst, "rm -rf ");
// strcat(inst, path);
// system(inst);
// strcat(sendMessage, "HTTP/1.1 200 OK\n");
// return 0;
// }
// else if (S_ISREG(file_mode))
// {//일반 파일인 경우
// strcat(inst, "rm -f ");
// strcat(inst, "/usr/http");
// strcat(inst, path);
// system(inst);
// strcat(sendMessage, "HTTP/1.1 200 OK\n");
// return 0;
// }
//}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
module for File Transfer
void inst_retr(char *target)
{
data_sock = socket(PF_INET, SOCK_STREAM,0);
if(data_sock == -1)
error_handling("Data socket() error");
memset(&data_adr, 0, sizeof(data_adr));
data_adr.sin_family = AF_INET;
data_adr.sin_addr.s_addr=htonl(INADDR_ANY);
data_adr.sin_port=htons(12501);
if(bind(data_sock, (struct sockaddr*)&data_adr, sizeof(data_adr))==-1)
error_handling("data bind() error");
else
error_handling("bind ok");
if(listen(data_sock, 5)==-1)
error_handling("listen() error");
datcl_adr_sz=sizeof(datcl_adr);
clnt_sock=accept(data_sock, (struct sockaddr*)&datcl_adr, &datcl_adr_sz);
if(clnt_sock==-1)
error_handling("accept() error");
else
printf("Connected data client \n");
int read_cnt;
char buf[BUF_SIZE];
char eof = EOF;
FILE * fp;
fp=fopen("../../usr/ftp/test.c", "rb");
while(1)
{
read_cnt=fread((void*)buf, 1, BUF_SIZE, fp);
if(read_cnt<BUF_SIZE)
{
write(clnt_sock, buf, read_cnt);
break;
}
write(clnt_sock, buf, BUF_SIZE);
puts("file data");
}
shutdown(clnt_sock, SHUT_WR);
puts("fin file data");
fclose(fp);
strcat(sendMsg,"END");
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define BUF_SIZE 1024
void error_handling(char *message);
void inst_retr();
int sock;
int main(int argc, char *argv[])
{
int datasock;
char message[BUF_SIZE];
char tmp[BUF_SIZE];
char dataMsg[BUF_SIZE];
char method[BUF_SIZE];
char target[BUF_SIZE];
int str_len;
struct sockaddr_in serv_adr, data_adr;
if(argc!=3) {
printf("Usage : %s <IP> <port>\n", argv[0]);
exit(1);
}
sock=socket(PF_INET, SOCK_STREAM, 0);
datasock=socket(PF_INET, SOCK_STREAM, 0);
if(sock==-1)
error_handling("socket() error");
if(datasock==-1)
error_handling("Data socket() error");
memset(&serv_adr, 0, sizeof(serv_adr));
memset(&data_adr, 0, sizeof(serv_adr));
serv_adr.sin_family=AF_INET;
serv_adr.sin_addr.s_addr=inet_addr(argv[1]);
serv_adr.sin_port=htons(atoi(argv[2]));
if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
error_handling("connect() error!");
else
puts("Connected...........");
// data_adr.sin_family=AF_INET;
// data_adr.sin_addr.s_addr=htons(atoi(argv[1]));
// data_adr.sin_port=htons(13230);
//
// if(connect(datasock, (struct sockaddr*)&data_adr, sizeof(data_adr)) == -1)
// error_handling("data connect() error!");
// else
// puts("Connected.....data...");
str_len=read(sock, message, BUF_SIZE-1);
message[str_len]=0;
printf("%s\n", message);
while(1)
{
fputs("Input message(Q to quit): ", stdout);
fgets(message, BUF_SIZE, stdin);
message[strlen(message)-1] = 0;
if(strcmp(message,"QUIT") == 0)
break;
strcpy(tmp,message);
sscanf(tmp, "%s %s",method, target);
if(strcmp(method, "RETR") == 0)
{
write(sock, message, strlen(message));
inst_retr();
str_len=read(sock, message, BUF_SIZE-1);
message[str_len]=0;
printf("Message from server: %s\n", message);
memset(message, 0, sizeof(char)*BUF_SIZE);
memset(method, 0, sizeof(char)*BUF_SIZE);
memset(target, 0, sizeof(char)*BUF_SIZE);
continue;
}
// if(strcmp(message,"data") == 0)
// {
// write(sock, message, strlen(message));
//
//
// str_len=read(datasock, message, BUF_SIZE-1);
// message[str_len]=0;
// printf("Message from server: %s", message);
//
//
// }
write(sock, message, strlen(message));
str_len=read(sock, message, BUF_SIZE-1);
message[str_len]=0;
printf("Message from server: %s\n", message);
memset(message, 0, sizeof(char)*BUF_SIZE);
memset(method, 0, sizeof(char)*BUF_SIZE);
memset(target, 0, sizeof(char)*BUF_SIZE);
}
close(sock);
return 0;
}
void inst_retr()
{
char buf[BUF_SIZE];
int read_cnt;
FILE *fp;
fp=fopen("../../usr/ftp/receive.dat", "wb");
while((read_cnt=read(sock, buf, BUF_SIZE ))!=0)
fwrite((void*)buf, 1, read_cnt, fp);
puts("Received file data");
fclose(fp);
return;
}
void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
module for file Recieving
void inst_retr()
{
datasock=socket(PF_INET, SOCK_STREAM, 0);
if(datasock==-1)
error_handling("Data socket() error");
if(connect(datasock, (struct sockaddr*)&data_adr, sizeof(data_adr)) == -1)
error_handling("data connect() error!");
else
puts("Connected.....data...");
char buf[BUF_SIZE];
int read_cnt;
FILE *fp;
fp=fopen("../../usr/ftp/receive.dat", "wb");
while((read_cnt=read(sock, buf, BUF_SIZE ))!=0)
fwrite((void*)buf, 1, read_cnt, fp);
puts("Received file data");
fclose(fp);
return;
}

Using IPC Sys V

i have a server and a client and want to send a file from the client to the server, by using Sys V IPC. My Problem is the sending of the file, the server is creating the file but than stops at msgrcv_3 Invalid argument (last do while in the server). Maybe somebody have an idea.
Snippet of Server:
while(1){
int ausgabe=0;
/* Messageq */
if ((msqid = msgget(server_key, IPC_CREAT|IPC_EXCL|0666)) < 0){
perror("msgget_1");
exit(EXIT_FAILURE);
}
/* Message Empfangen */
if((msreturn = msgrcv(msqid, (void*)&name, sizeof(struct name),0,0))<0){
perror("msgrcv_1");
exit(EXIT_FAILURE);
}
result.exists = FileExists(name.file_name);
printf("%d\n", result.exists);
/* Message Versenden*/
if((msreturn = msgsnd(msqid, (void*)&result, sizeof(struct result),0))<0){
perror("msgsnd_1");
exit(EXIT_FAILURE);
}
if(result.exists == 42){
if((msreturn = msgrcv(msqid, (void*)&data, sizeof(struct data),0,0))<0){
perror("msgrcv_2");
exit(EXIT_FAILURE);
}
creatfile = open(data.file_name, O_WRONLY | O_CREAT| O_EXCL , 0);
if(creatfile == -1){
perror("creratfile");
exit(EXIT_FAILURE);
}
do{
if(msgrcv(msqid, (void*)&msg_body, sizeof(struct msg_body),0,0)<0){
perror("msgrcv_3");
exit(EXIT_FAILURE);
}
buff_blub = write(creatfile, &msg_body.buffer, msg_body.bufsize);
if (buff_blub < 0){
perror("write");
exit(EXIT_FAILURE);
}
ausgabe = ausgabe+msg_body.bufsize;
}
while(ausgabe != data.datasize);
chmod(data.file_name, 0644);
}
}
Snippet of the Client:
strncpy(name.file_name, argv[2], sizeof(name.file_name) - 1);
/* Message Versenden*/
if((msreturn = msgsnd(msqid, (void*)&name, sizeof(struct name),0))<0){
perror("msgsnd");
exit(EXIT_FAILURE);
}
/* Message Empfangen */
if((msreturn = msgrcv(msqid, (void*)&result, sizeof(struct result),0,0))<0){
perror("msgrcv");
exit(EXIT_FAILURE);
}
if(result.exists == 1){
puts("File already exists");
exit(EXIT_FAILURE);
}
else if(result.exists == 42){
file_read = open(argv[1], O_RDONLY);
if (file_read > 0){
if (fstat(file_read, &sb)==-1){
perror("fstat");
return EXIT_FAILURE;
}
strncpy(data.file_name, argv[2], sizeof(data.file_name) - 1);
data.datasize = sb.st_size;
data.c_pid = getpid();
if((msreturn = msgsnd(msqid, (void*)&data, sizeof(struct data),0))<0){
perror("msgsnd");
exit(EXIT_FAILURE);
}
while((file_buffer = read (file_read, &msg_body.buffer, BUF_SIZE)) > 0){
msg_body.bufsize = file_buffer;
msg_body.prio = 2;
if((msreturn = msgsnd(msqid, (void*)&msg_body, sizeof(struct msg_body),0))<0){
perror("msgsnd");
exit(EXIT_FAILURE);
}
}
close(file_read);
}
}
return 1;
}
the structur:
#include <unistd.h>
#if !defined(__MSGBSP_H)
#define __MSGBSP_H
#define BUF_SIZE 1024
struct data {
char file_name[255];
ssize_t datasize;
long c_pid;
};
struct name {
char file_name[255];
};
struct result {
int exists;
};
struct header {
int size;
};
struct msg_body {
long prio;
ssize_t bufsize;
char buffer[BUF_SIZE];
};
#endif

Socket select don't work

i don't know why the select function don't return any result.
I put the server in execution with this command:
./server 5555
and i try to send any character from another terminal, using:
nc 127.0.0.1 5555
and
any string to send
This is the source code of the server.c
#include <stdlib.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <errno.h>
#define MAXSIZE 1000
int main(int argc, char **argv) {
int socketfd, connectedfd, maxfd;
int ris, i, len, ris1, sent, opt;
struct sockaddr_in serverS, clientS;
short int localServerPort;
fd_set rdfs, wrfs;
char buffer[MAXSIZE];
if (argc != 2) {
printf("necessario un parametro PORTNUMBER");
exit(1);
} else {
localServerPort = atoi(argv[1]);
}
socketfd = socket(AF_INET, SOCK_STREAM, 0);
if (socketfd < 0) {
printf("socket() error\n");
exit(1);
}
opt = 1;
ris = setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt));
if (ris < 0) {
printf ("setsockopt() SO_REUSEADDR failed, Err: %d \"%s\"\n", errno,strerror(errno));
exit(1);
}
memset(&serverS, 0, sizeof(serverS));
serverS.sin_family = AF_INET;
serverS.sin_addr.s_addr = htonl(INADDR_ANY);
serverS.sin_port = htons(localServerPort);
ris = bind(socketfd, (struct sockaddr*)&serverS, sizeof(serverS));
if (ris < 0) {
printf("bind() error");
exit(1);
}
ris = listen(socketfd, 10);
if (ris < 0) {
printf("listen() error");
exit(1);
}
len = sizeof(clientS);
connectedfd = accept(socketfd, (struct sockaddr*)&clientS, &len);
if (connectedfd < 0) {
printf("accept() error");
exit(1);
} else {
printf("Connesso con: %s:%d - descrittore: %d\n", inet_ntoa(clientS.sin_addr), ntohs(clientS.sin_port), connectedfd);
}
fd_set tempset;
FD_ZERO(&rdfs);
//FD_ZERO(&wrfs);
FD_SET(connectedfd, &rdfs);
maxfd = connectedfd + 1;
while (1) {
printf("Select...\n");
ris = select(connectedfd, &rdfs, NULL, NULL, NULL);
printf("test\n");
if (ris == 0) {
printf("select() timeout error\n");
} else if (ris < 0 && errno != EINTR) {
printf("select() error\n");
} else if (ris > 0) {
printf("test ris > 0\n");
for (i = 0; i < maxfd+1; i++) {
if (FD_ISSET(i, &rdfs)) {
do {
ris = recv(i, buffer, MAXSIZE, 0);
} while (ris == -1 && errno == EINTR);
if (ris > 0) {
buffer[ris] = 0;
printf("Echoing: %s\n", buffer);
sent = 0;
do {
ris1 = send(i, buffer+sent, ris-sent, MSG_NOSIGNAL);
if (ris1 > 0)
sent += ris1;
else if (ris1 < 0 && errno != EINTR);
break;
} while (ris > sent);
}
else if (ris == 0) {
close(i);
FD_CLR(i, &rdfs);
}
else {
printf("Error in recv(): %s\n", strerror(errno));
}
}
}
}
}
return(0);
}
Why the execution remain locked at "Select...\n"?
Thanks to all!
From http://linux.die.net/man/2/select, the first param passed should be the highest-numbered file descriptor in any of the three sets (read/write/exception), plus 1. I would try the following:
ris = select(connectedfd+1, &rdfs, NULL, NULL, NULL);

popen2: reading works, writing doesn't

The following function executes a process, returns its PID and provides file descriptors for reading and writing:
pid_t popen2(const char **command, int *infp, int *outfp)
{
int p_stdin[2], p_stdout[2];
pid_t pid;
if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0) {
return -1;
}
pid = fork();
if (pid < 0) {
return pid;
} else if (pid == 0) {
close(p_stdin[WRITE]);
dup2(p_stdin[READ], READ);
close(p_stdout[READ]);
dup2(p_stdout[WRITE], WRITE);
execvp(*command, command);
}
if (infp == NULL) {
close(p_stdin[WRITE]);
} else {
*infp = p_stdin[WRITE];
}
if (outfp == NULL) {
close(p_stdout[READ]);
} else {
*outfp = p_stdout[READ];
}
return pid;
}
I call the above function with
pid = popen2(..., &in, &out);
and read from the file descriptor out with
nBytes = read(out, line, sizeof(line));
and what I read makes perfect sense. It is the output normally displayed on the console. However, when I try to write a command to the program which it would normally receive via the console with
nBytes = write(in, cmd, strlen(cmd)+1);
nothing happens. The program shows no reaction whatsoever.
What am I missing here?
I did change it a bit, but it works now. Remove the fprintf(stderr,... after verification:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#define READ_END 0
#define WRITE_END 1
pid_t popen2(const char **command, int fdarray[]);
pid_t popen2(const char **command, int fdarray[])
{
int p_stdin[2], p_stdout[2];
pid_t pid;
int rc;
if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0) {
return -1;
}
pid = fork();
if (pid < 0) {
return pid;
} else if (pid == 0) {
close(p_stdin[WRITE_END]);
dup2(p_stdin[READ_END], STDIN_FILENO);
close(p_stdin[READ_END]);
close(p_stdout[READ_END]);
dup2(p_stdout[WRITE_END], STDOUT_FILENO);
close(p_stdout[WRITE_END]);
rc = execvp(*command, command);
_exit(EXIT_FAILURE);
}
close(p_stdout[WRITE_END]);
close(p_stdin[READ_END]);
if (fdarray == NULL) {
close(p_stdin[WRITE_END]);
close(p_stdout[READ_END]);
} else {
fdarray[READ_END] = p_stdout[READ_END];
fdarray[WRITE_END] = p_stdin[WRITE_END];
}
return pid;
}
#define BUFF_SIZE 1024
struct buff {
size_t used;
size_t size;
char data[BUFF_SIZE];
}
ibuf = {0,BUFF_SIZE,}
, obuf = {0,BUFF_SIZE,}
;
int readbuff(int fd, struct buff *bp);
int writebuff(int fd, struct buff *bp);
int readbuff(int fd, struct buff *bp)
{
size_t done;
int rc=0;
for (done=0; bp->used < bp->size; bp->used+=rc, done+=rc) {
if (done) break;
fprintf(stderr, "Read(%d,%zu)\n", fd, bp->size - bp->used );
rc = read(fd, bp->data+bp->used, bp->size - bp->used);
if (rc== -1) switch (errno) {
#if (EWOULDBLOCK != EAGAIN)
case EWOULDBLOCK:
#endif
case EAGAIN:
case EINTR: rc=0; continue;
default:
fprintf(stderr, "Error on readbuff: %d: %s\n", errno, strerror(errno));
goto failed;
}
fprintf(stderr, "Readbuff(%d) := %d\n", fd, rc);
if (rc==0) { rc = -1; break; }
}
failed:
return done ? done : rc;
}
int writebuff(int fd, struct buff *bp)
{
size_t done;
int rc= 0;
for (done=0; done < bp->used ; done+=rc) {
if (done) break;
fprintf(stderr, "Write(%d,%zu)\n", fd, bp->used - done);
rc = write(fd, bp->data+done, bp->used - done);
if (rc== -1) switch (errno) {
#if (EWOULDBLOCK != EAGAIN)
case EWOULDBLOCK:
#endif
case EINTR:
case EAGAIN:rc=0; continue;
default:
fprintf(stderr, "Error on writebuff: %d: %s\n", errno, strerror(errno));
goto failed;
}
fprintf(stderr, "Writebuff(%d) := %d\n", fd, rc);
if (rc==0) { rc = -1; break; }
}
failed:
if (done == bp->used ) bp->used =0;
else { memmove(bp->data, bp->data+done, bp->used - done); bp->used -= done; }
return done ? done : rc;
}
int main (void)
{
int pipes[2] = {-1,-1};
int rc1, rc2,err;
char *commands[] = { "tee", "teapot", NULL};
// signal(SIGCHLD, SIG_IGN);
// signal(SIGPIPE, SIG_IGN);
rc1 = popen2( commands, pipes);
err = errno;
fprintf(stderr, "Rc=%d:%d(%s) pipes[0]=%d, pipes[1]=%d\n"
, rc1 , rc1 == -1 ? err : 0
, strerror(rc1 == -1?err:0)
, pipes[0]
, pipes[1]
);
if (rc1 == -1) return EXIT_FAILURE;
while(1) {
fprintf(stderr, "#----------------------------------------\n" );
rc1 = readbuff(STDIN_FILENO, &ibuf);
#if 1
if (rc1 == -1 && ibuf.used ==0) {
fprintf(stderr, "Rc1=%d Close %d\n", rc1, pipes[WRITE_END]);
close(pipes[WRITE_END]);
}
else
#endif
writebuff(pipes[WRITE_END] , &ibuf);
rc2 = readbuff(pipes[READ_END] , &obuf);
writebuff(STDOUT_FILENO, &obuf);
fprintf(stderr, "Rc=%d/%d Ibuf[0]=%zu/%zu, Obuf[0]=%zu/%zu\n"
, rc1, rc2
, ibuf.used, ibuf.size
, obuf.used, obuf.size
);
if (rc1 < 0 && rc2 < 0) break;
}
wait(NULL);
return 0;
}

Resources