about summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--README.md3
-rw-r--r--build.zig10
-rw-r--r--csrc/cp.c28
-rw-r--r--csrc/cp.h2
-rw-r--r--csrc/http.c81
-rw-r--r--csrc/http.h5
-rw-r--r--csrc/main.c45
-rw-r--r--csrc/sh.c53
-rw-r--r--csrc/sh.h5
-rw-r--r--csrc/stat.c15
-rw-r--r--csrc/stat.h13
-rw-r--r--csrc/wc.c20
-rw-r--r--csrc/wc.h1
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);