diff --git a/README.md b/README.md index 62c9427..1676442 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,8 @@ This is the working structure of the 9p filesystem: * `load CART`: Load a cartridge * `chunk TYPE N`: Load data of type TYPE and chunk number N * `create REALM`: Create a new realm (start a new game) -- must have a cartridge loaded - * `protect REALM PW`: Protect the realm with a password if not already. + * `protect PW`: Protect the curent realm with a password if you are the master. + * `transfer USER`: Transfer ownership of the realm to another user. * `enter REALM`: Join an existing realm * `leave`: Leave the current realm * `unload`: Unload the cartridge @@ -40,7 +41,7 @@ This is the working structure of the 9p filesystem: Each realm directory on the server should have the following files: - * `realm`: Basic data for the realm, file should contain only the maximum number of members, and the password hash, if any, separated by a space - * `universe`: The actual game state in for the realm, key value pairs, one per line, as `KEY = VALUE`; limit 15 characters for keys, 63 for values. + * `realm`: Basic data for the realm, file should contain only the maximum number of members, the master's name, and the password hash, if any (otherwise 0), separated by spaces. + * `universe`: The actual game state for the realm as key value pairs, one per line, like `KEY = VALUE`; limit 15 characters for keys, 63 for values. The realm should be synchronized to disc when realm membership, limit, or password change. Fenagling some periodic autosave should be possible... \ No newline at end of file diff --git a/command.h b/command.h index ed30220..4860bd1 100644 --- a/command.h +++ b/command.h @@ -1,8 +1,10 @@ typedef enum { LOGIN = 208176873, LOAD = 5626172, + CHUNK = 190974201, CREATE = 7083959236, PROTECT = 295480618573, + TRANSFER = 11311529048177, ENTER = 195024746, LEAVE = 207662601, LOGOUT = 7702552890, diff --git a/realm.c b/realm.c index 5d1e346..296d8d6 100644 --- a/realm.c +++ b/realm.c @@ -45,6 +45,7 @@ Realm* create_realm(UserInfo* table, char* uname, char* name) { self->max = max; self->password = 0; self->universe = create_universe(); + scpy(uname, self->master, 32); save_realm(cart, self); fprintf(stderr, "created realm '%s'\n", name); return self; @@ -68,7 +69,7 @@ Realm* parse_realm(char* cart, char* name) { if (f != nil) { if (fgets(buf, 256, f)) { self = malloc(sizeof(Realm)); - sscanf(buf, "%hu %llu", &(self->max), &(self->password)); + sscanf(buf, "%hu %32s %llu", &(self->max), self->master, &(self->password)); fclose(f); } else { return nil; @@ -108,7 +109,7 @@ void save_realm(char* cart, Realm* self) { scat(file, "/realm"); f = fopen(file, "w"); if (f != nil) { - fprintf(f, "%hu %llu", self->max, self->password); + fprintf(f, "%hu %s, %llu", self->max, self->master, self->password); fclose(f); save_universe(cart, self->universe, self->name); fprintf(stderr, "saved realm data"); diff --git a/realm.h b/realm.h index 822a55f..10c5ba3 100644 --- a/realm.h +++ b/realm.h @@ -3,12 +3,13 @@ typedef struct UserInfo UserInfo; typedef struct Realm { char name[32]; + char master[32]; ushort max; uvlong password; Universe* universe; } Realm; -Realm* create_realm(UserInfo* table, char* cart, char* name); +Realm* create_realm(UserInfo* table, char* uname, char* name); Realm* parse_realm(char* cart, char* name); Realm* find_realm(UserInfo* table, char* name); void save_realm(char* cart, Realm* self); diff --git a/user.h b/user.h index 09c5cb3..19fdde2 100644 --- a/user.h +++ b/user.h @@ -5,6 +5,8 @@ typedef struct UserInfo { uvlong password; Cart* cart; Realm* realm; + char* scope; + int random; } UserInfo; UserInfo* find_user(UserInfo* table, char* uname); diff --git a/xrxs.c b/xrxs.c index abbbdc3..e9a09aa 100644 --- a/xrxs.c +++ b/xrxs.c @@ -77,6 +77,11 @@ int logout(char* uname) { if (scmp(uname, u->name)) { *(u->name) = 0; u->password = 0; + if (u->scope != nil) { + free(u->scope); + u->scope = nil; + } + u->random = 0; if (u->realm != nil) leave_realm(users_table, uname); if (u->cart != nil) @@ -91,7 +96,7 @@ int logout(char* uname) { void protect(char* uname, char* password) { UserInfo* u = find_user(users_table, uname); - if (u != nil && u->realm != nil) { + if (u != nil && u->realm != nil && scmp(uname, u->realm->master)) { u->realm->password = hash(password, 0); } } @@ -117,12 +122,17 @@ void write_ctl(Req* r) { case LOAD: load_cart(users_table, r->fid->uid, c); break; + case CHUNK: + // get_chunk(users_table, r->fid->uid, c); + break; case CREATE: create_realm(users_table, r->fid->uid, c); break; case PROTECT: protect(r->fid->uid, c); break; + case TRANSFER: + // transfer(r->fid->uid, c); case ENTER: enter_realm(users_table, r->fid->uid, c); break; @@ -222,13 +232,18 @@ void read_users(Req* r) { } String** list_dir(char* path) { - String** self = malloc(128 * sizeof(String*)); + int size = 128; + String** self = malloc(size * sizeof(String*)); DIR* dir; struct dirent* ent; int i = 0; char* c; if ((dir = opendir(path)) != NULL) { while ((ent = readdir(dir)) != NULL) { + if (i = size) { + size *= 2; + self = reallloc(self, size * sizeof(String*)); + } c = ent->d_name; if (scmp(c, ".") || scmp(c, "..")) { continue; @@ -246,17 +261,38 @@ String** list_dir(char* path) { return self; } +void s_freemany(String** ss) { + int i; + String** s = ss; + for (i = 0; i < 128; i++) { + if (*s != nil) { + s_free(*s); + } + } + free(ss); +} + +String* s_putmanyc(String* s, char* c) { + String* tmp = s_copy(c); + s_append(s, tmp); + s_free(tmp); + return s; +} + void read_carts(Req* r) { String** carts = list_dir(CARTSPATH); String** c = carts; - char data[4096] = {0}; + string* data = s_new(); while (*c != nil) { - scat(data, (*c)->base); - ccat(data, '\n'); + s_append(data, *c); + s_putc(data, '\n'); c++; } - readstr(r, data); + s_terminate(data); + readstr(r, data->base); respond(r, nil); + s_free(data); + s_freemany(carts); } void read_slot(Req* r) { @@ -299,7 +335,7 @@ void read_realms(Req* r) { String** realms; String** rr; Realm* realm; - char data[4096] = {0}; + String* data = s_new(); int i, u, m, p; char ubuf[8] = {0}; char mbuf[8] = {0}; @@ -316,8 +352,8 @@ void read_realms(Req* r) { rr = realms; while (*rr != nil) { - scat(data, (*rr)->base); - ccat(data, ' '); + s_append(data, *rr); + s_putc(data, ' '); realm = parse_realm(user->cart->name, (*rr)->base); m = realm->max; @@ -330,18 +366,51 @@ void read_realms(Req* r) { u++; } itoa(u, ubuf, 10); - scat(data, ubuf); - ccat(data, ' '); + s_putmanyc(data, ubuf); + s_putc(data, ' '); itoa(m, mbuf, 10); - scat(data, mbuf); - ccat(data, ' '); + s_putmanyc(data, mbuf); + s_putc(data, ' '); itoa(p, pbuf, 10); - scat(data, pbuf); - ccat(data, '\n'); + s_putmanyc(data, pbuf); + s_putc(data, '\n'); rr++; } - readstr(r, data); + s_terminate(data); + readstr(r, data->base); respond(r, nil); + s_free(data); + s_freemany(realms); +} + +void read_universe(Req* r) { + char* uname = r->fid->uid; + UserInfo* u = find_user(users_table, uname); + String* data = s_new(); + Universe* universe; + Atom* a; + int i; + + if (u == nil || u->realm == nil) { + respond(r, nil); + return; + } + + universe = u->realm->universe; + for (i = 0; i < 256; i++) { + a = universe[i]; + while (a != nil) { + s_putmanyc(data, a->name); + s_putmanyc(data, " = "); + s_putmanyc(data, a->value); + s_putc(data, '\n'); + a = a->next; + } + } + s_terminate(data); + readstr(r, data->base); + respond(r, nil); + s_free(data); } void xrxs_read(Req* r) { @@ -365,7 +434,7 @@ void xrxs_read(Req* r) { read_realms(r); break; case UNIVERSE: - // read_universe(r); + read_universe(r); break; case SCOPE: // read_scope(r);