*
* 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 <sys/types.h> /* primitive system data types */
+#include <sys/stat.h> /* file characteristics constants and functions */
+#include <stdlib.h> /* C standard library */
+#include <stdio.h> /* standard I/O library */
+#include <unistd.h> /* unix standard library */
+#include <arpa/inet.h> /* IP addresses conversion utilities */
+#include <sys/socket.h> /* socket constants, types and functions */
+#include <time.h> /* date and time constants, types and functions */
#include <syslog.h> /* syslog system functions */
-#include <signal.h> /* signal functions */
-#include <errno.h> /* error code */
-#include <stdlib.h>
+#include <signal.h> /* signal constants, types and functions */
+#include <errno.h> /* error definitions and routines */
+#include <string.h> /* C strings library */
+#include <dirent.h> /* directory operation constants and functions */
#include "Gapil.h"
+/*
+ * Function and globals definitions
+ */
#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 */
+struct code_page {
+ char * code;
+ char * name;
+ char * body;
+};
-/* Subroutines declaration */
void usage(void);
void ServPage(int sockfd);
void PrintErr(char * error);
-void print_headers(FILE *file);
-void print_err404(FILE *file, char *filename);
-void print_err400(FILE *file, char *string);
-void print_err500(FILE *file, char *string);
+void print_headers(FILE *file, struct code_page code);
+void print_error(FILE *file, struct code_page page, char * string);
-/* Program beginning */
-int main(int argc, char *argv[])
+/*
+ * Main program
+ */int main(int argc, char *argv[])
{
-/*
- * Variables definition
- */
+ /*
+ * Variables definition
+ */
int list_fd, conn_fd;
- int waiting = 0;
int compat = 0;
int reroot = 0;
+ int reuse = 1;
char * rootdir;
pid_t pid;
struct sockaddr_in cli_add;
*/
int i;
opterr = 0; /* don't want writing to stderr */
- while ( (i = getopt(argc, argv, "hdicw:r:")) != -1) {
+ while ( (i = getopt(argc, argv, "hwdicr:")) != -1) {
switch (i) {
/*
* Handling options
debugging = 1;
break;
case 'w':
- waiting = strtol(optarg, NULL, 10);
+ reuse = 0;
break;
case 'r':
- printf("chroot\n");
reroot = 1;
rootdir = optarg;
break;
SignalRestart(SIGCHLD, HandSigCHLD); /* restarting handler */
}
/* create and bind socket */
- if ( (list_fd = sockbind2(argv[optind], "www", 6, SOCK_STREAM)) < 0) {
+ if ( (list_fd = sockbindopt(argv[optind], "www", 6,
+ SOCK_STREAM, reuse)) < 0) {
return 1;
}
/* chroot if requested */
if (reroot) {
- printf("chroot to %s\n", rootdir);
if (chdir(rootdir)) {
perror("Cannot find directory to chroot");
exit(1);
PrintErr("listen error");
exit(1);
}
- if (waiting) sleep(waiting);
/* handle echo to client */
while (1) {
/* accept connection */
{
printf("Elementary echo server\n");
printf("Usage:\n");
- printf(" echod [-h] \n");
+ printf(" wwwd [-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");
+ printf(" -r /path chroot on /path\n");
exit(1);
}
/*
char outbuf[1024];
FILE *sock, *file;
char *line, *copy, *method, *ptr, *filename, *version;
- char *methods[] = { "GET", "PUT", NULL };
- char *codes[] = {
- "200 OK",
- "400 Bad Request",
- "404 Not Found",
- "500 Internal Server Error",
- NULL
+ char *methods[] = { "GET", "HEAD", NULL };
+ struct code_page codes[] = {
+ { "200", "OK", "%s"},
+ { "400", "Bad Request",
+ "Your browser sent a request that this server could not understand."
+ "<P>The request line<P>%s<P> is invalid following the protocol<P>"},
+ { "404", "Not Found",
+ "The requested URL %s was not found on this server.<P>"},
+ { "500", "Internal Server Error",
+ "We got an error processing your request.<P>Error is: %s<P>"},
+ { "405", "Method Not Allowed", "Method %s not allowed.<P>"},
+ { "403", "Forbidden", "You cannot access %s.<P>"}
};
int nleft;
- int i, j;
+ int i;
sock = fdopen(sockfd, "w+");
/* main loop, reading 0 char means client close connection */
/* parsing first line, getting method and filename */
copy = strndupa(line, MAXLINE);
if ((method = strtok_r(copy, " ", &ptr)) == NULL) {
- fprintf(sock, "HTTP/1.0 %s\n", codes[2]);
- print_headers(sock);
- print_err400(sock, line);
+ print_headers(sock, codes[1]);
+ print_error(sock, codes[1], line);
return;
}
if ((filename = strtok_r(NULL, " ", &ptr)) == NULL) {
- fprintf(sock, "HTTP/1.0 %s\n", codes[2]);
- print_headers(sock);
- print_err400(sock, line);
+ print_headers(sock, codes[1]);
+ print_error(sock, codes[1], line);
return;
}
if ((version = strtok_r(NULL, " ", &ptr)) == NULL) {
- fprintf(sock, "HTTP/1.0 %s\n", codes[2]);
- print_headers(sock);
- print_err400(sock, line);
+ print_headers(sock, codes[1]);
+ print_error(sock, codes[1], line);
return;
}
i = 0;
i++;
}
if (i>=2) {
- fprintf(sock, "HTTP/1.0 %s\n", codes[2]);
- print_headers(sock);
- print_err400(sock, line);
+ print_headers(sock, codes[4]);
+ print_error(sock, codes[4], method);
return;
}
}
if ( (file = fopen(filename, "r")) == NULL) {
- fprintf(sock, "HTTP/1.0 %s\n", codes[2]);
- print_headers(sock);
- print_err404(sock, filename);
+ if ( (errno == EACCES)||(errno == EPERM) ) {
+ print_headers(sock, codes[5]);
+ print_error(sock, codes[5], filename);
+ } else {
+ print_headers(sock, codes[2]);
+ print_error(sock, codes[2], filename);
+ }
return;
}
- fprintf(sock, "HTTP/1.0 %s\n", codes[0]);
- print_headers(sock);
-
- j = 0;
+ print_headers(sock, codes[0]);
while (!feof(file)) {
if ( (nleft = full_fread(file, outbuf, 1024)) != 0) {
if (ferror(file)) {
- fprintf(sock, "HTTP/1.0 %s\n", codes[3]);
- print_headers(sock);
- snprintf(buffer, MAXLINE, "reading %s", filename);
- print_err500(sock, buffer);
+ strncpy(buffer, strerror(errno), MAXLINE);
+ print_headers(sock, codes[3]);
+ print_error(sock, codes[3], buffer);
return;
}
}
if (full_fwrite(sock, outbuf, 1024-nleft) != 0) {
if (ferror(file)) {
- fprintf(sock, "HTTP/1.0 %s\n", codes[3]);
- print_headers(sock);
- snprintf(buffer, MAXLINE, "writing");
- print_err500(sock, buffer);
+ strncpy(buffer, strerror(errno), MAXLINE);
+ print_headers(sock, codes[3]);
+ print_error(sock, codes[3], buffer);
return;
}
}
return;
}
-void print_headers(FILE *file)
+void print_headers(FILE *file, struct code_page code)
{
time_t tempo;
+ fprintf(file, "HTTP/1.0 %s %s \n", code.code, code.name);
time(&tempo);
fprintf(file, "Date: %s", ctime(&tempo));
fprintf(file, "Server: WWWd test server\n");
return;
}
-void print_err404(FILE *file, char *filename)
-{
- fprintf(file, "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>\n");
- fprintf(file, "<BODY><H1>Not Found</H1>\nThe requested ");
- fprintf(file, "URL %s was not found on this server.<P><HR>", filename);
- fprintf(file, "<ADDRESS>WWWd by Simone Piccardi</ADDRESS></BODY></HTML>");
- return;
-}
-
-void print_err400(FILE *file, char *string)
+void print_error(FILE *file, struct code_page page, char * string)
{
- fprintf(file, "<HTML><HEAD><TITLE>404 Bad Request</TITLE></HEAD>\n");
- fprintf(file, "<BODY><H1>Bad Request</H1>\n ");
- fprintf(file, "Your browser sent a request that this server could not ");
- fprintf(file, "understand.<P>The request line<P> %s <P>", string);
- fprintf(file, "is invalid following the protocol<p><HR>");
- fprintf(file, "<ADDRESS>WWWd by Simone Piccardi </ADDRESS></BODY></HTML>");
+ fprintf(file, "<HTML><HEAD><TITLE>%s %s</TITLE></HEAD>\n",
+ page.code, page.name);
+ fprintf(file, "<BODY><H1>%s</H1>\n", page.name);
+ fprintf(file, page.body, string);
+ fprintf(file, "<HR><ADDRESS>WWWd by S. Piccardi</ADDRESS></BODY></HTML>");
return;
}
-
-void print_err500(FILE *file, char *string)
-{
- fprintf(file, "<HTML><HEAD><TITLE>500 Internal Server Error</TITLE>\n");
- fprintf(file, "</HEAD><BODY><H1>Internal Server Error</H1>\n ");
- fprintf(file, "We got an error processing your request.<P>");
- fprintf(file, "Error is: %s <P><HR>\n", string);
- fprintf(file, "<ADDRESS>WWWd by Simone Piccardi </ADDRESS></BODY></HTML>");
- return;
-}