summaryrefslogtreecommitdiff
path: root/Userland/syscall.cpp
diff options
context:
space:
mode:
authorMauri de Souza Nunes <mauri870@gmail.com>2019-09-12 11:26:54 -0300
committerAndreas Kling <awesomekling@gmail.com>2019-11-04 12:47:54 +0100
commitb61414fb9660c5368b1a8ca414acc344bd43ac33 (patch)
treedbc9c803886b4c82143a48c8c7cd6a25302d2d1a /Userland/syscall.cpp
parentd5b66a02c404d1d70dcf870bdd1a6973615f5a1b (diff)
downloadserenity-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 ...
Diffstat (limited to 'Userland/syscall.cpp')
-rw-r--r--Userland/syscall.cpp88
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;
+}