From df5b9166405f23c1c25006b16e86a25c527395c8 Mon Sep 17 00:00:00 2001 From: Alex Shinn Date: Tue, 11 Aug 2009 01:15:29 +0900 Subject: [PATCH] adding initial 9p interface --- opcodes.c | 1 + opt/plan9.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) diff --git a/opcodes.c b/opcodes.c index 492ebc6b..56aa6563 100644 --- a/opcodes.c +++ b/opcodes.c @@ -143,6 +143,7 @@ _FN1(SEXP_STRING, "getenv", 0, sexp_getenv), _FN1(SEXP_STRING, "change-directory", 0, sexp_chdir), _FN0("wait", 0, sexp_wait), _FN2(SEXP_FIXNUM, SEXP_STRING, "post-note", 0, sexp_postnote), +_FN4(SEXP_PAIR, SEXP_STRING, "%postmountsrv", 0, sexp_postmountsrv), #endif }; diff --git a/opt/plan9.c b/opt/plan9.c index 3cc51097..b386a3a0 100644 --- a/opt/plan9.c +++ b/opt/plan9.c @@ -120,3 +120,190 @@ sexp sexp_postnote (sexp ctx, sexp pid, sexp note) { return SEXP_VOID; } +/**********************************************************************/ +/* 9p interface */ + +typedef struct sexp_plan9_srv { + sexp context, auth, attach, walk, walk1, clone, open, create, remove, + read, write, stat, wstat, flush, destroyfid, destroyreq, end; +} *sexp_plan9_srv; + +void sexp_build_srv (sexp ctx, sexp_plan9_srv s, sexp ls) { + s->context = ctx; + s->auth = s->attach = s->walk = s->walk1 = s->clone = s->open + = s->create = s->remove = s->read = s->write = s->stat = s->wstat + = s->flush = s->destroyfid = s->destroyreq = s->end = SEXP_FALSE; + for ( ; sexp_pairp(ls) && sexp_pairp(sexp_cdr(ls)); ls=sexp_cddr(ls)) { + if (sexp_car(ls) == sexp_intern(ctx, "auth:")) { + s->auth = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "attach:")) { + s->attach = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "walk:")) { + s->walk = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "walk1:")) { + s->walk1 = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "clone:")) { + s->clone = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "open:")) { + s->open = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "create:")) { + s->create = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "remove:")) { + s->remove = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "read:")) { + s->read = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "write:")) { + s->write = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "stat:")) { + s->stat = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "wstat:")) { + s->wstat = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "flush:")) { + s->flush = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "destroyfid:")) { + s->destroyfid = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "destroyreq:")) { + s->destroyreq = sexp_cadr(ls); + } else if (sexp_car(ls) == sexp_intern(ctx, "end:")) { + s->end = sexp_cadr(ls); + } + } +} + +void sexp_run_9p_handler (Req *r, sexp handler) { + sexp_plan9_srv s = (sexp_plan9_srv)r->srv->aux; + sexp ctx = s->context; + sexp_gc_var(ctx, ptr, s_ptr); + sexp_gc_var(ctx, args, s_args); + sexp_gc_preserve(ctx, ptr, s_ptr); + sexp_gc_preserve(ctx, args, s_args); + ptr = sexp_make_cpointer(ctx, r); + args = sexp_cons(ctx, ptr, SEXP_NULL); + sexp_apply(ctx, handler, args); + sexp_gc_release(ctx, ptr, s_ptr); +} + +#define sexp_def_9p_handler(name, field) \ + void name (Req *r) { \ + sexp_run_9p_handler(r, ((sexp_plan9_srv)r->srv->aux)->field); \ + } + +sexp_def_9p_handler(sexp_9p_auth, auth) +sexp_def_9p_handler(sexp_9p_attach, attach) +sexp_def_9p_handler(sexp_9p_walk, walk) +sexp_def_9p_handler(sexp_9p_open, open) +sexp_def_9p_handler(sexp_9p_create, create) +sexp_def_9p_handler(sexp_9p_remove, remove) +sexp_def_9p_handler(sexp_9p_read, read) +sexp_def_9p_handler(sexp_9p_write, write) +sexp_def_9p_handler(sexp_9p_stat, stat) +sexp_def_9p_handler(sexp_9p_wstat, wstat) +sexp_def_9p_handler(sexp_9p_flush, flush) + +char* sexp_9p_walk1 (Fid *fid, char *name, Qid *qid) { + sexp_plan9_srv s = (sexp_plan9_srv)fid->pool->srv->aux; + sexp res, ctx = s->context; + sexp_gc_var(ctx, ptr, s_ptr); + sexp_gc_var(ctx, args, s_args); + sexp_gc_preserve(ctx, ptr, s_ptr); + sexp_gc_preserve(ctx, args, s_args); + ptr = sexp_make_cpointer(ctx, qid); + args = sexp_cons(ctx, ptr, SEXP_NULL); + ptr = sexp_c_string(ctx, name, -1); + args = sexp_cons(ctx, ptr, args); + ptr = sexp_make_cpointer(ctx, fid); + args = sexp_cons(ctx, ptr, args); + res = sexp_apply(ctx, s->walk1, args); + sexp_gc_release(ctx, ptr, s_ptr); + return sexp_stringp(res) ? sexp_string_data(res) : nil; +} + +char* sexp_9p_clone (Fid *oldfid, Fid *newfid) { + sexp_plan9_srv s = (sexp_plan9_srv)oldfid->pool->srv->aux; + sexp res, ctx = s->context; + sexp_gc_var(ctx, ptr, s_ptr); + sexp_gc_var(ctx, args, s_args); + sexp_gc_preserve(ctx, ptr, s_ptr); + sexp_gc_preserve(ctx, args, s_args); + ptr = sexp_make_cpointer(ctx, oldfid); + args = sexp_cons(ctx, ptr, SEXP_NULL); + ptr = sexp_make_cpointer(ctx, newfid); + args = sexp_cons(ctx, ptr, args); + res = sexp_apply(ctx, s->clone, args); + sexp_gc_release(ctx, ptr, s_ptr); + return sexp_stringp(res) ? sexp_string_data(res) : nil; +} + +void sexp_9p_destroyfid (Fid *fid) { + sexp_plan9_srv s = (sexp_plan9_srv)fid->pool->srv->aux; + sexp ctx = s->context; + sexp_gc_var(ctx, ptr, s_ptr); + sexp_gc_var(ctx, args, s_args); + sexp_gc_preserve(ctx, ptr, s_ptr); + sexp_gc_preserve(ctx, args, s_args); + ptr = sexp_make_cpointer(ctx, fid); + args = sexp_cons(ctx, ptr, SEXP_NULL); + sexp_apply(ctx, s->destroyfid, args); + sexp_gc_release(ctx, ptr, s_ptr); +} + +void sexp_9p_destroyreq (Req *r) { + sexp_plan9_srv s = (sexp_plan9_srv)r->srv->aux; + sexp ctx = s->context; + sexp_gc_var(ctx, ptr, s_ptr); + sexp_gc_var(ctx, args, s_args); + sexp_gc_preserve(ctx, ptr, s_ptr); + sexp_gc_preserve(ctx, args, s_args); + ptr = sexp_make_cpointer(ctx, r); + args = sexp_cons(ctx, ptr, SEXP_NULL); + sexp_apply(ctx, s->destroyreq, args); + sexp_gc_release(ctx, ptr, s_ptr); +} + +void sexp_9p_end (Srv *srv) { + sexp_plan9_srv s = (sexp_plan9_srv)srv->aux; + sexp ctx = s->context; + sexp_gc_var(ctx, ptr, s_ptr); + sexp_gc_var(ctx, args, s_args); + sexp_gc_preserve(ctx, ptr, s_ptr); + sexp_gc_preserve(ctx, args, s_args); + ptr = sexp_make_cpointer(ctx, srv); + args = sexp_cons(ctx, ptr, SEXP_NULL); + sexp_apply(ctx, s->end, args); + sexp_gc_release(ctx, ptr, s_ptr); +} + +sexp sexp_postmountsrv (sexp ctx, sexp ls, sexp name, sexp mtpt, sexp flags) { + Srv s; + struct sexp_plan9_srv p9s; + if (! sexp_listp(ctx, ls)) + return sexp_type_exception(ctx, "postmountsrv: not an list", ls); + if (! sexp_stringp(name)) + return sexp_type_exception(ctx, "postmountsrv: not a string", name); + if (! sexp_stringp(mtpt)) + return sexp_type_exception(ctx, "postmountsrv: not a string", mtpt); + if (! sexp_integerp(flags)) + return sexp_type_exception(ctx, "postmountsrv: not an integer", flags); + sexp_build_srv(ctx, &p9s, ls); + s.aux = &p9s; + s.auth = &sexp_9p_auth; + s.attach = &sexp_9p_attach; + s.walk = &sexp_9p_walk; + s.walk1 = &sexp_9p_walk1; + s.clone = &sexp_9p_clone; + s.open = &sexp_9p_open; + s.create = &sexp_9p_create; + s.remove = &sexp_9p_remove; + s.read = &sexp_9p_read; + s.write = &sexp_9p_write; + s.stat = &sexp_9p_stat; + s.wstat = &sexp_9p_wstat; + s.flush = &sexp_9p_flush; + s.destroyfid = &sexp_9p_destroyfid; + s.destroyreq = &sexp_9p_destroyreq; + s.end = &sexp_9p_end; + postmountsrv(&s, sexp_string_data(name), sexp_string_data(mtpt), + sexp_unbox_integer(flags)); + return SEXP_UNDEF; +} +