Advertisement
Guest User

Untitled

a guest
Feb 28th, 2020
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.28 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <sys/socket.h>
  5. #include <sys/stat.h>
  6. #include <sys/types.h>
  7. #include <sys/wait.h>
  8. #include <unistd.h>
  9.  
  10. volatile sig_atomic_t is_sigterm_caught = 0;
  11. volatile sig_atomic_t is_sigint_caught = 0;
  12.  
  13. void handle_sigterm(int signum) {
  14.     is_sigterm_caught = 1;
  15. }
  16.  
  17. void handle_sigint(int signum) {
  18.     is_sigint_caught = 1;
  19. }
  20.  
  21. void send_content_info(int handler_sock_fd, int requested_file_fd) {
  22.     struct stat st;
  23.     fstat(requested_file_fd, &st);
  24.     const int file_size = (int)(st.st_size);
  25.  
  26.     const int MAX_FILE_SIZE_DIGIT_COUNT = 4096;
  27.     char content_length[MAX_FILE_SIZE_DIGIT_COUNT];
  28.     sprintf(content_length, "Content-Length: %d\r\n\r\n", file_size);
  29.     send(handler_sock_fd, content_length, strlen(content_length), 0);
  30.  
  31.     const int MESS_PORTION_SIZE = 4096;
  32.     char file_content[MESS_PORTION_SIZE];
  33.     ssize_t read_byte_count = 0;
  34.     while ((read_byte_count = read(requested_file_fd, file_content, sizeof(file_content))) > 0) {
  35.         ssize_t written_byte_count = 0;
  36.         while (written_byte_count != read_byte_count) {
  37.             ssize_t byte_count = write(handler_sock_fd, file_content + written_byte_count,
  38.                                         (size_t)(read_byte_count - written_byte_count));
  39.             written_byte_count += byte_count;
  40.         }
  41.     }
  42. }
  43.  
  44. void send_execution_info(int handler_sock_fd, char* file_to_execute) {
  45.     pid_t pid = fork();
  46.     if (pid == 0) {
  47.         dup2(handler_sock_fd, 1);
  48.         int has_error_occured = execl(file_to_execute, file_to_execute, NULL);
  49.  
  50.         if (has_error_occured == -1) {
  51.             perror("file is not executed");
  52.             return;
  53.         }
  54.     } else {
  55.         int status = 0;
  56.         waitpid(pid, &status, 0);
  57.     }
  58. }
  59.  
  60. void send_answer(int handler_sock_fd, char* requested_file_name, char* dir_path) {
  61.     int dir_fd = open(dir_path, O_DIRECTORY);
  62.  
  63.     int is_existing_file = faccessat(dir_fd, requested_file_name, F_OK, 0);
  64.     if (is_existing_file == -1) {
  65.         char file_status[] = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
  66.         send(handler_sock_fd, file_status, strlen(file_status), 0);
  67.         close(dir_fd);
  68.         return;
  69.     }
  70.  
  71.     int is_read_allowed = faccessat(dir_fd, requested_file_name, R_OK, 0);
  72.     if (is_read_allowed == -1) {
  73.         char file_status[] = "HTTP/1.1 403 Forbidden\r\nContent-Length: 0\r\n\r\n";
  74.         send(handler_sock_fd, file_status, strlen(file_status), 0);
  75.         close(dir_fd);
  76.         return;
  77.     } else {
  78.         char file_status[] = "HTTP/1.1 200 OK\r\n";
  79.         send(handler_sock_fd, file_status, strlen(file_status), 0);
  80.     }
  81.  
  82.     int is_executable_file = faccessat(dir_fd, requested_file_name, X_OK, 0);
  83.  
  84.     if (is_executable_file == -1) {
  85.         int requested_file_fd = openat(dir_fd, requested_file_name, O_RDONLY);
  86.         close(dir_fd);
  87.         send_content_info(handler_sock_fd, requested_file_fd);
  88.         close(requested_file_fd);
  89.     } else {
  90.         close(dir_fd);
  91.         char file_to_execute[PATH_MAX];
  92.         strcat(file_to_execute, dir_path);
  93.         strcat(file_to_execute, "/");
  94.         strcat(file_to_execute, requested_file_name);
  95.         printf("%s\n", file_to_execute);
  96.         fflush(stdout);
  97.         send_execution_info(handler_sock_fd, file_to_execute);
  98.     }
  99. }
  100.  
  101. bool is_time_to_terminate() {
  102.     return is_sigterm_caught == 1 || is_sigint_caught == 1;
  103. }
  104.  
  105. int main(int argc, char** argv)
  106. {
  107.     struct sigaction sigterm_handler;
  108.     sigterm_handler.sa_handler = &handle_sigterm;
  109.     sigaction(SIGTERM, &sigterm_handler, NULL);
  110.  
  111.     struct sigaction sigint_handler;
  112.     sigint_handler.sa_handler = &handle_sigint;
  113.     sigaction(SIGINT, &sigint_handler, NULL);
  114.  
  115.     uint16_t port = (uint16_t)(strtoll(argv[1], NULL, 10));
  116.  
  117.     int listen_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
  118.  
  119.     const struct sockaddr_in server_addr =  {
  120.         .sin_family = AF_INET,
  121.         .sin_port = htons(port),
  122.         .sin_addr = {.s_addr = inet_addr("127.0.0.1")}
  123.     };
  124.     bind(listen_sock_fd, (const struct sockaddr*)(&server_addr),
  125.          (socklen_t)(sizeof(server_addr)));
  126.     listen(listen_sock_fd, SOMAXCONN);
  127.  
  128.     int handler_sock_fd = 0;
  129.     while(!is_time_to_terminate()) {
  130.         handler_sock_fd = accept(listen_sock_fd, NULL, NULL);
  131.  
  132.         if (handler_sock_fd == -1) {
  133.             if (is_time_to_terminate()) {
  134.                 close(listen_sock_fd);
  135.                 exit(0);
  136.             } else {
  137.                 continue;
  138.             }
  139.         }
  140.  
  141.         FILE* handler_sock = fdopen(handler_sock_fd, "r");
  142.  
  143.         char file_name[PATH_MAX];
  144.         fscanf(handler_sock, "GET %s HTTP/1.1", file_name);
  145.  
  146.         int char1 = 0;
  147.         int char2 = 0;
  148.         int char3 = 0;
  149.         int char4 = 0;
  150.         while (!(char1 == (int)('\r') && char2 == (int)('\n') &&
  151.                  char3 == (int)('\r') && char4 == (int)('\n'))) {
  152.             char1 = char2;
  153.             char2 = char3;
  154.             char3 = char4;
  155.             char4 = fgetc(handler_sock);
  156.             if (char4 == EOF) {
  157.                 break;
  158.             }
  159.         }
  160.  
  161.         send_answer(handler_sock_fd, file_name, argv[2]);
  162.         shutdown(handler_sock_fd, SHUT_RDWR);
  163.         fclose(handler_sock);
  164.     }
  165.  
  166.     close(listen_sock_fd);
  167. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement