Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85629444
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
8 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/lib/exile.ex b/lib/exile.ex
index 5c4b96c..95e279b 100644
--- a/lib/exile.ex
+++ b/lib/exile.ex
@@ -1,18 +1,44 @@
defmodule Exile do
- @moduledoc """
- Documentation for Exile.
- """
+ @on_load :load_nifs
- @doc """
- Hello world.
+ def load_nifs do
+ :erlang.load_nif('./priv/hello', 0)
+ end
+
+ def fast_compare(_a, _b) do
+ raise "NIF fast_compare/2 not implemented"
+ end
+
+ def exec_proc(_cmd) do
+ raise "NIF exec_proc/0 not implemented"
+ end
+
+ def write_proc(_cmd) do
+ raise "NIF exec_proc/0 not implemented"
+ end
- ## Examples
+ def read_proc(_cmd) do
+ raise "NIF exec_proc/0 not implemented"
+ end
- iex> Exile.hello()
- :world
+ def kill_proc(_pid) do
+ raise "NIF kill_proc/1 not implemented"
+ end
+
+ def terminate_proc(_pid) do
+ raise "NIF terminate_proc/1 not implemented"
+ end
+
+ def wait_proc(_pid) do
+ raise "NIF wait_proc/1 not implemented"
+ end
+
+ def pid_info(_pid) do
+ raise "NIF pid_info/1 not implemented"
+ end
- """
- def hello do
- :world
+ def ps(pid) do
+ {out, 0} = System.cmd("ps", [to_string(pid)])
+ out
end
end
diff --git a/priv/hello.c b/priv/hello.c
new file mode 100644
index 0000000..a4d2014
--- /dev/null
+++ b/priv/hello.c
@@ -0,0 +1,263 @@
+#include "erl_nif.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+
+static int set_flag (int fd)
+{
+ return fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK | O_CLOEXEC);
+}
+
+static ERL_NIF_TERM
+fast_compare(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
+ int a, b;
+ // Fill a and b with the values of the first two args
+ enif_get_int(env, argv[0], &a);
+ enif_get_int(env, argv[1], &b);
+
+ // Usual C unreadable code because this way is more true
+ int result = a == b ? 0 : (a > b ? 1 : -1);
+
+ return enif_make_int(env, result);
+}
+
+enum exec_status {
+ SUCCESS,
+ PIPE_CREATE_ERROR,
+ PIPE_FLAG_ERROR,
+ FORK_ERROR,
+ PIPE_DUP_ERROR
+};
+
+typedef struct ExecResults {
+ enum exec_status status;
+ int err;
+ pid_t pid;
+ int pipe_in;
+ int pipe_out;
+} ExecResult;
+
+static const int PIPE_READ = 0;
+static const int PIPE_WRITE = 1;
+
+static void
+close_all(int pipes[3][2]) {
+ for(int i=0; i<3; i++){
+ if (pipes[i][PIPE_READ]) close(pipes[i][PIPE_READ]);
+ if (pipes[i][PIPE_WRITE]) close(pipes[i][PIPE_WRITE]);
+ }
+}
+
+static ExecResult
+start_proccess(char *const *args) {
+ ExecResult result;
+ pid_t pid;
+ int pipes[3][2] = {{0, 0}, {0, 0}, {0, 0}};
+
+#define RETURN_ERROR(_status) \
+ do { \
+ result.status = _status; \
+ result.err = errno; \
+ close_all(pipes); \
+ return result; \
+ } while(0); \
+
+ if (
+ pipe(pipes[STDIN_FILENO]) == -1 ||
+ pipe(pipes[STDOUT_FILENO]) == -1 ||
+ pipe(pipes[STDERR_FILENO]) == -1) {
+ RETURN_ERROR(PIPE_CREATE_ERROR)
+ }
+
+ if (
+ set_flag(pipes[STDIN_FILENO][PIPE_READ]) < 0 ||
+ set_flag(pipes[STDIN_FILENO][PIPE_WRITE]) < 0 ||
+ set_flag(pipes[STDOUT_FILENO][PIPE_READ]) < 0 ||
+ set_flag(pipes[STDOUT_FILENO][PIPE_WRITE]) < 0 ||
+ set_flag(pipes[STDERR_FILENO][PIPE_READ]) < 0 ||
+ set_flag(pipes[STDERR_FILENO][PIPE_WRITE]) < 0) {
+ RETURN_ERROR(PIPE_FLAG_ERROR)
+ }
+
+ switch (pid = fork()) {
+ case -1:
+ RETURN_ERROR(FORK_ERROR)
+
+ case 0 :
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ fprintf(stderr, "HERE\n");
+
+ if (dup2(pipes[STDIN_FILENO][PIPE_READ], STDIN_FILENO) < 0) RETURN_ERROR(PIPE_DUP_ERROR)
+ fprintf(stderr, "HERE 2\n");
+ if (dup2(pipes[STDOUT_FILENO][PIPE_WRITE], STDOUT_FILENO) < 0) RETURN_ERROR(PIPE_DUP_ERROR)
+ fprintf(stderr, "HERE 3\n");
+
+ close_all(pipes);
+ fprintf(stderr, "HERE 4\n");
+
+ /* char* cmd = "/bin/sh"; */
+ char *const cmd_args[2] = {"/bin/sh", NULL};
+ execvp("/bin/sh", cmd_args);
+ perror("execvp(): failed");
+
+ default:
+ close(pipes[STDIN_FILENO][PIPE_READ]);
+ close(pipes[STDOUT_FILENO][PIPE_WRITE]);
+ result.pid = pid;
+ result.pipe_in = pipes[STDIN_FILENO][PIPE_WRITE];
+ result.pipe_out = pipes[STDOUT_FILENO][PIPE_READ];
+ result.status = SUCCESS;
+ return result;
+ }
+}
+
+static ERL_NIF_TERM
+exec_proc(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
+ char cmd_args[10][1024];
+ char *arg = NULL;
+
+ for (int i=0; i < argc; i++) {
+ if (enif_get_string(env, argv[i], cmd_args[i], sizeof(cmd_args[i]), ERL_NIF_LATIN1) < 1) {
+ return enif_make_badarg(env);
+ }
+ }
+
+ ExecResult result = start_proccess((char *const *)cmd_args);
+
+ switch (result.status) {
+ case SUCCESS:
+ return enif_make_tuple4(env, enif_make_int(env, 0), enif_make_int(env, result.pid), enif_make_int(env, result.pipe_in), enif_make_int(env, result.pipe_out));
+ default:
+ return enif_make_tuple4(env, enif_make_int(env, -1), enif_make_int(env, 0), enif_make_int(env, 0), enif_make_int(env, 0));
+ }
+}
+
+
+static ERL_NIF_TERM
+write_proc(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
+ int pipe_in;
+ enif_get_int(env, argv[0], &pipe_in);
+
+ char buf[] = "ls\n";
+ int count = write(pipe_in, buf, sizeof(buf));
+
+ if ( count == 0 ) {
+ printf("EOF!\n");
+ } else if ( count > 0) {
+ printf("Success! %d\n", count);
+ } else {
+ perror("write(): failed");
+ }
+
+ return enif_make_int(env, count);
+}
+
+
+static ERL_NIF_TERM
+read_proc(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
+ int pipe_out;
+ enif_get_int(env, argv[0], &pipe_out);
+
+ char buf[500];
+ (void)memset(&buf, '\0', sizeof(buf));
+
+ int count = read(pipe_out, buf, sizeof(buf));
+
+ if ( count == 0 ) {
+ printf("EOF!\n");
+ } else if ( count > 0) {
+ printf("%s\n", buf);
+ printf("Success %d\n", count);
+ } else if ( errno == EAGAIN ) {
+ printf("EAGAIN\n");
+ } else {
+ perror("read(): failed");
+ }
+
+ return enif_make_int(env, count);
+}
+
+
+static ERL_NIF_TERM
+pid_info(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
+ int pid;
+ enif_get_int(env, argv[0], &pid);
+
+ int result = kill(pid, 0);
+
+ if ( result == 0 ) {
+ printf("Success!\n");
+ } else {
+ printf("Fail!\n");
+ }
+
+ return enif_make_int(env, result);
+}
+
+static ERL_NIF_TERM
+terminate_proc(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
+ int pid;
+ enif_get_int(env, argv[0], &pid);
+ return enif_make_int(env, kill(pid, SIGTERM));
+}
+
+static ERL_NIF_TERM
+kill_proc(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
+ int pid;
+ enif_get_int(env, argv[0], &pid);
+ return enif_make_int(env, kill(pid, SIGKILL));
+}
+
+static ERL_NIF_TERM
+wait_proc(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
+ int pid, status;
+ enif_get_int(env, argv[0], &pid);
+
+ int wpid = waitpid(pid, &status, WNOHANG);
+ fprintf(stderr, "wait(): %s\n", strerror(status));
+
+ return enif_make_tuple2(env, enif_make_int(env, wpid), enif_make_int(env, status));
+}
+
+
+/* static ERL_NIF_TERM */
+/* terminate_proc(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { */
+/* int pid, status; */
+/* enif_get_int(env, argv[0], &pid); */
+
+/* int result = kill(pid, SIGTERM); */
+/* int wpid = waitpid(pid, &status, WNOHANG); */
+/* /\* usleep(500000); *\/ */
+
+/* printf("wpid: %d result: %d status: %d\n", wpid, result, status); */
+
+/* if ( wpid == pid && result == 0 ) { */
+/* printf("process %i succesfully killed\n", pid); */
+/* } else { */
+/* printf("failed to kill %i\n", pid); */
+/* } */
+
+/* return enif_make_int(env, kill(pid, signal)); */
+/* } */
+
+
+// Let's define the array of ErlNifFunc beforehand:
+static ErlNifFunc nif_funcs[] = {
+ // {erl_function_name, erl_function_arity, c_function}
+ {"fast_compare", 2, fast_compare},
+ {"exec_proc", 1, exec_proc},
+ {"write_proc", 1, write_proc},
+ {"read_proc", 1, read_proc},
+ {"terminate_proc", 1, terminate_proc},
+ {"wait_proc", 1, wait_proc},
+ {"kill_proc", 1, kill_proc},
+ {"pid_info", 1, pid_info},
+};
+
+ERL_NIF_INIT(Elixir.Exile, nif_funcs, NULL, NULL, NULL, NULL)
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Aug 8, 9:18 PM (1 d, 17 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1723982
Default Alt Text
(8 KB)
Attached To
Mode
R14 exile
Attached
Detach File
Event Timeline
Log In to Comment