261 lines
5.3 KiB
C
261 lines
5.3 KiB
C
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <limits.h>
|
|
#include <math.h>
|
|
#include <setjmp.h>
|
|
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
|
|
#include "scheme.h"
|
|
|
|
pid_t getpgid(pid_t pid);
|
|
|
|
static value_t dirsym;
|
|
struct fltype *dirtype;
|
|
|
|
void path_to_dirname(char *path)
|
|
{
|
|
char *p;
|
|
|
|
if (!(p = strrchr(path, '/'))) {
|
|
p = path;
|
|
}
|
|
*p = '\0';
|
|
}
|
|
|
|
void get_cwd(char *buf, size_t size)
|
|
{
|
|
if (!getcwd(buf, size)) {
|
|
memset(buf, 0, size);
|
|
}
|
|
}
|
|
|
|
int set_cwd(char *buf)
|
|
{
|
|
if (chdir(buf) == -1)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
value_t builtin_pid(value_t *args, uint32_t nargs)
|
|
{
|
|
(void)args;
|
|
argcount("pid", nargs, 0);
|
|
return fixnum(getpid());
|
|
}
|
|
|
|
value_t builtin_parent_pid(value_t *args, uint32_t nargs)
|
|
{
|
|
(void)args;
|
|
argcount("parent-pid", nargs, 0);
|
|
return fixnum(getppid());
|
|
}
|
|
|
|
value_t builtin_process_group(value_t *args, uint32_t nargs)
|
|
{
|
|
(void)args;
|
|
argcount("process-group", nargs, 0);
|
|
return fixnum(getpgid(0));
|
|
}
|
|
|
|
value_t builtin_user_effective_gid(value_t *args, uint32_t nargs)
|
|
{
|
|
(void)args;
|
|
argcount("user-effective-gid", nargs, 0);
|
|
return fixnum(getegid());
|
|
}
|
|
|
|
value_t builtin_user_effective_uid(value_t *args, uint32_t nargs)
|
|
{
|
|
(void)args;
|
|
argcount("user-effective-uid", nargs, 0);
|
|
return fixnum(geteuid());
|
|
}
|
|
|
|
value_t builtin_user_real_gid(value_t *args, uint32_t nargs)
|
|
{
|
|
(void)args;
|
|
argcount("user-real-gid", nargs, 0);
|
|
return fixnum(getgid());
|
|
}
|
|
|
|
value_t builtin_user_real_uid(value_t *args, uint32_t nargs)
|
|
{
|
|
(void)args;
|
|
argcount("user-real-uid", nargs, 0);
|
|
return fixnum(getuid());
|
|
}
|
|
|
|
int os_path_exists(const char *path)
|
|
{
|
|
struct stat st;
|
|
|
|
return stat(path, &st) != -1;
|
|
}
|
|
|
|
void os_setenv(const char *name, const char *value)
|
|
{
|
|
if (value) {
|
|
if (setenv(name, value, 1) != 0) {
|
|
lerror(ArgError, "os.setenv: cannot set environment variable");
|
|
}
|
|
} else {
|
|
if (unsetenv(name) != 0) {
|
|
lerror(ArgError, "os.setenv: cannot unset environment variable");
|
|
}
|
|
}
|
|
}
|
|
|
|
int isdirvalue(value_t v)
|
|
{
|
|
return iscvalue(v) && cv_class((struct cvalue *)ptr(v)) == dirtype;
|
|
}
|
|
|
|
static DIR **todirhandleptr(value_t v, const char *fname)
|
|
{
|
|
if (!isdirvalue(v))
|
|
type_error(fname, "dir", v);
|
|
return value2c(DIR **, v);
|
|
}
|
|
|
|
value_t builtin_os_open_directory(value_t *args, uint32_t nargs)
|
|
{
|
|
const char *path;
|
|
DIR *dirhandle;
|
|
DIR **dirhandleptr;
|
|
value_t dirvalue;
|
|
|
|
argcount("open-directory", nargs, 1);
|
|
path = tostring(args[0], "path");
|
|
if (!(dirhandle = opendir(path))) {
|
|
lerror(IOError, "cannot open directory");
|
|
}
|
|
dirvalue = cvalue(dirtype, sizeof(DIR *));
|
|
dirhandleptr = value2c(DIR **, dirvalue);
|
|
*dirhandleptr = dirhandle;
|
|
return dirvalue;
|
|
}
|
|
|
|
value_t builtin_os_read_directory(value_t *args, uint32_t nargs)
|
|
{
|
|
DIR *dirhandle;
|
|
DIR **dirhandleptr;
|
|
struct dirent *d;
|
|
|
|
argcount("read-directory", nargs, 1);
|
|
dirhandleptr = todirhandleptr(args[0], "dir");
|
|
dirhandle = *dirhandleptr;
|
|
for (;;) {
|
|
errno = 0;
|
|
if (!(d = readdir(dirhandle))) {
|
|
break;
|
|
}
|
|
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) {
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
if (!d && errno) {
|
|
lerror(IOError, "cannot read directory");
|
|
}
|
|
return d ? string_from_cstr(d->d_name) : FL_EOF;
|
|
}
|
|
|
|
value_t builtin_os_close_directory(value_t *args, uint32_t nargs)
|
|
{
|
|
DIR *dirhandle;
|
|
DIR **dirhandleptr;
|
|
|
|
argcount("read-directory", nargs, 1);
|
|
dirhandleptr = todirhandleptr(args[0], "dir");
|
|
dirhandle = *dirhandleptr;
|
|
if (dirhandle) {
|
|
if (closedir(dirhandle) == -1) {
|
|
lerror(IOError, "cannot close directory");
|
|
}
|
|
*dirhandleptr = dirhandle = 0;
|
|
}
|
|
return FL_F;
|
|
}
|
|
|
|
static void print_dir(value_t v, struct ios *f)
|
|
{
|
|
(void)v;
|
|
fl_print_str("#<directory>", f);
|
|
}
|
|
|
|
static void free_dir(value_t self)
|
|
{
|
|
DIR *dirhandle;
|
|
DIR **dirhandleptr;
|
|
|
|
dirhandleptr = todirhandleptr(self, "dir");
|
|
dirhandle = *dirhandleptr;
|
|
if (dirhandle) {
|
|
if (closedir(dirhandle) == -1) {
|
|
// lerror(IOError, "cannot close directory");
|
|
}
|
|
*dirhandleptr = dirhandle = 0;
|
|
}
|
|
}
|
|
|
|
static void relocate_dir(value_t oldv, value_t newv)
|
|
{
|
|
(void)oldv;
|
|
(void)newv;
|
|
}
|
|
|
|
// TODO: cleanup
|
|
static struct termios term_mode_orig;
|
|
static struct termios term_mode_raw;
|
|
|
|
void cfmakeraw(struct termios *t);
|
|
|
|
static void term_mode_init(void)
|
|
{
|
|
static int done;
|
|
|
|
if (!done) {
|
|
done = 1;
|
|
tcgetattr(0, &term_mode_orig);
|
|
cfmakeraw(&term_mode_raw);
|
|
}
|
|
}
|
|
|
|
value_t builtin_term_init(value_t *args, uint32_t nargs)
|
|
{
|
|
(void)args;
|
|
argcount("term-init", nargs, 0);
|
|
term_mode_init();
|
|
tcsetattr(0, TCSAFLUSH, &term_mode_raw);
|
|
return FL_T;
|
|
}
|
|
|
|
value_t builtin_term_exit(value_t *args, uint32_t nargs)
|
|
{
|
|
(void)args;
|
|
argcount("term-exit", nargs, 0);
|
|
term_mode_init();
|
|
tcsetattr(0, TCSAFLUSH, &term_mode_orig);
|
|
return FL_T;
|
|
}
|
|
|
|
struct cvtable dir_vtable = { print_dir, relocate_dir, free_dir, NULL };
|
|
|
|
void os_init(void)
|
|
{
|
|
dirsym = symbol("dir");
|
|
dirtype = define_opaque_type(dirsym, sizeof(DIR *), &dir_vtable, NULL);
|
|
}
|