diff options
Diffstat (limited to '')
-rw-r--r-- | README.md | 3 | ||||
-rw-r--r-- | build.zig | 10 | ||||
-rw-r--r-- | csrc/cp.c | 28 | ||||
-rw-r--r-- | csrc/cp.h | 2 | ||||
-rw-r--r-- | csrc/http.c | 81 | ||||
-rw-r--r-- | csrc/http.h | 5 | ||||
-rw-r--r-- | csrc/main.c | 45 | ||||
-rw-r--r-- | csrc/sh.c | 53 | ||||
-rw-r--r-- | csrc/sh.h | 5 | ||||
-rw-r--r-- | csrc/stat.c | 15 | ||||
-rw-r--r-- | csrc/stat.h | 13 | ||||
-rw-r--r-- | csrc/wc.c | 20 | ||||
-rw-r--r-- | csrc/wc.h | 1 |
13 files changed, 281 insertions, 0 deletions
diff --git a/README.md b/README.md index f406926..a319bfe 100644 --- a/README.md +++ b/README.md @@ -24,3 +24,6 @@ This is pool of ideas of what to implement in zig - [ ] improve cli args parser - [ ] play with markow chains - [ ] btree index for toy db + +## More ideas +https://github.com/practical-tutorials/project-based-learning?tab=readme-ov-file#cc diff --git a/build.zig b/build.zig index 9b16a14..62a971b 100644 --- a/build.zig +++ b/build.zig @@ -81,4 +81,14 @@ pub fn build(b: *std.Build) !void { try define_subproj("monkey_brain", b, target, optimize); try define_subproj("monkey_learns", b, target, optimize); + + const cprog = b.addExecutable(.{ .name = "cprog", .target = target, .optimize = optimize }); + cprog.linkLibC(); + cprog.addCSourceFiles(.{ .files = &.{ "csrc/cp.c", "csrc/main.c", "csrc/wc.c", "csrc/sh.c", "csrc/stat.c", "csrc/http.c" }, .flags = &.{} }); + b.installArtifact(cprog); + + const run_c_cmd = b.addRunArtifact(cprog); + run_c_cmd.step.dependOn(b.getInstallStep()); + const runc_step = b.step("runc", "Run c prog"); + runc_step.dependOn(&run_c_cmd.step); } diff --git a/csrc/cp.c b/csrc/cp.c new file mode 100644 index 0000000..5280bae --- /dev/null +++ b/csrc/cp.c @@ -0,0 +1,28 @@ +#include "cp.h" +#include <stdio.h> + +FileStatus copy_file(char *src, char *dst) { + + FILE *source = fopen(src, "rb"); + if (!source) { + return READ_ERROR; + } + + FILE *destination = fopen(dst, "wb"); + if (!destination) { + fclose(source); + return WRITE_ERROR; + } + + char buffer[1024]; + size_t bytes; + + while ((bytes = fread(buffer, 1, sizeof(buffer), source)) > 0) { + fwrite(buffer, 1, bytes, destination); + } + + fclose(source); + fclose(destination); + + return WRITE_OK; +} diff --git a/csrc/cp.h b/csrc/cp.h new file mode 100644 index 0000000..70b1c13 --- /dev/null +++ b/csrc/cp.h @@ -0,0 +1,2 @@ +typedef enum { READ_ERROR, WRITE_ERROR, WRITE_OK } FileStatus; +FileStatus copy_file(char *src, char *dst); diff --git a/csrc/http.c b/csrc/http.c new file mode 100644 index 0000000..0da89c4 --- /dev/null +++ b/csrc/http.c @@ -0,0 +1,81 @@ +#include "http.h" +#include <arpa/inet.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define MAX_QUEUE 3 + +void *handle_client(void *client_socket) { + int sock = *(int *)client_socket; + + free(client_socket); + + char buffer[1024]; + int n; + + n = read(sock, buffer, sizeof(buffer) - 1); + if (n < 0) { + perror("read"); + close(sock); + exit(1); + return NULL; + } + + buffer[n] = '\0'; + printf("Request: %s\n", buffer); + + const char *response = "HTTP/1.1 200 OK\r\n\r\nHello, World!"; + write(sock, response, strlen(response)); + close(sock); + + return NULL; +} + +void start_server(int port) { + int server_sock, client_sock, *new_sock; + struct sockaddr_in server, client; + + socklen_t client_len = sizeof(client); + pthread_t thread_id; + + server_sock = socket(AF_INET, SOCK_STREAM, 0); + if (server_sock < 0) { + perror("socket"); + exit(1); + } + + server.sin_family = AF_INET; + server.sin_port = htons(port); + server.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(server_sock, (struct sockaddr *)&server, sizeof(server)) < 0) { + perror("bind"); + close(server_sock); + exit(1); + } + + listen(server_sock, MAX_QUEUE); + + printf("Server listening on port %d\n", port); + + while ((client_sock = + accept(server_sock, (struct sockaddr *)&client, &client_len))) { + new_sock = malloc(sizeof(int)); + *new_sock = client_sock; + + if (pthread_create(&thread_id, NULL, handle_client, (void *)new_sock) < 0) { + perror("pthread_create"); + exit(1); + } + } + + if (client_sock < 0) { + perror("accept"); + exit(1); + } + + close(server_sock); +} diff --git a/csrc/http.h b/csrc/http.h new file mode 100644 index 0000000..5701b27 --- /dev/null +++ b/csrc/http.h @@ -0,0 +1,5 @@ +#ifndef __HTTP_H__ +#define __HTTP_H__ +void *handle_client(void *client_socket); +void start_server(int port); +#endif diff --git a/csrc/main.c b/csrc/main.c new file mode 100644 index 0000000..f8393e5 --- /dev/null +++ b/csrc/main.c @@ -0,0 +1,45 @@ +#include "cp.h" +#include "http.h" +#include "sh.h" +#include "stat.h" +#include "wc.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int main(int argc, char *argv[]) { + if (argc < 3) { + return 1; + } + + char *command = argv[1]; + + if (command == NULL) { + return 1; + } + + if (strcmp(command, "cp") == 0) { + char *src = argv[2]; + char *dst = argv[3]; + FileStatus status = copy_file(src, dst); + if (status == READ_ERROR) { + fprintf(stderr, "Error reading file: %s\n", src); + } else if (status == WRITE_ERROR) { + fprintf(stderr, "Error writing file: %s\n", dst); + } + } else if (strncmp(command, "wc", 2) == 0) { + char *src = argv[2]; + int lines = count_lines(src); + printf("%d\n", lines); + } else if (strncmp(command, "sh", 2) == 0) { + shell(); + } else if (strncmp(command, "stat", 4) == 0) { + char *filename = argv[2]; + if (mstat(filename) == STAT_ERR) { + return 1; + } + } else if (strncmp(command, "http", 4) == 0) { + int port = atoi(argv[2]); + start_server(port); + } +} diff --git a/csrc/sh.c b/csrc/sh.c new file mode 100644 index 0000000..7372d2d --- /dev/null +++ b/csrc/sh.c @@ -0,0 +1,53 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#define MAXLINE 80 + +int shell() { + char line[MAXLINE]; + char *args[MAXLINE / 2 + 1]; + int should_run = 1; + + while (should_run) { + printf(">"); + fflush(stdout); + + if (!fgets(line, MAXLINE, stdin)) { + break; + } + + line[strlen(line) - 1] = '\0'; + + int i = 0; + args[i] = strtok(line, " "); + while (args[i] != NULL) { + i++; + args[i] = strtok(NULL, " "); + } + + if (args[0] == NULL) { + continue; + } + + if (strncmp(args[0], "exit", 4) == 0) { + break; + } + + pid_t pid = fork(); + if (pid < 0) { + perror("fork"); + return 1; + } else if (pid == 0) { + if (execvp(args[0], args) == -1) { + perror("execvp"); + } + return 1; + } else { + wait(NULL); + } + } +} diff --git a/csrc/sh.h b/csrc/sh.h new file mode 100644 index 0000000..523c3f0 --- /dev/null +++ b/csrc/sh.h @@ -0,0 +1,5 @@ +#ifndef __SHELLH__ +#define __SHELLH__ + +int shell(); +#endif diff --git a/csrc/stat.c b/csrc/stat.c new file mode 100644 index 0000000..fb60302 --- /dev/null +++ b/csrc/stat.c @@ -0,0 +1,15 @@ +#include "stat.h" + +stat_res_t mstat(char *file) { + struct stat fileStat; + + if (stat(file, &fileStat) < 0) { + return STAT_ERR; + } + + printf("File Size: %ld bytes\n", fileStat.st_size); + printf("Number of Links %ld\n", fileStat.st_nlink); + printf("File inode: %ld\n", fileStat.st_ino); + + return STAT_OK; +} diff --git a/csrc/stat.h b/csrc/stat.h new file mode 100644 index 0000000..3ad725d --- /dev/null +++ b/csrc/stat.h @@ -0,0 +1,13 @@ +#ifndef __STATH_ +#define __STATH_ + +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +typedef enum { STAT_OK, STAT_ERR } stat_res_t; + +stat_res_t mstat(char *file); + +#endif diff --git a/csrc/wc.c b/csrc/wc.c new file mode 100644 index 0000000..1059c5c --- /dev/null +++ b/csrc/wc.c @@ -0,0 +1,20 @@ +#include "wc.h" +#include <stdio.h> + +int count_lines(char *src) { + FILE *file = fopen(src, "r"); + + if (file == NULL) { + return -1; + } + + int lines = 0; + char c; + while ((c = fgetc(file)) != EOF) { + if (c == '\n') { + lines++; + } + } + fclose(file); + return lines; +} diff --git a/csrc/wc.h b/csrc/wc.h new file mode 100644 index 0000000..4811392 --- /dev/null +++ b/csrc/wc.h @@ -0,0 +1 @@ +int count_lines(char *src); |