1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-24 17:27:18 +00:00

Add more os module functions.

This commit is contained in:
Calvin Rose 2019-03-28 23:22:58 -04:00
parent bfd3845218
commit 53c7f2eedd
6 changed files with 150 additions and 34 deletions

View File

@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
- Add (break) special form and improve loop macro - Add (break) special form and improve loop macro
- Allow abstract types to specify custom tostring method - Allow abstract types to specify custom tostring method
- Extend C API for marshalling abstract types and other values - Extend C API for marshalling abstract types and other values
- Add functions to `os` module.
## 0.4.0 - 2019-03-08 ## 0.4.0 - 2019-03-08
- Fix a number of smaller bugs - Fix a number of smaller bugs

View File

@ -98,6 +98,15 @@ DEFINE_GETTER(cfunction, CFUNCTION, JanetCFunction)
DEFINE_GETTER(boolean, BOOLEAN, int) DEFINE_GETTER(boolean, BOOLEAN, int)
DEFINE_GETTER(pointer, POINTER, void *) DEFINE_GETTER(pointer, POINTER, void *)
const char *janet_getcstring(const Janet *argv, int32_t n) {
const uint8_t *jstr = janet_getstring(argv, n);
const char *cstr = (const char *)jstr;
if (strlen(cstr) != (size_t) janet_string_length(jstr)) {
janet_panicf("string %v contains embedded 0s");
}
return cstr;
}
int32_t janet_getinteger(const Janet *argv, int32_t n) { int32_t janet_getinteger(const Janet *argv, int32_t n) {
Janet x = argv[n]; Janet x = argv[n];
if (!janet_checkint(x)) { if (!janet_checkint(x)) {

View File

@ -24,6 +24,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <inttypes.h> #include <inttypes.h>
#include <math.h>
#ifndef JANET_AMALG #ifndef JANET_AMALG
#include <janet.h> #include <janet.h>

View File

@ -26,16 +26,24 @@
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#ifndef JANET_REDUCED_OS
#include <time.h> #include <time.h>
#ifdef JANET_WINDOWS #ifdef JANET_WINDOWS
#include <Windows.h> #include <Windows.h>
#include <direct.h> #include <direct.h>
#else #else
#include <sys/stat.h>
#include <utime.h>
#include <unistd.h> #include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h>
#endif #endif
/* For macos */ /* For macos */
@ -44,6 +52,12 @@
#include <mach/mach.h> #include <mach/mach.h>
#endif #endif
#endif
/* Core OS functions */
/* Full OS functions */
static Janet os_which(int32_t argc, Janet *argv) { static Janet os_which(int32_t argc, Janet *argv) {
janet_fixarity(argc, 0); janet_fixarity(argc, 0);
(void) argv; (void) argv;
@ -58,6 +72,30 @@ static Janet os_which(int32_t argc, Janet *argv) {
#endif #endif
} }
static Janet os_exit(int32_t argc, Janet *argv) {
janet_arity(argc, 0, 1);
if (argc == 0) {
exit(EXIT_SUCCESS);
} else if (janet_checkint(argv[0])) {
exit(janet_unwrap_integer(argv[0]));
} else {
exit(EXIT_FAILURE);
}
return janet_wrap_nil();
}
#ifdef JANET_REDUCED_OS
/* Provide a dud os/getenv so init.janet works, but nothing else */
static Janet os_getenv(int32_t argc, Janet *argv) {
(void) argv;
janet_fixarity(argc, 1);
return janet_wrap_nil();
}
#else
/* Provide full os functionality */
#ifdef JANET_WINDOWS #ifdef JANET_WINDOWS
static Janet os_execute(int32_t argc, Janet *argv) { static Janet os_execute(int32_t argc, Janet *argv) {
janet_arity(argc, 1, -1); janet_arity(argc, 1, -1);
@ -124,13 +162,13 @@ static Janet os_execute(int32_t argc, Janet *argv) {
#else #else
static Janet os_execute(int32_t argc, Janet *argv) { static Janet os_execute(int32_t argc, Janet *argv) {
janet_arity(argc, 1, -1); janet_arity(argc, 1, -1);
const uint8_t **child_argv = malloc(sizeof(uint8_t *) * (argc + 1)); const char **child_argv = malloc(sizeof(char *) * (argc + 1));
int status = 0; int status = 0;
if (NULL == child_argv) { if (NULL == child_argv) {
JANET_OUT_OF_MEMORY; JANET_OUT_OF_MEMORY;
} }
for (int32_t i = 0; i < argc; i++) { for (int32_t i = 0; i < argc; i++) {
child_argv[i] = janet_getstring(argv, i); child_argv[i] = janet_getcstring(argv, i);
} }
child_argv[argc] = NULL; child_argv[argc] = NULL;
@ -139,7 +177,7 @@ static Janet os_execute(int32_t argc, Janet *argv) {
if (pid < 0) { if (pid < 0) {
janet_panic("failed to execute"); janet_panic("failed to execute");
} else if (pid == 0) { } else if (pid == 0) {
if (-1 == execve((const char *)child_argv[0], (char **)child_argv, NULL)) { if (-1 == execve(child_argv[0], (char **)child_argv, NULL)) {
exit(1); exit(1);
} }
} else { } else {
@ -153,7 +191,7 @@ static Janet os_execute(int32_t argc, Janet *argv) {
static Janet os_shell(int32_t argc, Janet *argv) { static Janet os_shell(int32_t argc, Janet *argv) {
janet_arity(argc, 0, 1); janet_arity(argc, 0, 1);
const char *cmd = argc const char *cmd = argc
? (const char *)janet_getstring(argv, 0) ? janet_getcstring(argv, 0)
: NULL; : NULL;
int stat = system(cmd); int stat = system(cmd);
return argc return argc
@ -163,10 +201,9 @@ static Janet os_shell(int32_t argc, Janet *argv) {
static Janet os_getenv(int32_t argc, Janet *argv) { static Janet os_getenv(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1); janet_fixarity(argc, 1);
const uint8_t *k = janet_getstring(argv, 0); const char *cstr = janet_getcstring(argv, 0);
const char *cstr = (const char *) k;
const char *res = getenv(cstr); const char *res = getenv(cstr);
return (res && cstr) return res
? janet_cstringv(res) ? janet_cstringv(res)
: janet_wrap_nil(); : janet_wrap_nil();
} }
@ -180,25 +217,11 @@ static Janet os_setenv(int32_t argc, Janet *argv) {
#define UNSETENV(K) unsetenv(K) #define UNSETENV(K) unsetenv(K)
#endif #endif
janet_arity(argc, 1, 2); janet_arity(argc, 1, 2);
const uint8_t *k = janet_getstring(argv, 0); const char *ks = janet_getcstring(argv, 0);
const char *ks = (const char *) k;
if (argc == 1 || janet_checktype(argv[1], JANET_NIL)) { if (argc == 1 || janet_checktype(argv[1], JANET_NIL)) {
UNSETENV(ks); UNSETENV(ks);
} else { } else {
const uint8_t *v = janet_getstring(argv, 1); SETENV(ks, janet_getcstring(argv, 1));
SETENV(ks, (const char *)v);
}
return janet_wrap_nil();
}
static Janet os_exit(int32_t argc, Janet *argv) {
janet_arity(argc, 0, 1);
if (argc == 0) {
exit(EXIT_SUCCESS);
} else if (janet_checkint(argv[0])) {
exit(janet_unwrap_integer(argv[0]));
} else {
exit(EXIT_FAILURE);
} }
return janet_wrap_nil(); return janet_wrap_nil();
} }
@ -301,7 +324,68 @@ static Janet os_date(int32_t argc, Janet *argv) {
return janet_wrap_struct(janet_struct_end(st)); return janet_wrap_struct(janet_struct_end(st));
} }
static Janet os_link(int32_t argc, Janet *argv) {
janet_arity(argc, 2, 3);
#ifdef JANET_WINDOWS
(void) argc;
(void) argv;
janet_panic("os/link not supported on Windows");
return janet_wrap_nil();
#else
const char *oldpath = janet_getcstring(argv, 0);
const char *newpath = janet_getcstring(argv, 1);
int res = ((argc == 3 && janet_getboolean(argv, 2)) ? symlink : link)(oldpath, newpath);
if (res == -1) janet_panicv(janet_cstringv(strerror(errno)));
return janet_wrap_integer(res);
#endif
}
static Janet os_mkdir(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
const char *path = janet_getcstring(argv, 0);
#ifdef JANET_WINDOWS
int res = _mkdir(path);
#else
int res = mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH);
#endif
return janet_wrap_boolean(res != -1);
}
static Janet os_cd(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1);
const char *path = janet_getcstring(argv, 0);
int res = chdir(path);
return janet_wrap_boolean(res != -1);
}
static Janet os_touch(int32_t argc, Janet *argv) {
janet_arity(argc, 1, 3);
const char *path = janet_getcstring(argv, 0);
struct utimbuf timebuf, *bufp;
if (argc >= 2) {
bufp = &timebuf;
timebuf.actime = (time_t) janet_getnumber(argv, 1);
if (argc >= 3) {
timebuf.modtime = (time_t) janet_getnumber(argv, 2);
} else {
timebuf.modtime = timebuf.actime;
}
} else {
bufp = NULL;
}
int res = utime(path, bufp);
return janet_wrap_boolean(res != -1);
}
#endif /* JANET_REDUCED_OS */
static const JanetReg os_cfuns[] = { static const JanetReg os_cfuns[] = {
{
"os/exit", os_exit,
JDOC("(os/exit x)\n\n"
"Exit from janet with an exit code equal to x. If x is not an integer, "
"the exit with status equal the hash of x.")
},
{ {
"os/which", os_which, "os/which", os_which,
JDOC("(os/which)\n\n" JDOC("(os/which)\n\n"
@ -310,6 +394,35 @@ static const JanetReg os_cfuns[] = {
"\t:macos - Apple macos\n" "\t:macos - Apple macos\n"
"\t:posix - A POSIX compatible system (default)") "\t:posix - A POSIX compatible system (default)")
}, },
{
"os/getenv", os_getenv,
JDOC("(os/getenv variable)\n\n"
"Get the string value of an environment variable.")
},
#ifndef JANET_REDUCED_OS
{
"os/touch", os_touch,
JDOC("(os/touch path [, actime [, modtime]])\n\n"
"Update the access time and modification times for a file. By default, sets "
"times to the current time.")
},
{
"os/cd", os_cd,
JDOC("(os/cd path)\n\n"
"Change current directory to path. Returns true on success, false on failure.")
},
{
"os/mkdir", os_mkdir,
JDOC("(os/mkdir path)\n\n"
"Create a new directory. The path will be relative to the current directory if relative, otherwise "
"it will be an absolute path.")
},
{
"os/link", os_link,
JDOC("(os/link oldpath newpath [, symlink])\n\n"
"Create a symlink from oldpath to newpath. The 3 optional paramater "
"enables a hard link over a soft link. Does not work on Windows.")
},
{ {
"os/execute", os_execute, "os/execute", os_execute,
JDOC("(os/execute program & args)\n\n" JDOC("(os/execute program & args)\n\n"
@ -321,17 +434,6 @@ static const JanetReg os_cfuns[] = {
JDOC("(os/shell str)\n\n" JDOC("(os/shell str)\n\n"
"Pass a command string str directly to the system shell.") "Pass a command string str directly to the system shell.")
}, },
{
"os/exit", os_exit,
JDOC("(os/exit x)\n\n"
"Exit from janet with an exit code equal to x. If x is not an integer, "
"the exit with status equal the hash of x.")
},
{
"os/getenv", os_getenv,
JDOC("(os/getenv variable)\n\n"
"Get the string value of an environment variable.")
},
{ {
"os/setenv", os_setenv, "os/setenv", os_setenv,
JDOC("(os/setenv variable value)\n\n" JDOC("(os/setenv variable value)\n\n"
@ -375,6 +477,7 @@ static const JanetReg os_cfuns[] = {
"\t:year-day - day of the year [0-365]\n" "\t:year-day - day of the year [0-365]\n"
"\t:dst - If Day Light Savings is in effect") "\t:dst - If Day Light Savings is in effect")
}, },
#endif
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };

View File

@ -1256,6 +1256,7 @@ JANET_API const Janet *janet_gettuple(const Janet *argv, int32_t n);
JANET_API JanetTable *janet_gettable(const Janet *argv, int32_t n); JANET_API JanetTable *janet_gettable(const Janet *argv, int32_t n);
JANET_API const JanetKV *janet_getstruct(const Janet *argv, int32_t n); JANET_API const JanetKV *janet_getstruct(const Janet *argv, int32_t n);
JANET_API const uint8_t *janet_getstring(const Janet *argv, int32_t n); JANET_API const uint8_t *janet_getstring(const Janet *argv, int32_t n);
JANET_API const char *janet_getcstring(const Janet *argv, int32_t n);
JANET_API const uint8_t *janet_getsymbol(const Janet *argv, int32_t n); JANET_API const uint8_t *janet_getsymbol(const Janet *argv, int32_t n);
JANET_API const uint8_t *janet_getkeyword(const Janet *argv, int32_t n); JANET_API const uint8_t *janet_getkeyword(const Janet *argv, int32_t n);
JANET_API JanetBuffer *janet_getbuffer(const Janet *argv, int32_t n); JANET_API JanetBuffer *janet_getbuffer(const Janet *argv, int32_t n);

View File

@ -34,6 +34,7 @@
/* #define JANET_NO_PEG */ /* #define JANET_NO_PEG */
/* #define JANET_NO_TYPED_ARRAY */ /* #define JANET_NO_TYPED_ARRAY */
/* #define JANET_NO_INT_TYPES */ /* #define JANET_NO_INT_TYPES */
/* #define JANET_REDUCED_OS */
/* #define JANET_API __attribute__((visibility ("default"))) */ /* #define JANET_API __attribute__((visibility ("default"))) */
/* #define JANET_OUT_OF_MEMORY do { printf("janet out of memory\n"); exit(1); } while (0) */ /* #define JANET_OUT_OF_MEMORY do { printf("janet out of memory\n"); exit(1); } while (0) */
/* #define JANET_RECURSION_GUARD 1024 */ /* #define JANET_RECURSION_GUARD 1024 */