use libString insead of static character arrays where useful, added some data structure stuff for realm master, random, and scope
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEkFh6dA+k/6CXFXU4O3+8IhROY5gFAmD3R0UACgkQO3+8IhRO Y5iFiQ//TGkXRVpk0HCXXk4N7CGh8BbrjqHY6G4TUdby2rHmXz9TU/7WN1LTI5eS bMIZKr7nV21elIaHkjN5PUe9v4NwMz62cyvCQDiVlDsKdNVR+cnJYnKUKNqIJTmJ mL364zEaap1B8Aur522iwwH2GdxpICNJZuQc1vYTglHheLQGIqWtd7RpngbzpNhg kN2kPxbfwgpYrEMq0yyQ0GZRM2wvHTROsVNsScKLRCjXW6Rhvqvs5+6bd3TfGqMP hc5JHKMrOZhJixPg0naHCAFfG7JiUkDbhsQBCXdUG66ZLo+q+GHknMLCb3QPEHMF sO83zWDF18p3s4wkt1SI7BijFuUErgbCmm+os8ugmQYJOS3s8Cif7x2WvTJoxH9X kXiA4d370D29sYxQsunCGprgKAIu7u4TqeG67JWioY30D5d88xYb1mTOb70hS47X 9DVLfJHlmn02/M69x3rXrw6m0F4FXH2iB54aMGYvWSG2i7TEEjxhvnlR3dFnCh+L KvgJwapZWgdCMeRot9i7pCP/VrIv1PFAAevDu75TAhWL9tNZKhB//AeSadlb20tC h+rtsbXXzMAgaTAfGOhj+3PU4B/i03WnaBmAGF7DZW9mjroxTc90Gc3E/IJbAfgP jKvSn5ub75vJcRAXxCb2PBHnkCA1AcU/KkHOFL3jDy9RIuZZ7eE= =eirs -----END PGP SIGNATURE-----
M
README.md
→
README.md
@@ -13,7 +13,8 @@ * `login PW`: Authenticate with `xrxs` -- password is hashed against realm password hash
* `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 @@ ## realm format
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...
M
realm.c
→
realm.c
@@ -45,6 +45,7 @@ scpy(name, self->name, 32);
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 @@ f = fopen(file, "r");
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 @@
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");
M
realm.h
→
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);
M
xrxs.c
→
xrxs.c
@@ -77,6 +77,11 @@ for (i = 0; i < 64; i++) {
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 @@
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 @@ break;
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 @@ respond(r, nil);
} 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 @@ self[i] = nil;
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 @@ char realm_path[128] = {0};
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 @@ realms = list_dir(realm_path);
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 @@ scmp(users_table[i].realm->name, realm->name))
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 @@ case REALMS:
read_realms(r); break; case UNIVERSE: - // read_universe(r); + read_universe(r); break; case SCOPE: // read_scope(r);