From 9662c2754834599a1074d12565279674c20af467 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Tue, 21 Jan 2025 23:28:00 -0800 Subject: notes and stuff --- server.c | 258 +++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 159 insertions(+), 99 deletions(-) (limited to 'server.c') diff --git a/server.c b/server.c index 8522785b..8f65a793 100644 --- a/server.c +++ b/server.c @@ -6,119 +6,179 @@ #include #define SOCKET_PATH "/sockets/ctrl" -#define BUFFER_SIZE 262144 +#define INITIAL_BUFFER_SIZE 1024 -void handle_client(const char *result_socket, const char *command); +void handle_client(const char *result_socket, const char *command, const char *data); int main() { - int server_fd, client_fd; - struct sockaddr_un server_addr; - char buffer[BUFFER_SIZE]; + int server_fd, client_fd; + struct sockaddr_un server_addr; - unlink(SOCKET_PATH); + // Unlink the socket file in case it exists + unlink(SOCKET_PATH); - server_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (server_fd == -1) { - perror("socket failed"); - exit(EXIT_FAILURE); - } - - memset(&server_addr, 0, sizeof(struct sockaddr_un)); - server_addr.sun_family = AF_UNIX; - strncpy(server_addr.sun_path, SOCKET_PATH, sizeof(server_addr.sun_path) - 1); - - if (bind(server_fd, (struct sockaddr *)&server_addr, - sizeof(struct sockaddr_un)) == -1) { - perror("bind failed"); - close(server_fd); - exit(EXIT_FAILURE); - } - - if (listen(server_fd, 5) == -1) { - perror("listen failed"); - close(server_fd); - exit(EXIT_FAILURE); - } - - printf("Server listening on %s\n", SOCKET_PATH); - - while (1) { - - client_fd = accept(server_fd, NULL, NULL); - if (client_fd == -1) { - perror("accept failed"); - continue; + server_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (server_fd == -1) { + perror("socket failed"); + exit(EXIT_FAILURE); } - memset(buffer, 0, BUFFER_SIZE); - ssize_t num_bytes = read(client_fd, buffer, BUFFER_SIZE - 1); - if (num_bytes > 0) { - - buffer[num_bytes] = '\0'; - - printf("Received: %s\n", buffer); + memset(&server_addr, 0, sizeof(struct sockaddr_un)); + server_addr.sun_family = AF_UNIX; + strncpy(server_addr.sun_path, SOCKET_PATH, sizeof(server_addr.sun_path) - 1); - char result_socket[BUFFER_SIZE], command[BUFFER_SIZE]; - if (sscanf(buffer, "%s %[^\n]", result_socket, command) == 2) { - printf("Result socket: %s\n", result_socket); - printf("Command: %s\n", command); - - handle_client(result_socket, command); - } else { - fprintf(stderr, "Invalid input format\n"); - } + if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_un)) == -1) { + perror("bind failed"); + close(server_fd); + exit(EXIT_FAILURE); } - close(client_fd); - } - - close(server_fd); - unlink(SOCKET_PATH); - return 0; -} - -void handle_client(const char *result_socket, const char *command) { - pid_t pid = fork(); - - if (pid == 0) { - - int result_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (result_fd == -1) { - perror("result socket failed"); - exit(EXIT_FAILURE); + if (listen(server_fd, 5) == -1) { + perror("listen failed"); + close(server_fd); + exit(EXIT_FAILURE); } - struct sockaddr_un result_addr; - memset(&result_addr, 0, sizeof(struct sockaddr_un)); - result_addr.sun_family = AF_UNIX; - strncpy(result_addr.sun_path, result_socket, - sizeof(result_addr.sun_path) - 1); - - if (connect(result_fd, (struct sockaddr *)&result_addr, - sizeof(struct sockaddr_un)) == -1) { - perror("connect to result socket failed"); - close(result_fd); - exit(EXIT_FAILURE); + printf("Server listening on %s\n", SOCKET_PATH); + + while (1) { + client_fd = accept(server_fd, NULL, NULL); + if (client_fd == -1) { + perror("accept failed"); + continue; + } + + size_t buffer_size = INITIAL_BUFFER_SIZE; + char *buffer = malloc(buffer_size); + if (!buffer) { + perror("malloc failed"); + close(client_fd); + continue; + } + + size_t total_bytes_read = 0; + ssize_t num_bytes; + + while ((num_bytes = read(client_fd, buffer + total_bytes_read, buffer_size - total_bytes_read - 1)) > 0) { + total_bytes_read += num_bytes; + + // Expand buffer if necessary + if (total_bytes_read >= buffer_size - 1) { + buffer_size *= 2; + char *new_buffer = realloc(buffer, buffer_size); + if (!new_buffer) { + perror("realloc failed"); + free(buffer); + close(client_fd); + continue; + } + buffer = new_buffer; + } + } + + if (num_bytes == -1) { + perror("read failed"); + free(buffer); + close(client_fd); + continue; + } + + buffer[total_bytes_read] = '\0'; // Null-terminate the string + + printf("Received: %s\n", buffer); + + // Split message into result_socket, command, and data + char *result_socket = strtok(buffer, " "); + char *command = strtok(NULL, "\n"); + char *data = strtok(NULL, ""); + + if (result_socket && command) { + printf("Result socket: %s\n", result_socket); + printf("Command: %s\n", command); + if (data) { + printf("Data: %s\n", data); + } + handle_client(result_socket, command, data); + } else { + fprintf(stderr, "Invalid input format\n"); + } + + free(buffer); + close(client_fd); } - FILE *cmd_output = popen(command, "r"); - if (cmd_output == NULL) { - perror("popen failed"); - close(result_fd); - exit(EXIT_FAILURE); - } + close(server_fd); + unlink(SOCKET_PATH); + return 0; +} - char output_buffer[BUFFER_SIZE]; - while (fgets(output_buffer, sizeof(output_buffer), cmd_output) != NULL) { - write(result_fd, output_buffer, strlen(output_buffer)); +void handle_client(const char *result_socket, const char *command, const char *data) { + pid_t pid = fork(); + + if (pid == 0) { + int result_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (result_fd == -1) { + perror("result socket failed"); + exit(EXIT_FAILURE); + } + + struct sockaddr_un result_addr; + memset(&result_addr, 0, sizeof(struct sockaddr_un)); + result_addr.sun_family = AF_UNIX; + strncpy(result_addr.sun_path, result_socket, sizeof(result_addr.sun_path) - 1); + + if (connect(result_fd, (struct sockaddr *)&result_addr, sizeof(struct sockaddr_un)) == -1) { + perror("connect to result socket failed"); + close(result_fd); + exit(EXIT_FAILURE); + } + + int pipe_fd[2]; + if (pipe(pipe_fd) == -1) { + perror("pipe failed"); + close(result_fd); + exit(EXIT_FAILURE); + } + + pid_t cmd_pid = fork(); + if (cmd_pid == 0) { + // Child process: run the command + dup2(pipe_fd[0], STDIN_FILENO); // Redirect stdin + close(pipe_fd[0]); + close(pipe_fd[1]); + close(result_fd); + + execlp("/bin/sh", "sh", "-c", command, (char *)NULL); + perror("execlp failed"); + exit(EXIT_FAILURE); + } + + // Parent process: send data and collect output + close(pipe_fd[0]); // Close read end of the pipe + + if (data) { + write(pipe_fd[1], data, strlen(data)); + } + close(pipe_fd[1]); // Close write end of the pipe + + FILE *cmd_output = fdopen(result_fd, "w"); + if (!cmd_output) { + perror("fdopen failed"); + close(result_fd); + exit(EXIT_FAILURE); + } + + char output_buffer[INITIAL_BUFFER_SIZE]; + while (fgets(output_buffer, sizeof(output_buffer), cmd_output) != NULL) { + write(result_fd, output_buffer, strlen(output_buffer)); + } + + fclose(cmd_output); + shutdown(result_fd, SHUT_WR); + close(result_fd); + unlink(result_socket); + exit(0); + } else if (pid < 0) { + perror("fork failed"); } - - pclose(cmd_output); - shutdown(result_fd, SHUT_WR); - close(result_fd); - unlink(result_socket); - exit(0); - } else if (pid < 0) { - perror("fork failed"); - } } -- cgit v1.2.3