ref: e6b34aae9701ee0f54ea60d974eeb87058e464db
dir: /main.c/
#include <u.h> #include <libc.h> #include <fcall.h> #include <thread.h> #include <9p.h> enum { Qroot, Qnickname, Qchannels, }; typedef struct Neinfile Neinfile; typedef struct NeinAux NeinAux; struct Neinfile { char *name; Qid qid; ulong mode; }; struct NeinAux { char *nickname; int currentChan; }; void fsattach(Req*); void fsstat(Req*); void fsread(Req*); void fswrite(Req*); char *fsclone(Fid*, Fid*); char *fswalk1(Fid*, char*, Qid*); int rootgen(int, Dir*, void*); int channelsgen(int, Dir*, void*); Neinfile *findfile(uvlong); void fillstat(Dir*, Neinfile); char *username; Neinfile qroot[] = { "nickname", {Qnickname, 0, QTFILE}, 0666, "channels", {Qchannels, 0, QTDIR}, 0555 | DMDIR, }; Neinfile root = {"/", {Qroot, 0, QTDIR}, 555 | DMDIR}; void main(void) { Srv fs = { .attach = fsattach, .walk1 = fswalk1, .clone = fsclone, .stat = fsstat, .read = fsread, .write = fswrite, }; char *postname = "neinchat"; char *addr = "tcp!*!12345"; username = getuser(); print("Starting neinchat server on %s and posting to /srv/%s\n", addr, postname); listensrv(&fs, addr); postmountsrv(&fs, "neinchat", nil, MREPL|MCREATE); exits(nil); } void fsattach(Req *r) { static int nicknamecount; NeinAux *aux; r->fid->qid = root.qid; r->ofcall.qid = r->fid->qid; aux = emalloc9p(sizeof(NeinAux)); aux->nickname = smprint("RandomUser%d", nicknamecount++); aux->currentChan = -1; r->fid->aux = aux; respond(r, nil); } void fsstat(Req *r) { Neinfile *f = findfile(r->fid->qid.path); if(f == nil){ respond(r, "not found"); return; } fillstat(&r->d, *f); respond(r, nil); } void fsread(Req *r) { char *str; NeinAux *aux; switch(r->fid->qid.path){ case Qroot: dirread9p(r, rootgen, nil); respond(r, nil); break; case Qchannels: dirread9p(r, channelsgen, nil); respond(r, nil); break; case Qnickname: aux = r->fid->aux; str = smprint("%s\n", aux->nickname); readstr(r, str); free(str); respond(r, nil); break; default: respond(r, "wut no"); } } void fswrite(Req *r) { NeinAux *aux = r->fid->aux; if(r->fid->qid.path == Qnickname){ if(r->ifcall.count > 64){ respond(r, "nickname too long (max is 64 chars)"); return; } if(r->ifcall.offset != 0){ respond(r, "Can't write at offset"); return; } char *buf = emalloc9p(r->ifcall.count + 1); memcpy(buf, r->ifcall.data, r->ifcall.count); buf[r->ifcall.count] = 0; free(aux->nickname); aux->nickname = buf; r->ofcall.count = r->ifcall.count; respond(r, nil); return; } respond(r, "write prohibited"); } char * fsclone(Fid *old, Fid *new) { new->aux = old->aux; return nil; } char * fswalk1(Fid *fid, char *name, Qid *qid) { int i; if(strcmp("..", name) == 0){ *qid = root.qid; fid->qid = *qid; return nil; } switch(fid->qid.path){ case Qroot: for(i = 0; i < nelem(qroot); i++){ if(strcmp(qroot[i].name, name) == 0){ *qid = qroot[i].qid; fid->qid = *qid; return nil; } } if(strcmp("..", name) == 0){ *qid = root.qid; fid->qid = *qid; return nil; } break; } return "not found"; } int rootgen(int n, Dir *d, void *) { if(n >= nelem(qroot)) return -1; Neinfile f = qroot[n]; fillstat(d, f); return 0; } int channelsgen(int n, Dir *d, void *) { USED(n); USED(d); return -1; } Neinfile * findfile(uvlong path) { int i; if(path == Qroot) return &root; for(i = 0; i < nelem(qroot); i++){ if(qroot[i].qid.path == path) return &qroot[i]; } return nil; } void fillstat(Dir *d, Neinfile f) { d->qid = f.qid; d->mode = f.mode; d->length = 0; d->name = estrdup9p(f.name); d->uid = estrdup9p(username); d->gid = estrdup9p(username); d->muid = estrdup9p(username); d->atime = time(0); d->mtime = time(0); }