ref: fba678b80d8c266077e12cd43d5e42d3ab6e411c
author: Sean Hinchee <henesy@users.noreply.github.com>
date: Sun Sep 23 22:34:46 EDT 2018
more boilerplate before work really begins
--- /dev/null
+++ b/9curses.h
@@ -1,0 +1,57 @@
+/* This header is cursed.
+ *
+ * The functions and whatnot here are aimed at providing a layer of compatibility
+ * between ncurses-like interfaces and cursedfs to avoid too much rewriting.
+ */
+
+// stub
+#define KEY_UP L'↑'
+// stub
+#define KEY_DOWN L'↓'
+// Stub
+#define stdscr 0
+
+typedef struct WINDOW WINDOW;
+
+// Clear the screen
+void clear();
+
+// Initialize a new WINDOW
+WINDOW* newwin(uint, uint, uint, uint);
+
+// Clean up and close a WINDOW
+endwin();
+
+// Analogue to print for a string from origin y,x
+int mvprintw(int y, int x, char *fmt, ...);
+
+// Sets a character at y,x
+mvaddch(int y, int x, char c);
+
+// Get a 'raw' character input from the user
+getch();
+
+// Initialize the screen
+initscr();
+
+// Set raw mode for the screen
+raw();
+
+// Don't echo keypress characters to the screen
+noecho();
+
+// Place the cursor at location y,x
+curs_set();
+
+// Set delay until escape sequence potential is ignored
+set_escdelay();
+
+// Refresh the screen
+refresh();
+
+// Refresh a window
+wrefresh(WINDOW*);
+
+struct WINDOW{
+ s8int naught;// Stub
+};
--- /dev/null
+++ b/cursed.c
@@ -1,0 +1,72 @@
+#include <u.h>
+#include <libc.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+#include "cursed.h"
+
+Sem *sems[Nsems];
+
+Sem *
+newsem(char *name)
+{
+ int i;
+
+ for(i = 0; i < Nsems; i++)
+ if(sems[i] == nil)
+ break;
+ if(i == Nsems)
+ return nil;
+ sems[i] = emalloc9p(sizeof(Sem));
+ memset(sems[i], 0, sizeof(Sem));
+ sems[i]->ref = 2;
+ sems[i]->name = estrdup9p(name);
+ return sems[i];
+}
+
+void
+closesem(Sem *s)
+{
+ if(s != nil && decref(s) == 0){
+ assert(s->reqs == nil);
+ assert(sems[s->id] == s);
+ sems[s->id] = nil;
+ free(s->name);
+ free(s);
+ }
+}
+
+void
+queuereq(Sem *s, Req *r)
+{
+ QReq *q;
+ QReq **l;
+
+ q = emalloc9p(sizeof(QReq));
+ q->r = r;
+ q->next = nil;
+ for(l = &s->reqs; *l != nil; l = &(*l)->next)
+ ;
+ *l = q;
+}
+
+Req *
+dequeuereq(Sem *s)
+{
+ QReq *q;
+ Req *r;
+
+ if(s->reqs == nil)
+ return nil;
+ q = s->reqs;
+ s->reqs = q->next;
+ r = q->r;
+ free(q);
+ return r;
+}
+
+int
+queuedreqs(Sem *s)
+{
+ return s->reqs != nil;
+}
--- /dev/null
+++ b/cursed.h
@@ -1,0 +1,24 @@
+typedef struct Sem Sem;
+typedef struct QReq QReq;
+
+struct Sem{
+ Ref;
+ int id; // index in array; qid.path
+ char *name; // of file
+ int tickets;
+ QReq *reqs; // reads (i.e., downs) pending
+};
+
+struct QReq{
+ QReq *next; // in pending request list
+ Req *r; // the request pending
+};
+
+#define Nsems 32
+extern Sem *sems[];
+
+extern Sem *newsem(char *name);
+extern void closesem(Sem *s);
+extern void queuereq(Sem *s, Req *r);
+extern Req *dequeuereq(Sem *s);
+extern int queuedreqs(Sem *s);
--- /dev/null
+++ b/cursedfs.c
@@ -1,0 +1,250 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include <thread.h>
+#include <9p.h>
+#include "cursed.h"
+
+static void
+fsattach(Req *r)
+{
+ r->fid->qid = (Qid) { 0, 0, QTDIR };
+ r->ofcall.qid = r->fid->qid;
+ respond(r, nil);
+}
+
+static void
+fscreate(Req *r)
+{
+ Fid *fid;
+ Qid q;
+ Sem *s;
+
+ fid = r->fid;
+ q = fid->qid;
+ if(!(q.type & QTDIR)){
+ respond(r, "not a directory");
+ return;
+ }
+ s = newsem(r->ifcall.name);
+ fid->qid = (Qid){s->id, 0, 0};
+ fid->aux = s;
+ fid->omode = r->ifcall.mode;
+ incref(s);
+ r->ofcall.qid = fid->qid;
+ respond(r, nil);
+}
+
+static void
+fsremove(Req *r)
+{
+ Req *q;
+ Sem *s;
+
+ s = r->fid->aux;
+ while(q = dequeuereq(s))
+ respond(q, "file has bee removed");
+ closesem(s);
+ r->fid->aux = nil;
+ closesem(s); // release reference from sems[]
+ respond(r, nil);
+}
+
+static int
+getdirent(int n, Dir *d, void *)
+{
+ d->atime = time(nil);
+ d->mtime = d->atime;
+ d->uid = estrdup9p(getuser());
+ d->gid = estrdup9p(d->uid);
+ d->muid = estrdup9p(d->uid);
+ if(n == -1){
+ d->qid = (Qid) {0, 0, QTDIR};
+ d->mode = 0775;
+ d->name = estrdup9p("/");
+ d->length = 0;
+ }else if(n >= 0 && n < Nsems && sems[n] != nil){
+ d->qid = (Qid) {n, 0, 0};
+ d->mode = 0664;
+ d->name = estrdup9p(sems[n]->name);
+ d->length = sems[n]->tickets;
+ }else
+ return -1;
+ return 0;
+}
+
+static void
+fsread(Req *r)
+{
+ Fid *fid;
+ Qid q;
+ Sem *s;
+ char nl[] = "\n";
+
+ fid = r->fid;
+ q = fid->qid;
+ if(q.type & QTDIR){
+ dirread9p(r, getdirent, nil);
+ respond(r, nil);
+ return;
+ }
+ s = fid->aux;
+ if(s->tickets > 0){
+ s->tickets--;
+ readstr(r, nl);
+ respond(r, nil);
+ }else
+ queuereq(s, r);
+}
+
+static void
+fswrite(Req *r)
+{
+ Fid *fid;
+ Qid q;
+ Sem *s;
+ Req *qr;
+ char str[10];
+ char nl[] = "\n";
+
+ fid = r->fid;
+ q = fid->qid;
+ if(q.type & QTDIR){
+ respond(r, "permission denied");
+ return;
+ }
+ if(r->ifcall.count > sizeof(str) - 1){
+ respond(r, "string too large");
+ return;
+ }
+ memmove(str, r->ifcall.data, r->ifcall.count);
+ str[r->ifcall.count] = 0;
+ s = fid->aux;
+ s->tickets += atoi(str);
+
+ while(s->tickets > 0 && queuedreqs(s)){
+ qr = dequeuereq(s);
+ qr->ofcall.count = 1;
+ s->tickets--;
+ readstr(qr, nl);
+ respond(qr, nil);
+ }
+ respond(r, nil);
+}
+
+static char *
+fswalkl(Fid * fid, char *name, Qid *qid)
+{
+ Qid q;
+ Sem *s;
+ int i;
+
+ q = fid->qid;
+ s = fid->aux;
+ if(!(q.type && QTDIR)){
+ if(!strcmp(name, "..")){
+ fid->qid = (Qid) {0, 0, QTDIR};
+ *qid = fid->qid;
+ closesem(s);
+ fid->aux = nil;
+ return nil;
+ }
+ }else{
+ for(i = 0; i < Nsems; i++)
+ if(sems[i] && !strcmp(name, sems[i]->name)){
+ fid->qid = (Qid){i, 0, 0};
+ incref(sems[i]);
+ closesem(fid->aux);
+ fid->aux = sems[i];
+ *qid = fid->qid;
+ return nil;
+ }
+ }
+ return "no such file";
+}
+
+static char *
+fsclone(Fid *fid, Fid *newfid)
+{
+ Sem *s;
+
+ s = fid->aux;
+ if(s != nil)
+ incref(s);
+ newfid->aux = s;
+ return nil;
+}
+
+static void
+fsstat(Req *r)
+{
+ Fid *fid;
+ Qid q;
+
+ fid = r->fid;
+ q = fid->qid;
+ if(q.type & QTDIR)
+ getdirent(-1, &r->d, nil);
+ else
+ getdirent(q.path, &r->d, nil);
+ respond(r, nil);
+}
+
+static void
+freefid(Fid *fid)
+{
+ Sem *s;
+
+ s = fid->aux;
+ fid->aux = nil;
+ closesem(s);
+}
+
+static Srv sfs =
+{
+ .attach = fsattach,
+ .create = fscreate,
+ .remove = fsremove,
+ .read = fsread,
+ .write = fswrite,
+ .walk1 = fswalkl,
+ .clone = fsclone,
+ .stat = fsstat,
+ .destroyfid = freefid,
+};
+
+
+void
+usage(void)
+{
+ fprint(2, "usage: %s [-D] [-s srv] [-m mnt]\n", argv0);
+ threadexitsall("usage");
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+ char *mnt, *srv;
+
+ srv = nil;
+ mnt = "/mnt/sem";
+ ARGBEGIN{
+ case 'D':
+ chatty9p++;
+ break;
+ case 's':
+ srv = EARGF(usage());
+ break;
+ case 'm':
+ mnt = EARGF(usage());
+ break;
+ default:
+ usage();
+ }ARGEND;
+
+ if(argc != 0)
+ usage();
+ threadpostmountsrv(&sfs, srv, mnt, MREPL|MCREATE);
+ threadexits(nil);
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,15 @@
+</$objtype/mkfile
+
+TARG = cursedfs
+
+OFILES = \
+ cursed.$O \
+ cursedfs.$O
+
+HFILES = \
+ cursed.h \
+ 9curses.h
+
+BIN = $home/bin/$objtype
+
+</sys/src/cmd/mkone