diff options
author | Mauri de Souza Nunes <mauri870@gmail.com> | 2019-09-12 11:26:54 -0300 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-11-04 12:47:54 +0100 |
commit | b61414fb9660c5368b1a8ca414acc344bd43ac33 (patch) | |
tree | dbc9c803886b4c82143a48c8c7cd6a25302d2d1a | |
parent | d5b66a02c404d1d70dcf870bdd1a6973615f5a1b (diff) | |
download | serenity-b61414fb9660c5368b1a8ca414acc344bd43ac33.zip |
Userland: Add syscall program
The Plan9 OS has this program that can test a system call with the
given arguments. For the most basic system calls it can be very
helpful and aid with testing or just to play with a given syscall
without writing a dedicated program.
Some examples:
syscall write 1 hello 5
syscall -o read 0 buf 5
syscall mkdir /tmp/my-dir
syscall exit 2
...
-rw-r--r-- | Userland/syscall.cpp | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/Userland/syscall.cpp b/Userland/syscall.cpp new file mode 100644 index 0000000000..59f111ab96 --- /dev/null +++ b/Userland/syscall.cpp @@ -0,0 +1,88 @@ +#include <Kernel/Syscall.h> +#include <errno.h> +#include <getopt.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#if !defined __ENUMERATE_SYSCALL +# define __ENUMERATE_SYSCALL(x) SC_##x, +#endif + +#define SC_NARG 4 + +Syscall::Function syscall_table[] = { + ENUMERATE_SYSCALLS +}; + +uintptr_t arg[SC_NARG]; +char buf[BUFSIZ]; + +uintptr_t parse(char* s); + +int main(int argc, char** argv) +{ + int oflag; + int opt; + while ((opt = getopt(argc, argv, "oh")) != -1) { + switch (opt) { + case 'o': + oflag = 1; + break; + case 'h': + fprintf(stderr, "usage: \tsyscall [-o] entry [args; buf==BUFSIZ buffer]\n"); + fprintf(stderr, "\tsyscall write 1 hello 5\n"); + fprintf(stderr, "\tsyscall -o read 0 buf 5\n"); + fprintf(stderr, "\tsyscall -o getcwd buf 100\n"); + break; + default: + exit(EXIT_FAILURE); + } + } + + if (optind >= argc) { + fprintf(stderr, "No entry specified\n"); + return -1; + } + + for (int i = 0; i < argc - optind; i++) { + arg[i] = parse(argv[i + optind]); + } + + for (auto sc : syscall_table) { + if (strcmp(Syscall::to_string(sc), (char*)arg[0]) == 0) { + int rc = syscall(sc, arg[1], arg[2], arg[3]); + if (rc == -1) { + perror("syscall"); + } else { + if (oflag) + printf("%s", buf); + } + + fprintf(stderr, "Syscall return: %d\n", rc); + return 0; + } + } + + fprintf(stderr, "Invalid syscall entry %s\n", (char*)arg[0]); + return -1; +} + +uintptr_t parse(char* s) +{ + char* t; + uintptr_t l; + + if (strcmp(s, "buf") == 0) { + return (uintptr_t)buf; + } + + l = strtoul(s, &t, 0); + if (t > s && *t == 0) { + return l; + } + + return (uintptr_t)s; +} |