Súbor: [Platon] / libplaton / utils / server-backend / server-backend.c (stiahnutie)
Revízia 1.3, Wed Oct 16 21:04:54 2002 UTC (21 years, 6 months ago) by nepto
Zmeny od 1.2: +30 -90
[lines]
Interactive communication implemented. Use -i switch.
Code split into several parts and redunand added into utils.c file.
server-backend2.[ch] removed, server-backed-fast.c added, they both use
the same header server-backend.h file.
README added with description and compilation notes.
|
/*
* server_backend.c - network server socketing backend
*
* (c) 2001 Ondrej Jombik <nepto@pobox.sk>
*
* History
* - 19/9/2001 - initial release
* - 20/9/2001 - minor bugfixes
* - waitpid() used as substitute of wait()
*
* TODO
* - write debug infomations to STDERR
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/* wait() */
#include <sys/wait.h>
/* struct timeval */
#include <sys/time.h>
/* signal() */
#include <signal.h>
#include "utils.h"
#include "server-backend.h"
int main(int argc, char *argv[])
{
int port;
int listen_sock;
fd_set fds;
struct client *client_first = NULL;
char **process;
if (argc < 3) {
fprintf(stderr, "Usage: %s <port> <process> <arg1> ... <argn>\n",
PROG_NAME);
return 1;
}
port = get_port(argv[1]);
if ((process = create_process_array(argc, argv, 2)) == NULL) {
perror(PROG_NAME);
return 32;
}
fake_command_line(argc, argv);
if ((listen_sock = bind_to_port(port)) == -1) {
perror(PROG_NAME);
return 16;
}
if (0) {
(void) setpgrp();
signal(SIGHUP, SIG_IGN);
}
if (1)
fcntl(listen_sock,F_SETFL,O_NDELAY);
switch (fork()) {
case -1:
perror(PROG_NAME);
return errno;
break;
case 0:
break;
default:
fprintf(stderr, "%s: accepting connections on port %d\n",
PROG_NAME, port);
return 0;
break;
}
while (1) {
int pid;
struct client *client;
struct timeval tv;
/*
for (pid = 0, client = client_first; client != NULL;
client = client->next)
pid++;
fprintf(stderr, "debug: %d active clients\n", pid);
*/
FD_ZERO(&fds);
FD_SET(listen_sock, &fds);
tv.tv_sec = 1;
tv.tv_usec = 0;
if (select(FD_SETSIZE, &fds, NULL, NULL, &tv) == -1)
continue;
if (FD_ISSET(listen_sock, &fds)) {
struct client *client_new;
struct sockaddr_in acc_addr;
unsigned int size;
int accept_sock;
struct hostent *host;
size = sizeof(struct sockaddr_in);
accept_sock = accept(listen_sock,
(struct sockaddr*) &acc_addr, &size);
if (accept_sock > 0 &&
(client_new = (struct client*)
malloc(sizeof(struct client))) != NULL) {
client_new->fd = accept_sock;
/* Geting client IP address. */
strncpy(client_new->ip,
(char*)inet_ntoa(acc_addr.sin_addr),
IP_SIZE);
client_new->ip[IP_SIZE] = '\0';
/* Geting host name. */
host = gethostbyaddr((char *)&acc_addr.sin_addr, 4, AF_INET);
if (host == NULL)
strncpy(client_new->host, client_new->ip, HOST_SIZE);
else
strncpy(client_new->host, host->h_name, HOST_SIZE);
client_new->host[HOST_SIZE] = '\0';
client_new->port = ntohs(acc_addr.sin_port);
client_new->next = NULL;
if (client_first == NULL) {
client_first = client_new;
}
else {
for (client = client_first;
client->next != NULL;
client = client->next)
;
client->next = client_new;
}
switch (pid = fork()) {
case -1:
perror(PROG_NAME);
return errno;
break;
case 0: /* child */
close(0);
dup(client_new->fd);
close(1);
dup(client_new->fd);
close(2);
dup(client_new->fd);
close(listen_sock);
/* write(client_new->fd, "----------------\n\r", 18); */
/* execvp(argv[2], argv + 2); */
execvp(process[0], process);
write(client_new->fd, "execlp() failure\n\r", 18);
break;
default: /* parent */
client_new->pid = pid;
close(client_new->fd);
break;
}
}
}
/*
* Terminated childs remove stuff.
*/
while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
for (client = client_first; client != NULL; ) {
/*
fprintf(stderr, "debug: trying to removing pid %d, comparing with %d\n", pid, client->pid);
*/
if (client->pid == pid) {
/*
fprintf(stderr, "debug: removing pid %d\n", pid);
*/
shutdown(client->fd, 2);
close(client->fd);
if (client_first != client) {
struct client* prev;
for (prev = client_first;
prev->next != client;
prev = prev->next )
;
prev->next = client->next;
free(client);
client = prev->next;
}
else {
client_first = client->next;
free(client);
client = client_first;
}
}
else {
client = client->next;
}
}
}
} /* while (1) */
return 0;
}
Platon Group <platon@platon.sk> http://platon.sk/
|