implemented some more functions and started putting it all together... realms aren't being saved on leaving; something's up
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEkFh6dA+k/6CXFXU4O3+8IhROY5gFAmDtQgoACgkQO3+8IhRO Y5guQhAAhxh+WvBfBLGBLhZnrsiMbhUGRWfUfgHaBmwnEOyNaxoftkPvB8DoFZAK vrzD5wpPVFMd9jrbpsdQ0ZN0MXSpNqODsgzY13lZntrCy9UtVLaqc6je1nlZgF8n VQYsrgtkqYaiLhSI/KsQkbz5aDhoxikXgJktCDUD2H/7Zxg1HyXb4/7FB/m7l8y7 1sXjZXo58f5hu/bVG9sEPjHeKosQyV8HpHf4n94k4e1RgvpmCWPbu7/CKeGPMkrT vm4+AoYvGJfK8EEvhEQ62D9vGgThS3oiDBpFBKHKDpARcsb6v2onbsznnSiAoLC6 JhMBgq/vEaBzm6qIykaqjQuY2j9wRYQ5havJggj+20g8JHs2Z6X7qB0NieoWKhOH 5RqdHOyrGogqAslajQA/kVag4hJQCLgrReXJD4faWb9xBqPPv14fZz7ihUBwgEcp ErkkVw8yO1tTzx6PVtzAZCUlXZTgVaxbZOXMxZ/kY82zxfz/1O8h6kXxqWCuFzBo jnErxm45q2zx6Hfl/2y21/AFRHJLEuo+lrY4JJIRMIR9Grkd1vgxZyMfIH/WNXbs HnWjdZg4uRht8UK+eUgWZQMVRnt8tanGXb982BJF8Lsq2rvyw3f2D4yaqqO0eJUN XZ8FATPJsoeN08robXT/ggvtXJgkUUyqtUE8Ggg96qt3K56iiQ8= =ZdkP -----END PGP SIGNATURE-----
M
realm.c
→
realm.c
@@ -35,10 +35,14 @@ scpy(path, file, 64);
scat(file, "/realm"); f = fopen(file, "r"); - if (fgets(buf, 256, f)) { - self = malloc(sizeof(Realm)); - sscanf(buf, "%hu %llu", &(self->max), &(self->password)); - fclose(f); + if (f != nil) { + if (fgets(buf, 256, f)) { + self = malloc(sizeof(Realm)); + sscanf(buf, "%hu %llu", &(self->max), &(self->password)); + fclose(f); + } else { + return nil; + } } else { return nil; }@@ -58,6 +62,32 @@ if (slen(u->name) > 0 && u->realm != nil && scmp(u->realm->name, name))
return u->realm; u++; } + return nil; } -void save_realm(Realm* self) {}+void save_realm(Realm* self) { + FILE* f; + char path[64]; + char file[64]; + scat(path, "realms/"); + scat(path, self->name); + scpy(path, file, 64); + + scat(file, "/realm"); + f = fopen(file, "w"); + if (f != nil) { + fprintf(f, "%hu %llu", self->max, self->password); + fclose(f); + save_universe(self->universe, self->name); + } +} + +void destroy_realm(Realm* self) { + if (self != nil) { + if (self->universe != nil) { + destroy_universe(self->universe); + } + free(self); + self = nil; + } +}
M
user.c
→
user.c
@@ -0,0 +1,100 @@
+#include <u.h> +#include <libc.h> +#include "util.h" +#include "cart.h" +#include "realm.h" +#include "user.h" + +extern UserInfo users_table[64]; + +UserInfo* find_user(UserInfo* table, char* uname) { + UserInfo* u = table; + int i; + for (i = 0; i < 64; i++) { + if (scmp(uname, u->name)) + return u; + u++; + } + return nil; +} + +int load_cart(UserInfo* table, char* uname, char* cart_name) { + Cart* c = find_cart(table, cart_name); + UserInfo* u = find_user(table, uname); + + if (u == nil) + return 0; + + if (c != nil) { + u->cart = c; + return 1; + } else { + u->cart = create_cart(cart_name); + if (u->cart == nil) + return 0; + else + return 1; + } +} + +int enter_realm(UserInfo* table, char* uname, char* realm_name) { + Realm* r = find_realm(table, realm_name); + UserInfo* u = find_user(table, uname); + int i, j; + + if (u == nil || u->cart == nil) + return 0; + + for (i = j = 0; i < 64; i++) { + if (table[i].realm != nil && scmp(table[i].realm->name, realm_name)) + j++; + } + if (j >= r->max) + return 0; + + if (r != nil) { + u->realm = r; + return 1; + } else { + u->realm = parse_realm(realm_name); + if (u->realm == nil) + return 0; + else + return 1; + } +} + +int leave_realm(UserInfo* table, char* uname) { + UserInfo* u = find_user(table, uname); + Realm* r; + + if (u == nil) + return 0; + + r = u->realm; + if (r == nil) + return 0; + + save_realm(r); + u->realm = nil; + if (find_realm(table, r->name) == nil) + destroy_realm(r); + return 1; +} + +int unload_cart(UserInfo* table, char* uname) { + UserInfo* u = find_user(table, uname); + Cart* c; + + if (u == nil) + return 0; + + c = u->cart; + if (c == nil) + return 0; + + u->cart = nil; + if (find_cart(table, c->name) == nil) + destroy_cart(c); + return 1; +}
M
user.h
→
user.h
@@ -7,7 +7,8 @@ Cart* cart;
Realm* realm; } UserInfo; -int load_cart(char* uname, char* cart_name); -int enter_realm(char* uname, char* realm_name); -int leave_realm(char* uname, Realm* realm); -int unload_cart(char* uname, Cart* cart); +UserInfo* find_user(UserInfo* table, char* uname); +int load_cart(UserInfo* table, char* uname, char* cart_name); +int enter_realm(UserInfo* table, char* uname, char* realm_name); +int leave_realm(UserInfo* table, char* uname); +int unload_cart(UserInfo* table, char* uname);
M
util.c
→
util.c
@@ -138,4 +138,49 @@ } else {
fclose(f); return buf; } +} + +void strreverse(char* begin, char* end) { + + char aux; + + while (end > begin) + + aux = *end, *end-- = *begin, *begin++ = aux; +} + +void itoa(int value, char* str, int base) { + + static char num[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + + char* wstr = str; + + int sign; + + // Validate base + + if (base < 2 || base > 35) { + *wstr = '\0'; + return; + } + + // Take care of sign + + if ((sign = value) < 0) + value = -value; + + // Conversion. Number is reversed. + + do + *wstr++ = num[value % base]; + while (value /= base); + + if (sign < 0) + *wstr++ = '-'; + + *wstr = '\0'; + + // Reverse string + + strreverse(str, wstr - 1); }
M
xrxs.c
→
xrxs.c
@@ -6,6 +6,7 @@ #include <9p.h>
#include <stdio.h> #include <dirent.h> #include <libString.h> +#include <string.h> #include "err.h" #include "command.h" #include "util.h"@@ -14,6 +15,9 @@ #include "cart.h"
#include "universe.h" #include "realm.h" #include "user.h" + +#define CARTSPATH "./carts" +#define REALMSPATH "./realms" int chatty9p = 1;@@ -67,95 +71,29 @@ }
int logout(char* uname) { int i; - fprintf(stderr, uname); + UserInfo* u = users_table; + for (i = 0; i < 64; i++) { - if (scmp(uname, users_table[i].name)) { - *(users_table[i].name) = 0; - users_table[i].password = 0; - /* free cart */ - /* free realm */ + if (scmp(uname, u->name)) { + *(u->name) = 0; + u->password = 0; + if (u->realm != nil) + leave_realm(users_table, uname); + if (u->cart != nil) + unload_cart(users_table, uname); return 1; } + u++; } return 0; } -int load(char* uname, char* cart) { - /* 1. get file handle to cartridge file - * 2. make cartridge file available in CART.data for this user - * 3. add cartridge name to user's UserInfo - * 4. if cartridge data dir is not empty, walk it - * 5. for each file in data dir, create corresponding - * data file in DATA/ for this user, grab a file handle, and make - * the data available in DATA.data - */ - return 1; -} - -int rcreate(char* realm) { // create is taken in the libc header! - /* 1. split input by space -- if 2+ elements, second element - * is the max number of members (default 4) - * 2. check if realm exists; return 0 if it does - * 3. create real files in the realms directory and fill as - * appropriate - */ - return 1; -} - -int protect(char* password) { - /* 1. if current realm has a password already, return 0; - * 2. otherwise, hash the password and put it after the - * member limit in the realm file - */ - return 1; -} - -int enter(char* uname, char* realm) { - /* 1. get password for realm; if none, skip to 3 - * 2. check password for current user against it; - * return 0 if different - * 3. if member limit already met, return 0 - * 4. otherwise, insert username in the realm - * and the realm name in the user's UserInfo - */ - return 1; -} - -int leave(char* uname) { - /* 1. if not in a realm, return 0; - * 2. else remove self from realm file - * and remove realm from user's UserInfo - */ - return 1; -} - -int save(char* uname) { - /* 1. flush this user's universe to the realm; - * maybe this is not needed - */ - return 1; -} - -int reset(char* uname) { - /* 1. save - * 2. leave - * 3. clear this user's password - * 4. the client should now be able to restart execution - * of the cartridge safely - */ - return 1; -} +void protect(char* uname, char* password) { + UserInfo* u = find_user(users_table, uname); -int unload(char* uname) { - /* 1. reset - * 2. clear cartridge data from CART->data for this user - * 3. destroy all files in DATA/ for this user - * 4. remove cartridge from UserInfo for thi user - * 5. the client should now be able to unload - * the cartridge from memory safely and restart - * the 'firmware' ROM execution - */ - return 1; + if (u != nil && u->realm != nil) { + u->realm->password = hash(password, 0); + } } void write_ctl(Req* r) {@@ -166,6 +104,9 @@
for (i = 0; i < r->ifcall.count && *c != ' ' && *c != '\n'; i++) { ccat(cmd, *c++); } + if (*c == ' ') + c++; + fprintf(stderr, cmd); uvlong const cmd_hashv = hash(cmd, 0); switch (cmd_hashv) {@@ -173,19 +114,19 @@ case LOGIN:
login(r->fid->uid, c); break; case LOAD: - // load(r->fid->uid, c); + load_cart(users_table, r->fid->uid, c); break; case CREATE: - // rcreate(c); + create_realm(c); break; case PROTECT: - // protect(c); + protect(r->fid->uid, c); break; case ENTER: - // enter(r->fid->uid, c); + enter_realm(users_table, r->fid->uid, c); break; case LEAVE: - // leave(r->fid->uid); + leave_realm(users_table, r->fid->uid); break; case LOGOUT: logout(r->fid->uid);@@ -197,7 +138,7 @@ case RESET:
// reset(r->fid->uid); break; case UNLOAD: - // unload(r->fid->uid); + unload_cart(users_table, r->fid->uid); break; } r->ofcall.count = r->ifcall.count;@@ -205,6 +146,39 @@ r->fid->file->dir.length = r->ifcall.count;
respond(r, nil); } +void write_universe(Req* r) { + char key[16] = {0}; + char value[64] = {0}; + char* c = r->ifcall.data; + UserInfo* u = find_user(users_table, r->fid->uid); + Atom* a; + int i; + + for (i = 0; i < 15 && i < r->ifcall.count && *c != ' ' && *c != '\n'; i++) { + ccat(key, *c++); + } + c++; + for (i = 0; i < 63 && i < r->ifcall.count && *c != ' ' && *c != '\n'; i++) { + ccat(value, *c++); + } + + if (u != nil && u->realm != nil && u->realm->universe != nil) { + a = get_atom(u->realm->universe, key); + if (a != nil) { + scpy(value, a->value, 64); + } else { + a = malloc(sizeof(Atom)); + scpy(key, a->name, 16); + scpy(value, a->value, 64); + a->next = nil; + set_atom(u->realm->universe, a); + } + } + r->ofcall.count = r->ifcall.count; + r->fid->file->dir.length = r->ifcall.count; + respond(r, nil); +} + void xrxs_write(Req* r) { Aux* a = r->fid->file->aux; switch (a->type) {@@ -212,7 +186,7 @@ case CTL:
write_ctl(r); break; case UNIVERSE: - // write_universe(r); + write_universe(r); break; default: respond(r, nil);@@ -244,6 +218,117 @@ readstr(r, buf);
respond(r, nil); } +String** list_dir(char* path) { + String** self = malloc(128 * sizeof(String*)); + DIR* dir; + struct dirent* ent; + int i = 0; + char* c; + if ((dir = opendir(path)) != NULL) { + while ((ent = readdir(dir)) != NULL) { + c = ent->d_name; + if (scmp(c, ".") || scmp(c, "..")) { + continue; + } + self[i] = s_new(); + + while (*c) { + s_putc(self[i], *c++); + } + s_terminate(self[i++]); + } + closedir(dir); + } + self[i] = nil; + return self; +} + +void read_carts(Req* r) { + String** carts = list_dir(CARTSPATH); + String** c = carts; + char data[4096] = {0}; + while (*c != nil) { + scat(data, (*c)->base); + ccat(data, '\n'); + c++; + } + readstr(r, data); + respond(r, nil); +} + +void read_slot(Req* r) { + UserInfo* u = find_user(users_table, r->fid->uid); + if (u == nil) + goto end; + + if (u->cart == nil) + goto end; + + readstr(r, u->cart->rom); +end: + respond(r, nil); +} + +void read_data(Req* r, FileType t) { + UserInfo* u = find_user(users_table, r->fid->uid); + + if (u->cart == nil) + goto end; + + switch (t) { + case SPRITE_DATA: + readstr(r, u->cart->sprite_data); + break; + case AUDIO_DATA: + readstr(r, u->cart->audio_data); + break; + case TEXT_DATA: + readstr(r, u->cart->txt_data); + break; + } +end: + respond(r, nil); +} + +void read_realms(Req* r) { + String** realms = list_dir(REALMSPATH); + String** rr = realms; + Realm* realm; + char data[4096] = {0}; + int i, u, m, p; + char ubuf[8] = {0}; + char mbuf[8] = {0}; + char pbuf[2] = {0}; + + while (*rr != nil) { + scat(data, (*rr)->base); + ccat(data, ' '); + + realm = parse_realm((*rr)->base); + m = realm->max; + p = realm->password ? 1 : 0; + + for (i = u = 0; i < 64; i++) { + if ( + users_table[i].realm != nil && + scmp(users_table[i].realm->name, realm->name)) + u++; + } + itoa(u, ubuf, 10); + scat(data, ubuf); + ccat(data, ' '); + itoa(m, mbuf, 10); + scat(data, mbuf); + ccat(data, ' '); + itoa(p, pbuf, 10); + scat(data, pbuf); + ccat(data, '\n'); + rr++; + } + readstr(r, data); + respond(r, nil); +} + void xrxs_read(Req* r) { Aux* a = r->fid->file->aux; switch (a->type) {@@ -251,16 +336,18 @@ case USERS:
read_users(r); break; case CARTS: - // read_carts(r); + read_carts(r); break; case SLOT: - // read_slot(r); + read_slot(r); break; - case DATA: - // read_data(r); + case SPRITE_DATA: + case AUDIO_DATA: + case TEXT_DATA: + read_data(r, a->type); break; case REALMS: - // read_realms(r); + read_realms(r); break; case UNIVERSE: // read_universe(r);@@ -281,31 +368,6 @@ free(a);
} } -String** listdir(char* path) { - String** self = malloc(128 * sizeof(String*)); - DIR* dir; - struct dirent* ent; - int i = 0; - char* c; - if ((dir = opendir(path)) != NULL) { - while ((ent = readdir(dir)) != NULL) { - c = ent->d_name; - if (scmp(c, ".") || scmp(c, "..")) { - continue; - } - self[i] = s_new(); - - while (*c) { - s_putc(self[i], *c++); - } - s_terminate(self[i++]); - } - closedir(dir); - } - self[i] = nil; - return self; -} - Srv fs = {.attach = xrxs_attach, .read = xrxs_read, .write = xrxs_write}; int threadmaybackground(void) { return 1; }@@ -314,7 +376,6 @@ void threadmain(int argc, char* argv[]) {
char* mtpt = nil; char* usocket = nil; int i; - String** cart; /* if -h CMD is given, print the hash value of CMD */ if (argc == 3 && scmp(argv[1], "-h")) {@@ -348,16 +409,31 @@ closefile(createfile(tree->root, "carts", nil, 0400, create_aux(CARTS)));
closefile(createfile(tree->root, "users", nil, 0400, create_aux(USERS))); closefile(createfile(tree->root, "slot", nil, 0400, create_aux(SLOT))); closefile(createfile(tree->root, "data", nil, DMDIR | 0500, nil)); + closefile(createfile( + walkfile(tree->root, "data"), + "sprite", + nil, + 0400, + create_aux(SPRITE_DATA))); + closefile(createfile( + walkfile(tree->root, "data"), + "audio", + nil, + 0400, + create_aux(AUDIO_DATA))); + closefile(createfile( + walkfile(tree->root, "data"), + "text", + nil, + 0400, + create_aux(TEXT_DATA))); closefile(createfile(tree->root, "realms", nil, 0400, create_aux(REALMS))); - closefile( - createfile(tree->root, "universe", nil, 0600, create_aux(UNIVERSE))); - /*String** carts = listdir("carts/"); - cart = carts; - - while (*cart) { - // just concatenate the carts into a multiline string, and put it in - CARTS.data - }*/ + closefile(createfile( + tree->root, + "universe", + nil, + DMAPPEND | 0600, + create_aux(UNIVERSE))); if (argc >= 3) { if (mtpt != nil && access(mtpt, AEXIST) < 0 && access(mtpt, AEXIST) < 0)