hermes

HTTP GET/HEAD-only web server for static content.
git clone git://git.francescosaccone.com/hermes
Log | Files | Refs | README | LICENSE

hermes.c (3148B)


      1 #include <grp.h>
      2 #include <pwd.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 
      7 #include "socket.h"
      8 #include "utils.h"
      9 
     10 #define DIRECTORY_INDEX_MAX_LENGTH 32
     11 #define USER_NAME_MAX_LENGTH 32
     12 #define GROUP_NAME_MAX_LENGTH 32
     13 
     14 void
     15 print_usage(char *program_name) {
     16 	print_error("usage: %s [-p port] [-i file] [-u user] [-g group]",
     17 	            program_name);
     18 }
     19 
     20 int
     21 main(int argc, char *argv[]) {
     22 	char *program_name = argv[0],
     23 	     user_name[USER_NAME_MAX_LENGTH] = "nobody",
     24 	     group_name[GROUP_NAME_MAX_LENGTH] = "nogroup",
     25 	     directory_index[DIRECTORY_INDEX_MAX_LENGTH] = "index.html";
     26 	int i, port = 80,
     27 	    server_socket_fd;
     28 	struct passwd *user;
     29 	struct group *group;
     30 
     31 	for (i = 1; i < argc; i++) {
     32 		char *argument = argv[i];
     33 
     34 		if (argument[0] != '-' ||
     35 		    argument[1] == '\0' ||
     36 		    argument[2] != '\0' ||
     37 		    i + 1 >= argc /* Argument value exists */) {
     38 			print_usage(program_name);
     39 			return 1;
     40 		}
     41 
     42 		switch (argument[1]) {
     43 		case 'p':
     44 			port = atoi(argv[i + 1]);
     45 			if (port < 1 || port > 65535) {
     46 				print_error("error: port must be between 1 and 65535.");
     47 				return 1;
     48 			};
     49 			i++;
     50 			break;
     51 		case 'i':
     52 			if (strlen(argv[i + 1]) >= DIRECTORY_INDEX_MAX_LENGTH) {
     53 				print_error("error: directory index must be less than "
     54 				            "%u characters",
     55 				            DIRECTORY_INDEX_MAX_LENGTH);
     56 			}
     57 			snprintf(directory_index,
     58 			         sizeof(directory_index),
     59 			         "%s",
     60 			         argv[i + 1]);
     61 			directory_index[sizeof(directory_index) - 1] = '\0';
     62 			i++;
     63 			break;
     64 		case 'u':
     65 			if (strlen(argv[i + 1]) >= USER_NAME_MAX_LENGTH) {
     66 				print_error("error: the user name must be less than "
     67 				            "%u characters",
     68 				            USER_NAME_MAX_LENGTH);
     69 			}
     70 			strncpy(user_name, argv[i + 1], sizeof(user_name) - 1);
     71 			user_name[sizeof(user_name) - 1] = '\0';
     72 			i++;
     73 			break;
     74 		case 'g':
     75 			if (strlen(argv[i + 1]) >= GROUP_NAME_MAX_LENGTH) {
     76 				print_error("error: the group name must be less than "
     77 				            "%u characters",
     78 				            GROUP_NAME_MAX_LENGTH);
     79 			}
     80 			strncpy(group_name, argv[i + 1], sizeof(group_name) - 1);
     81 			group_name[sizeof(group_name) - 1] = '\0';
     82 			i++;
     83 			break;
     84 		default:
     85 			print_usage(program_name);
     86 			return 1;
     87 		}
     88 	}
     89 
     90 	user = getpwnam(user_name);
     91 	group = getgrnam(group_name);
     92 
     93 	if (user == NULL) {
     94 		print_error("error: user %s does not exist.", user_name);
     95 		return 1;
     96 	}
     97 
     98 	if (group == NULL) {
     99 		print_error("error: group %s does not exist.", group_name);
    100 		return 1;
    101 	}
    102 
    103 	server_socket_fd = create_socket(port);
    104 
    105 	while (1) {
    106 		int client_socket_fd,
    107 		    buffer_size = 104857600 * sizeof(char); /* i.e. 100 MiB */
    108 		char *buffer = malloc(buffer_size);
    109 
    110 		client_socket_fd = accept_client(server_socket_fd);
    111 
    112 		if (client_socket_fd == -1) {
    113 			free(buffer);
    114 			close_socket(client_socket_fd);
    115 			continue;
    116 		}
    117 
    118 		if (read_client_request(client_socket_fd,
    119 		                        buffer,
    120 		                        buffer_size) == -1) {
    121 			free(buffer);
    122 			close_socket(client_socket_fd);
    123 			continue;
    124 		}
    125 
    126 		free(buffer);
    127 		close_socket(client_socket_fd);
    128 	}
    129 
    130 	close_socket(server_socket_fd);
    131 
    132 	return 0;
    133 }