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;
+}
--
⑨