freeaddrinfo(save); /* done, release memory */
return sock;
}
+/****************************************************************
+ *
+ * Routine sockbind2
+ * Return a binded socket given hostname, service, and socket type
+ * Issue a SO_REUSEADDR on the socket before binding.
+ *
+ * Author: Simone Piccardi
+ * Mar. 2005
+ *
+ * $Id$
+ *
+ ****************************************************************/
+int sockbind2(char *host, char *serv, int prot, int type)
+{
+ struct addrinfo hint, *addr, *save;
+ int res;
+ int sock;
+ int opt=1;
+ char buf[INET6_ADDRSTRLEN];
+ /* initialize hint structure */
+ memset(&hint, 0, sizeof(struct addrinfo));
+ hint.ai_flags = AI_PASSIVE; /* address for binding */
+ hint.ai_family = PF_UNSPEC; /* generic address (IPv4 or IPv6) */
+ hint.ai_protocol = prot; /* protocol */
+ hint.ai_socktype = type; /* socket type */
+ res = getaddrinfo(host, serv, &hint, &addr); /* calling getaddrinfo */
+ if (res != 0) { /* on error exit */
+ fprintf(stderr, "sockbind: resolution failed:");
+// fprintf(stderr, "host %s, service %s, protocol %d", host, serv, prot);
+ fprintf(stderr, " %s\n", gai_strerror(res));
+ errno = 0; /* clear errno */
+ return -1;
+ }
+ save = addr; /* saving for freeaddrinfo */
+ while (addr != NULL) { /* loop on possible addresses */
+ /* get a socket */
+ sock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
+ if (sock < 0) { /* on error */
+ if (addr->ai_next != NULL) { /* if other addresses */
+ addr=addr->ai_next; /* take next */
+ continue; /* restart cycle */
+ } else { /* else stop */
+ perror("sockbind: cannot create socket");
+ return sock;
+ }
+ }
+ /* connect the socket */
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
+ printf("error on socket options\n");
+ return -1;
+ }
+ printf("Indirizzo %s\n", ip_ntop(addr, buf, sizeof(buf)));
+ if ( (res = bind(sock, addr->ai_addr, addr->ai_addrlen)) < 0) {
+ if (addr->ai_next != NULL) { /* if other addresses */
+ addr=addr->ai_next; /* take next */
+ close(sock); /* close socket */
+ continue; /* restart cycle */
+ } else { /* else stop */
+ perror("sockbind: cannot connect");
+ close(sock);
+ return res;
+ }
+ } else break; /* ok, we are binded! */
+ }
+ freeaddrinfo(save); /* done, release memory */
+ return sock;
+}
--- /dev/null
+/* wwwd.c
+ *
+ * Copyright (C) 2005 Simone Piccardi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/****************************************************************
+ *
+ * Program wwwd
+ * Elementary WWW server (port 80)
+ *
+ * Author: Simone Piccardi
+ * Mar. 2005
+ *
+ * Usage: wwwd -h give all info
+ *
+ * $Id$
+ *
+ ****************************************************************/
+/*
+ * Include needed headers
+ */
+#define _GNU_SOURCE
+#include <string.h> /* error strings */
+#include <sys/types.h> /* predefined types */
+#include <unistd.h> /* include unix standard library */
+#include <arpa/inet.h> /* IP addresses conversion utiliites */
+#include <sys/socket.h> /* socket library */
+#include <stdio.h> /* include standard I/O library */
+#include <time.h>
+#include <syslog.h> /* syslog system functions */
+#include <signal.h> /* signal functions */
+#include <errno.h> /* error code */
+#include <stdlib.h>
+
+#include "Gapil.h"
+
+#define BACKLOG 10
+#define MAXLINE 256
+int demonize = 1; /* daemon use option: default is daemon */
+int debugging = 0; /* debug info printing option: default is no debug */
+
+/* Subroutines declaration */
+void usage(void);
+void ServPage(int sockfd);
+void PrintErr(char * error);
+void print_headers(FILE *file);
+
+/* Program beginning */
+int main(int argc, char *argv[])
+{
+/*
+ * Variables definition
+ */
+ int list_fd, conn_fd;
+ int waiting = 0;
+ int compat = 0;
+ pid_t pid;
+ struct sockaddr_in cli_add;
+ socklen_t len;
+ char debug[MAXLINE], ipaddr[20];
+ /*
+ * Input section: decode parameters passed in the calling
+ * Use getopt function
+ */
+ int i;
+ opterr = 0; /* don't want writing to stderr */
+ while ( (i = getopt(argc, argv, "hdicw:")) != -1) {
+ switch (i) {
+ /*
+ * Handling options
+ */
+ case 'h':
+ printf("Wrong -h option use\n");
+ usage();
+ return(0);
+ break;
+ case 'i':
+ demonize = 0;
+ break;
+ case 'c':
+ compat = 1;
+ break;
+ case 'd':
+ debugging = 1;
+ break;
+ case 'w':
+ waiting = strtol(optarg, NULL, 10);
+ break;
+ case '?': /* unrecognized options */
+ printf("Unrecognized options -%c\n",optopt);
+ usage();
+ default: /* should not reached */
+ usage();
+ }
+ }
+ /* ***********************************************************
+ *
+ * Options processing completed
+ *
+ * Main code beginning
+ *
+ * ***********************************************************/
+ /* Main code begin here */
+ if (compat) { /* install signal handler */
+ Signal(SIGCHLD, HandSigCHLD); /* non restarting handler */
+ } else {
+ SignalRestart(SIGCHLD, HandSigCHLD); /* restarting handler */
+ }
+ /* create and bind socket */
+ if ( (list_fd = sockbind2(argv[optind], "www", 6, SOCK_STREAM)) < 0) {
+ return 1;
+ }
+ /* release privileges and go daemon */
+ if (setgid(65534) !=0) { /* first give away group privileges */
+ perror("cannot give away group privileges");
+ exit(1);
+ }
+ if (setuid(65534) !=0) { /* and only after user ... */
+ perror("cannot give away user privileges");
+ exit(1);
+ }
+ if (demonize) { /* go daemon */
+ openlog(argv[0], 0, LOG_DAEMON); /* open logging */
+ if (daemon(0, 0) != 0) {
+ perror("cannot start as daemon");
+ exit(1);
+ }
+ }
+ /* main body */
+ if (listen(list_fd, BACKLOG) < 0 ) {
+ PrintErr("listen error");
+ exit(1);
+ }
+ if (waiting) sleep(waiting);
+ /* handle echo to client */
+ while (1) {
+ /* accept connection */
+ len = sizeof(cli_add);
+ while (((conn_fd = accept(list_fd, (struct sockaddr *)&cli_add, &len))
+ < 0) && (errno == EINTR));
+ if (conn_fd < 0) {
+ PrintErr("accept error");
+ exit(1);
+ }
+ if (debugging) {
+ inet_ntop(AF_INET, &cli_add.sin_addr, ipaddr, sizeof(ipaddr));
+ snprintf(debug, MAXLINE, "Accepted connection form %s\n", ipaddr);
+ if (demonize) {
+ syslog(LOG_DEBUG, debug);
+ } else {
+ printf("%s", debug);
+ }
+ }
+ /* fork to handle connection */
+ if ( (pid = fork()) < 0 ){
+ PrintErr("fork error");
+ exit(1);
+ }
+ if (pid == 0) { /* child */
+ close(list_fd); /* close listening socket */
+ ServPage(conn_fd); /* handle echo */
+ if (debugging) {
+ snprintf(debug, MAXLINE, "Closed connection %s\n", ipaddr);
+ if (demonize) {
+ syslog(LOG_DEBUG, debug);
+ } else {
+ printf("%s", debug);
+ }
+ }
+ exit(0);
+ } else { /* parent */
+ close(conn_fd); /* close connected socket */
+ }
+ }
+ /* normal exit, never reached */
+ exit(0);
+}
+/*
+ * routine to print usage info and exit
+ */
+void usage(void)
+{
+ printf("Elementary echo server\n");
+ printf("Usage:\n");
+ printf(" echod [-h] \n");
+ printf(" -h print this help\n");
+ printf(" -d write debug info\n");
+ printf(" -i use interactively\n");
+ printf(" -c disable BSD semantics\n");
+ printf(" -w N wait N sec. before calling accept\n");
+ exit(1);
+}
+/*
+ * routine to handle echo for connection
+ */
+void ServPage(int sockfd)
+{
+ char buffer[MAXLINE];
+ char outbuf[1024];
+ FILE *sock, *file;
+ char *line, *copy, *method, *ptr, *filename, *version;
+ char *methods[] = { "GET", "PUT", NULL };
+ char *codes[] = {
+ "200 OK",
+ "404 Not Found",
+ NULL
+ };
+ int nleft;
+ int i, j;
+
+ sock = fdopen(sockfd, "w+");
+ /* main loop, reading 0 char means client close connection */
+ line = fgets(buffer, MAXLINE, sock);
+ copy = strndupa(line, MAXLINE);
+
+ if (line == NULL) {
+ PrintErr("Errore in lettura");
+ return;
+ }
+ if ((method = strtok_r(copy, " ", &ptr)) == NULL) {
+ PrintErr("Non ho trovato il metodo");
+ return;
+ }
+ if ((filename = strtok_r(NULL, " ", &ptr)) == NULL) {
+ PrintErr("Non ho trovato il file");
+ return;
+ }
+ if ((version = strtok_r(NULL, " ", &ptr)) == NULL) {
+ PrintErr("Non ho trovato la versione");
+ return;
+ }
+ printf("metodo %s -- file %s -- versione %s\n", method, filename, version);
+ i = 0;
+ while ( (ptr = methods[i]) != NULL) {
+ if ( (strncmp(ptr, method, strlen(ptr)) == 0)) {
+ break;
+ }
+ i++;
+ }
+ if (i>=2) {
+ printf("No method %s found\n", method);
+ return;
+ }
+
+ while (strcmp(line,"\r\n")) {
+ line = fgets(buffer, MAXLINE, sock);
+ printf("letto: %s\n", line);
+ }
+
+ if ( (file = fopen(filename, "r")) == NULL) {
+ printf("file %s", filename);
+ perror("Error opening");
+ fprintf(sock, "HTTP/1.0 %s\n", codes[1]);
+ print_headers(sock);
+ return;
+ }
+ fprintf(sock, "HTTP/1.0 %s\n", codes[0]);
+ //PrintHeader(sock);
+ print_headers(sock);
+
+ j = 0;
+ while (!feof(file)) {
+ printf("Loop %d\n", j++);
+ if ( (nleft = full_fread(file, outbuf, 1024)) != 0) {
+ if (ferror(file)) {
+ printf("Errore in lettura");
+ return;
+ }
+ }
+ printf("Loop %d rimasti %d\n", j, nleft);
+ if (full_fwrite(sock, outbuf, 1024-nleft) != 0) {
+ if (ferror(file)) {
+ printf("Errore in scrittura");
+ return;
+ }
+ }
+ }
+ printf("Ok fin qui!");
+// line = fgets(buffer, MAXLINE, sock);
+ fclose(file);
+ fclose(sock);
+ return;
+}
+/*
+ * routine to print error on stout or syslog
+ */
+void PrintErr(char * error)
+{
+ if (demonize) { /* daemon mode */
+ syslog(LOG_ERR, "%s: %m", error); /* log string and error message */
+ } else {
+ perror(error);
+ }
+ return;
+}
+
+void print_headers(FILE *file)
+{
+ time_t tempo;
+
+ time(&tempo);
+ fprintf(file, "Date: %s", ctime(&tempo));
+ fprintf(file, "Server: WWWd test server\n");
+ fprintf(file, "Connection: close\n");
+ fprintf(file, "Content-Type: text/html; charset=iso-8859-1\n");
+ fprintf(file, "\n");
+ printf("Date: %s", ctime(&tempo));
+ printf("Server: WWWd test server\n");
+ printf("Connection: close\n");
+ printf("Content-Type: text/html; charset=iso-8859-1\n");
+ printf("\n");
+ return;
+}