ref: 4161df5fd7487feaf4758b93a8d8371bec433471
parent: b402639434e9360c99fc8b9cb12d51614abfbeea
author: sirjofri <sirjofri@sirjofri.de>
date: Sat Jul 19 17:14:03 EDT 2025
working filesystem with async reads (works with con -C)
--- a/cmd.c
+++ b/cmd.c
@@ -6,18 +6,38 @@
#include "version.h"
static void
-cversion(Request *r)
+cversion(User *u, Request *r)
{ if (r->args[0]) {fprint(2, "get version of '%s' (not implemented yet!)\n", r->args[0]);
- reply(Enosuchserver, r->args[0]);
+ reply(u, Enosuchserver, r->args[0]);
return;
}
- reply(Rversion, getversion());
+ reply(u, Rversion, getversion());
}
+static void
+cuser(User *u, Request *r)
+{+ // TODO: how to respond without knowing the user?
+ if (!r->args[3]) {+ fprint(2, "user without enough args%R\n", *r);
+ // reply(u, Eneedmoreparams, r->cmd.name);
+ return;
+ }
+ u = finduser(r->args[0]);
+ if (u) {+ fprint(2, "user already registered%R\n", *r);
+ // reply(u, Ealreadyregistered);
+ return;
+ }
+ u = adduser(r->args[0]);
+ setuser(u);
+}
+
static Command commands[] = { { "version", cversion },+ { "user", cuser },};
int ncommands = sizeof(commands) / sizeof(Command);
@@ -38,7 +58,7 @@
}
void
-execrequest(Request r)
+execrequest(User *u, Request r)
{ if (!(r.cmd && r.cmd->func)) {fprint(2, "cannot execute request: no command\n");
@@ -46,5 +66,5 @@
}
if (debug)
fprint(2, "run command '%s'\n", r.cmd->name);
- r.cmd->func(&r);
+ r.cmd->func(u, &r);
}
--- a/cmd.h
+++ b/cmd.h
@@ -7,3 +7,13 @@
.nr = 402,
.msg = "%s :No such server",
};
+
+Reply Eneedmoreparams = {+ .nr = 461,
+ .msg = "%s :Not enough parameters",
+};
+
+Reply Ealreadyregistered = {+ .nr = 462,
+ .msg = ":Unauthorized command (already registered)",
+};
--- a/dat.h
+++ b/dat.h
@@ -2,6 +2,9 @@
typedef struct Request Request;
typedef struct Command Command;
typedef struct Reply Reply;
+typedef struct User User;
+typedef struct Replybuffer Replybuffer;
+typedef struct Userlist Userlist;
#pragma varargck type "R" Request
@@ -22,7 +25,7 @@
struct Command
{char *name;
- void (*func)(Request*);
+ void (*func)(User*,Request*);
};
struct Reply
@@ -31,4 +34,25 @@
char *msg;
};
+struct Replybuffer
+{+ QLock;
+ void *reply;
+};
+
+struct User
+{+ char *name;
+ Replybuffer replies;
+
+ User *prev;
+ User *next;
+};
+
+struct Userlist
+{+ User *first;
+};
+
extern int debug;
+extern char* sysnameb;
--- a/fns.h
+++ b/fns.h
@@ -2,11 +2,17 @@
Command* findcommand(char*);
Command* findcommandn(int);
-void execrequest(Request);
+void execrequest(User*, Request);
void clearrequest(Request);
-void reply(Reply, ...);
-int hasreplies(char*);
+void setuser(User*);
+void reply(User*, Reply, ...);
+char *getreplies(User*);
+void flushreplies(User*);
int Rfmt(Fmt *f);
char *getversion(void);
+
+User* adduser(char*);
+void deluser(User*);
+User* finduser(char*);
--- a/ircd.c
+++ b/ircd.c
@@ -13,11 +13,11 @@
usage(void)
{fprint(2, "usage: %s\n", argv0);
- exits("usage");+ threadexitsall("usage");}
static Biobuf *bio;
-static char *sysnameb = "nil";
+char *sysnameb = "nil";
static char *versionstring = nil;
int debug = 0;
@@ -31,43 +31,39 @@
return versionstring;
}
-static void
-parselines(void)
-{- char *line;
- Request parsedrequest;
-
- while (line = Brdstr(bio, '\n', 1)) {- parsedrequest = parseline(line);
- if (debug > 1)
- fprint(2, "request: %R\n", parsedrequest);
- execrequest(parsedrequest);
- free(line);
- }
-}
-
char *mtpt = "/mnt/ircd";
char *srvname = "ircd";
Reqqueue *reqqueue = nil;
+User *ircuser = nil;
-// TODO: implement hasdata for client. put all replies in a bulk buffer.
-int hasdata = 0;
-QLock datalock;
+void
+setuser(User *u)
+{+ ircuser = u;
+}
static void
readproc(Req *r)
{+ char *repl;
+
+ threadsetname("readproc");+
+ if (!ircuser) {+ respond(r, nil);
+ return;
+ }
+
while (1) {- qlock(&datalock);
- if (hasdata) {- readstr(r, "hasdata\n");
- fprint(2, "responded with hasdata\n");
- hasdata = 0;
- qunlock(&datalock);
+ qlock(&ircuser->replies);
+ repl = getreplies(ircuser);
+ if (repl) {+ readstr(r, repl);
+ qunlock(&ircuser->replies);
respond(r, nil);
return;
}
- qunlock(&datalock);
+ qunlock(&ircuser->replies);
}
}
@@ -99,12 +95,8 @@
parsed = parseline(line);
if (debug > 1)
fprint(2, "request:%R", parsed);
- execrequest(parsed);
+ execrequest(ircuser, parsed);
- qlock(&datalock);
- hasdata = 1;
- qunlock(&datalock);
-
respond(r, nil);
}
@@ -140,7 +132,7 @@
break;
case 'v':
fprint(2, "version: %s\n", getversion());
- exits(nil);
+ threadexitsall(nil);
case 's':
srvname = EARGF(usage());
break;
@@ -163,17 +155,5 @@
fs.tree = alloctree(nil, nil, DMDIR|0777, nil);
populatetree(fs.tree->root);
threadpostmountsrv(&fs, srvname, mtpt, MREPL|MCREATE);
- exits(nil);
-}
-
-void
-reply(Reply repl, ...)
-{- char buf[511];
- va_list arg;
-
- va_start(arg, repl);
- vsnprint(buf, sizeof buf, repl.msg, arg);
- va_end(arg);
- print(":%s %03d %s\r\n", sysnameb, repl.nr, buf);+ //exits(nil);
}
--- a/mkfile
+++ b/mkfile
@@ -6,6 +6,8 @@
cmd.$O\
parse.$O\
fmt.$O\
+ reply.$O\
+ users.$O\
HFILES=fns.h dat.h cmd.h
--- /dev/null
+++ b/reply.c
@@ -1,0 +1,40 @@
+#include <u.h>
+#include <libc.h>
+#include <String.h>
+#include "dat.h"
+#include "fns.h"
+
+char*
+getreplies(User *u)
+{+ return u->replies.reply;
+}
+
+void
+flushreplies(User *u)
+{+ if (!u->replies.reply)
+ return;
+ free(u->replies.reply);
+ u->replies.reply = nil;
+}
+
+void
+reply(User *u, Reply repl, ...)
+{+ char buf[511];
+ va_list arg;
+ String *s = u->replies.reply;
+
+ snprint(buf, sizeof buf, "%s %03d ", sysnameb, repl.nr);
+ s_append(s, buf);
+
+ va_start(arg, repl);
+ vsnprint(buf, sizeof buf, repl.msg, arg);
+ va_end(arg);
+
+ s_append(s, buf);
+ s_append(s, "\r\n");
+
+ fprint(2, ":%s %03d %s\r\n", sysnameb, repl.nr, buf);
+}
--- /dev/null
+++ b/users.c
@@ -1,0 +1,54 @@
+#include <u.h>
+#include <libc.h>
+#include <String.h>
+#include "dat.h"
+#include "fns.h"
+
+static Userlist users;
+
+User*
+adduser(char *name)
+{+ User *n;
+ n = mallocz(sizeof(User), 1);
+ n->name = strdup(name);
+ n->replies.reply = s_new();
+
+ if (!users.first) {+ users.first = n;
+ return n;
+ }
+ n->next = users.first;
+ users.first->prev = n;
+ users.first = n;
+ return n;
+}
+
+void
+deluser(User *user)
+{+ String *s;
+ if (!user->prev) {+ users.first = user->next;
+ if (user->next)
+ user->next->prev = nil;
+ } else {+ user->prev->next = user->next;
+ if (user->next)
+ user->next->prev = user->prev;
+ }
+ s = user->replies.reply;
+ s_free(s);
+ free(user->name);
+ free(user);
+}
+
+User*
+finduser(char *name)
+{+ for (User *u = users.first; u; u = u->next) {+ if (strcmp(name, u->name) == 0)
+ return u;
+ }
+ return nil;
+}
--
⑨