Added the check for a pid file (syslog.pid by default).
#include <unistd.h> // Per les crides a fitxer
#include <stdio.h> // Per l'I/O de stdin/stdout
#include <errno.h> // Pels errors de les crides a fitxer
#include <string.h> // Per strerror()
#include <stdlib.h> // Per abort()
#include <sys/types.h> // Per crides de fitxer
#include <sys/socket.h> // Per les macros bool,true,false
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <assert.h> // Per assert()
#include <sys/select.h> // Pel select()
#include "rfc3164.h"
#include "syslog.h"
#define LISTEN_QUEUE = 10;
void show_help(const char * restrict program)
{
printf("Usage: %s <udp_port> (negative for enable ipv6)\n", program);
}
int listen_ipv6(int port)
{
int socket_ipv6;
struct sockaddr_in6 source_ipv6;
int result;
int on=1;
socket_ipv6 = socket(PF_INET6, SOCK_DGRAM, 0);
if (socket_ipv6 == -1)
{
fprintf(stderr, "IPv6 socket failed.\n");
abort();
}
/* Fem que poguem reutilitzar l'adreça encara que no s'hagi acabat
el timeout després de tancar-se la connexió */
if (setsockopt(socket_ipv6, SOL_SOCKET, SO_REUSEADDR,
(char *)&on,sizeof(on)) < 0)
{
fprintf(stderr, "IPv6 setsockopt() failed: %s.\n",
strerror(errno));
abort();
}
/* IPv6 listen address */
memset(&source_ipv6, 0, sizeof(source_ipv6));
source_ipv6.sin6_family = AF_INET6;
source_ipv6.sin6_flowinfo = 0;
source_ipv6.sin6_port = htons(port);
source_ipv6.sin6_addr = in6addr_any;
result = bind(socket_ipv6, (struct sockaddr *) &source_ipv6,
sizeof(source_ipv6));
assert(result == 0);
/*
result = listen(socket_ipv6, const_listen_queue);
if (result != 0)
{
printf("Error in listen() ipv6: %s\n", strerror(errno));
abort();
}
*/
return socket_ipv6;
}
int listen_ipv4(int port)
{
int socket_ipv4;
struct sockaddr_in source_ipv4;
int result;
int on=1;
socket_ipv4 = socket(PF_INET, SOCK_DGRAM, 0);
if (socket_ipv4 == -1)
{
fprintf(stderr, "IPv4 socket not supported.\n");
abort();
}
/* Fem que poguem reutilitzar l'adreça encara que no s'hagi acabat
el timeout després de tancar-se la connexió */
if (setsockopt(socket_ipv4, SOL_SOCKET, SO_REUSEADDR,
(char *)&on,sizeof(on)) < 0)
{
fprintf(stderr, "IPv4 setsockopt() failed: %s.\n",
strerror(errno));
abort();
}
/* IPv4 listen address */
memset(&source_ipv4, 0, sizeof(source_ipv4));
source_ipv4.sin_family = AF_INET;
source_ipv4.sin_port = htons(port);
source_ipv4.sin_addr.s_addr = htonl(INADDR_ANY);
result = bind(socket_ipv4, (struct sockaddr *) &source_ipv4,
sizeof(source_ipv4));
assert(result == 0);
/*
result = listen(socket_ipv4, const_listen_queue);
if (result != 0)
{
printf("Error in listen() ipv4: %s\n", strerror(errno));
abort();
}
*/
return socket_ipv4;
}
void server_loop(const int port, const bool ipv6enabled)
{
int socket_ipv6, socket_ipv4;
fd_set listen_sockets;
struct timeval wait_time;
int result;
int size;
int high_socket;
char message[MESSAGE_LENGTH+1];
socket_ipv4 = listen_ipv4(port);
if (ipv6enabled)
socket_ipv6 = listen_ipv6(port);
/* Mirem quin és el socket més alt pel select() */
high_socket = socket_ipv4;
if (ipv6enabled && (high_socket < socket_ipv6) )
high_socket = socket_ipv6;
high_socket += 1;
result = 0;
while (result >= 0)
{
/* Establim els FDs que volem esperar al select() */
FD_ZERO(&listen_sockets);
if (ipv6enabled)
FD_SET(socket_ipv6, &listen_sockets);
FD_SET(socket_ipv4, &listen_sockets);
/* Establim el temporitzador pel select() */
wait_time.tv_sec = 5;
wait_time.tv_usec = 0;
result = select(high_socket, &listen_sockets, NULL, NULL,
&wait_time);
if (result == 0)
continue;
else if (result == -1)
{
fprintf(stderr, "Error in select(): %s\n",
strerror(errno));
abort();
}
/* Algun FD té dades... */
if (FD_ISSET(socket_ipv4, &listen_sockets))
{
size = recv(socket_ipv4, message, MESSAGE_LENGTH, 0);
process_message(message);
/* Debug */
if(!strcmp(message,"close"))
break;
write(1, message, size);
}
if (ipv6enabled && FD_ISSET(socket_ipv6, &listen_sockets))
{
size = recv(socket_ipv6, message, MESSAGE_LENGTH, 0);
process_message(message);
/* Debug */
if(!strcmp(message,"close"))
break;
write(1, message, size);
}
}
/* Closing sockets at the end */
close(socket_ipv4);
if (ipv6enabled)
close(socket_ipv6);
}
int main(int argn, char **argv)
{
int port;
bool use_ipv6 = false;
/* Processem els paràmetres d'entrada */
if (argn != 2) {
show_help(argv[0]);
return 2;
}
port=atoi(argv[1]);
/* If a port number is typed as negative, it will start
* also the ipv6 server */
if(port < 0)
{
port = -port;
use_ipv6 = true;
}
if (port < 0 || port >65535)
{
show_help(argv[0]);
return 2;
}
program_ignore_hup();
server_loop(port, use_ipv6);
return 0;
}