From 8de6f45af1628c90c571002679735b5d496c95a5 Mon Sep 17 00:00:00 2001 From: catfood Date: Thu, 5 Jan 2023 17:03:50 +0800 Subject: [PATCH] lab util grade 100 --- Makefile | 5 ++++ time.txt | 1 + user/find.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ user/pingpong.c | 27 ++++++++++++++++++ user/primes.c | 51 ++++++++++++++++++++++++++++++++++ user/sleep.c | 17 ++++++++++++ user/xargs.c | 59 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 234 insertions(+) create mode 100644 time.txt create mode 100644 user/find.c create mode 100644 user/pingpong.c create mode 100644 user/primes.c create mode 100644 user/sleep.c create mode 100644 user/xargs.c diff --git a/Makefile b/Makefile index ded5bc2..eadf415 100644 --- a/Makefile +++ b/Makefile @@ -188,6 +188,11 @@ UPROGS=\ $U/_grind\ $U/_wc\ $U/_zombie\ + $U/_sleep\ + $U/_pingpong\ + $U/_primes\ + $U/_find\ + $U/_xargs\ diff --git a/time.txt b/time.txt new file mode 100644 index 0000000..62f9457 --- /dev/null +++ b/time.txt @@ -0,0 +1 @@ +6 \ No newline at end of file diff --git a/user/find.c b/user/find.c new file mode 100644 index 0000000..75e5dcd --- /dev/null +++ b/user/find.c @@ -0,0 +1,74 @@ +#include "kernel/types.h" +#include "user/user.h" +#include "kernel/stat.h" +#include "kernel/fs.h" + +int fmtname(const char *path) { + int p; + for(p=strlen(path); p >= 0 && *(path + p) != '/'; p--); + p++; + return p; +} + +void find(const char *path, const char* target) { + char buf[512], *p; + int fd; + struct dirent de; + struct stat st; + if((fd = open(path, 0)) < 0){ + fprintf(2, "find: cannot open %s\n", path); + return; + } + + if(fstat(fd, &st) < 0){ + fprintf(2, "find: cannot stat %s\n", path); + close(fd); + return; + } + + switch(st.type){ + case T_DEVICE: + case T_FILE: + if (strcmp(path + fmtname(path), target) == 0) { + printf("%s\n", path); + } + break; + + case T_DIR: + if (strcmp(path + fmtname(path), target) == 0) { + printf("%s\n", path); + } + if(strlen(path) + 1 + DIRSIZ + 1 > sizeof buf){ + printf("find: path too long\n"); + break; + } + strcpy(buf, path); + p = buf+strlen(buf); + *p++ = '/'; + while(read(fd, &de, sizeof(de)) == sizeof(de)){ + if(de.inum == 0) + continue; + if (strcmp(de.name, ".") == 0 || strcmp(de.name, "..") == 0) + continue; + memmove(p, de.name, DIRSIZ); + p[DIRSIZ] = 0; + if(stat(buf, &st) < 0){ + printf("find: cannot stat %s\n", buf); + continue; + } + find(buf, target); + } + break; + } + close(fd); +} + +int main(int argc, char** argv) { + if (argc != 3) { + printf("\x1b[31mInvalid arguments\x1b[0m\n"); + printf("\x1b[32musage\x1b[0m: find \n"); + exit(0); + } + find(argv[1], argv[2]); + exit(0); +} \ No newline at end of file diff --git a/user/pingpong.c b/user/pingpong.c new file mode 100644 index 0000000..868f67c --- /dev/null +++ b/user/pingpong.c @@ -0,0 +1,27 @@ +#include "kernel/types.h" +#include "user/user.h" + +int main(int argc, char** argv) { + int p[2]; // hell, read from p[0] and write to p[1] no matter in pa/ch + if (pipe(p) == -1) exit(1); + uint8 senddata[] = {0xAC}; + uint8 recvdata[] = {0}; + int pid = fork(); + if (pid == 0) { + // child + if (read(p[0], recvdata, 1) != 1) printf("error child read\n"); + close(p[0]); + printf("%d: received ping\n", getpid()); + if (write(p[1], senddata, 1) != 1) printf("error child write\n"); + close(p[1]); + exit(0); + } + else { + if (write(p[1], senddata, 1) != 1) printf("error parent write\n"); + close(p[1]); + if (read(p[0], recvdata, 1) != 1) printf("error parent read\n"); + printf("%d: received pong\n", getpid()); + close(p[0]); + exit(0); + } +} \ No newline at end of file diff --git a/user/primes.c b/user/primes.c new file mode 100644 index 0000000..07d2034 --- /dev/null +++ b/user/primes.c @@ -0,0 +1,51 @@ +#include "kernel/types.h" +#include "user/user.h" + +void pipeline(int leftfd) { + int pipefd[2]; + int p; read(leftfd, &p, sizeof(p)); + printf("prime %d\n", p); + int n; + int has_right = 0; + while (read(leftfd, &n, sizeof(n)) > 0) { + if (n % p != 0) { + if (!has_right) { + has_right = 1; + pipe(pipefd); + if (fork() == 0) { + close(pipefd[1]); + pipeline(pipefd[0]); + } else { + close(pipefd[0]); + } + } + write(pipefd[1], &n, sizeof(n)); + } + } + close(leftfd); + if (has_right) { + close(pipefd[1]); + while(wait(0) != -1); + } + exit(0); +} + +int main(int argc, char** argv) { + int pipefd[2]; + pipe(pipefd); + int pid = fork(); + if (pid != 0) { + close(pipefd[0]); // no need to read in the feeding proc + for (int i = 2; i <= 35; ++ i) { + write(pipefd[1], &i, sizeof(i)); + } + close(pipefd[1]); + while(wait(0) != -1); + exit(0); + } + else { + close(pipefd[1]); // pipeline proc will have its own write pipe + pipeline(pipefd[0]); + } + exit(0); +} \ No newline at end of file diff --git a/user/sleep.c b/user/sleep.c new file mode 100644 index 0000000..39d5d0b --- /dev/null +++ b/user/sleep.c @@ -0,0 +1,17 @@ +#include "kernel/types.h" +#include "user/user.h" + +int main(int argc, char** argv) { + if (argc != 2) { + printf("\x1b[31mUnexpected argument\x1b[0m\n"); + printf("usage: sleep \n"); + exit(0); + } + int ticks = atoi(argv[1]); + int ret = sleep(ticks); + if (ret) { + printf("\x1b[31mFailed to sleep\x1b[0m\n"); + exit(-1); + } + exit(0); +} \ No newline at end of file diff --git a/user/xargs.c b/user/xargs.c new file mode 100644 index 0000000..46553f3 --- /dev/null +++ b/user/xargs.c @@ -0,0 +1,59 @@ +#include "kernel/param.h" +#include "kernel/types.h" +#include "user/user.h" + +static inline int is_ws(const char ch) { + return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'; +} + +int main(int argc, char** argv) { + int STDIN = 0; + char linebuf[1024]; + char* p = linebuf; + char* _argv[MAXARG]; + while (read(STDIN, p, 1) > 0) { + if (*p == '\n') { + int i; + int in_ws = 1; + for (i = 0; i < argc - 1; ++i) { + _argv[i] = argv[i + 1]; + } + for (char* p0 = linebuf; p0 <= p; ++p0) { + if (is_ws(*p0)) { + if (!in_ws) { + in_ws = 1; + i++; + } + *p0 = '\0'; + } else if (in_ws) { + in_ws = 0; + _argv[i] = p0; + } + if (i >= MAXARG) { + printf("warning: too many arguments"); + break; + } + } + *p = '\0'; + _argv[i] = 0; + // for (int j = 0; j < i; ++ j) { + // printf("%s\n", _argv[j]); + // } + if (fork() == 0) { + exec(_argv[0], _argv); + exit(0); + } else { + p = linebuf; + while (wait(0) != -1) + ; + } + } else { + p++; + if (p >= linebuf + sizeof(linebuf)) { + printf("line buffer exceeded\n"); + exit(0); + } + } + } + exit(0); +} \ No newline at end of file