int curvezmq_keypair_save (curvezmq_keypair_t *self) { assert (self); // Get printable key strings char *public_key = s_key_to_hex (self->public_key); char *secret_key = s_key_to_hex (self->secret_key); // Set process file create mask to owner access only zfile_mode_private (); // The public key file contains just the public key zconfig_t *root = zconfig_new ("root", NULL); zconfig_t *key = zconfig_new ("public-key", root); zconfig_set_value (key, public_key); zconfig_save (root, "public.key"); // The secret key file contains both secret and public keys key = zconfig_new ("secret-key", root); zconfig_set_value (key, secret_key); zconfig_save (root, "secret.key"); zconfig_destroy (&root); // Reset process file create mask zfile_mode_default (); free (public_key); free (secret_key); return 0; }
static void s_save_metadata_all (zcert_t *self) { zconfig_destroy (&self->config); self->config = zconfig_new ("root", NULL); zconfig_t *section = zconfig_new ("metadata", self->config); zhash_foreach (self->metadata, s_save_metadata, section); char *timestr = zclock_timestr (); zconfig_comment (self->config, " **** Generated on %s by CZMQ ****", timestr); zstr_free (×tr); }
int hydra_post_save (hydra_post_t *self, const char *filename) { assert (self); assert (filename); // Creeate subdirectories if necessary zsys_dir_create ("posts"); zsys_dir_create ("posts/blobs"); // If post content hasn't yet been serialised, write it to disk in the // blobs directory and set the location property to point to it. if (self->content) { assert (!self->location); self->location = zsys_sprintf ("posts/blobs/%s", self->digest); FILE *output = fopen (self->location, "wb"); zchunk_write (self->content, output); zchunk_destroy (&self->content); fclose (output); } zconfig_t *root = zconfig_new ("root", NULL); zconfig_put (root, "/post/ident", hydra_post_ident (self)); zconfig_put (root, "/post/subject", self->subject); zconfig_put (root, "/post/timestamp", self->timestamp); zconfig_put (root, "/post/parent-id", self->parent_id); zconfig_put (root, "/post/mime-type", self->mime_type); zconfig_put (root, "/post/digest", self->digest); zconfig_put (root, "/post/location", self->location); zconfig_putf (root, "/post/content-size", "%ld", self->content_size); zconfig_savef (root, "posts/%s", filename); zconfig_destroy (&root); return 0; }
static int s_save_metadata (const char *name, void *value, void *args) { zconfig_t *item = zconfig_new ((char *) name, (zconfig_t *) args); zconfig_set_value (item, "%s", (char *) value); return 0; }
void zconfig_put (zconfig_t *self, char *path, char *value) { if (*path == '/') path++; // Check length of next path segment char *slash = strchr (path, '/'); int length = strlen (path); if (slash) length = slash - path; // Find or create items starting at first child of root zconfig_t *child = self->child; while (child) { if (strlen (child->name) == length && memcmp (child->name, path, length) == 0) { // This segment exists if (slash) // Recurse to next level zconfig_put (child, slash + 1, value); else zconfig_set_value (child, "%s", value); return; } child = child->next; } // This segment doesn't exist, create it child = zconfig_new (path, self); child->name [length] = 0; if (slash) // Recurse down further zconfig_put (child, slash, value); else zconfig_set_value (child, "%s", value); }
JNIEXPORT jlong JNICALL Java_zconfig__1_1new (JNIEnv *env, jclass c, jstring name, jlong parent) { char *name_ = (char *) (*env)->GetStringUTFChars (env, name, NULL); jlong new_ = (jlong) zconfig_new (name_, (zconfig_t *) parent); (*env)->ReleaseStringUTFChars (env, name, name_); return new_; }
void zconfig_test (bool verbose) { printf (" * zconfig: "); // @selftest // Create temporary directory for test files # define TESTDIR ".test_zconfig" zsys_dir_create (TESTDIR); zconfig_t *root = zconfig_new ("root", NULL); zconfig_t *section, *item; section = zconfig_new ("headers", root); item = zconfig_new ("email", section); zconfig_set_value (item, "*****@*****.**"); item = zconfig_new ("name", section); zconfig_set_value (item, "Justin Kayce"); zconfig_put (root, "/curve/secret-key", "Top Secret"); zconfig_set_comment (root, " CURVE certificate"); zconfig_set_comment (root, " -----------------"); assert (zconfig_comments (root)); zconfig_save (root, TESTDIR "/test.cfg"); zconfig_destroy (&root); root = zconfig_load (TESTDIR "/test.cfg"); if (verbose) zconfig_save (root, "-"); char *email = zconfig_resolve (root, "/headers/email", NULL); assert (email); assert (streq (email, "*****@*****.**")); char *passwd = zconfig_resolve (root, "/curve/secret-key", NULL); assert (passwd); assert (streq (passwd, "Top Secret")); zconfig_save (root, TESTDIR "/test.cfg"); zconfig_destroy (&root); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); zdir_remove (dir, true); zdir_destroy (&dir); // @end printf ("OK\n"); }
// Process message from pipe static void server_control_message (server_t *self) { zmsg_t *msg = zmsg_recv (self->pipe); char *method = zmsg_popstr (msg); if (streq (method, "BIND")) { char *endpoint = zmsg_popstr (msg); self->port = zsocket_bind (self->router, endpoint); zstr_sendf (self->pipe, "%d", self->port); free (endpoint); } else if (streq (method, "PUBLISH")) { char *location = zmsg_popstr (msg); char *alias = zmsg_popstr (msg); mount_t *mount = mount_new (location, alias); zlist_append (self->mounts, mount); free (location); free (alias); } else if (streq (method, "SET ANONYMOUS")) { char *enabled_string = zmsg_popstr (msg); long enabled = atoi (enabled_string); free (enabled_string); // Enable anonymous access without a config file zconfig_put (self->config, "security/anonymous", enabled? "1" :"0"); } else if (streq (method, "CONFIG")) { char *config_file = zmsg_popstr (msg); zconfig_destroy (&self->config); self->config = zconfig_load (config_file); if (self->config) server_apply_config (self); else { printf ("E: cannot load config file '%s'\n", config_file); self->config = zconfig_new ("root", NULL); } free (config_file); } else if (streq (method, "SETOPTION")) { char *path = zmsg_popstr (msg); char *value = zmsg_popstr (msg); zconfig_put (self->config, path, value); server_config_self (self); free (path); free (value); } else if (streq (method, "STOP")) { zstr_send (self->pipe, "OK"); self->stopped = true; } free (method); zmsg_destroy (&msg); }
static void s_save_metadata_all (zcert_t *self) { zconfig_destroy (&self->config); self->config = zconfig_new ("root", NULL); zconfig_t *section = zconfig_new ("metadata", self->config); char *value = (char *) zhash_first (self->metadata); while (value) { zconfig_t *item = zconfig_new (zhash_cursor (self->metadata), section); zconfig_set_value (item, "%s", value); value = (char *) zhash_next (self->metadata); } char *timestr = zclock_timestr (); zconfig_set_comment (self->config, " **** Generated on %s by CZMQ ****", timestr); zstr_free (×tr); }
JNIEXPORT jlong JNICALL Java_org_zeromq_czmq_Zconfig__1_1new (JNIEnv *env, jclass c, jstring name, jlong parent) { char *name_ = (char *) (*env)->GetStringUTFChars (env, name, NULL); // Disable CZMQ signal handling; allow Java to deal with it zsys_handler_set (NULL); jlong new_ = (jlong) (intptr_t) zconfig_new (name_, (zconfig_t *) (intptr_t) parent); (*env)->ReleaseStringUTFChars (env, name, name_); return new_; }
static server_t * server_new (zctx_t *ctx, void *pipe) { server_t *self = (server_t *) zmalloc (sizeof (server_t)); self->ctx = ctx; self->pipe = pipe; self->router = zsocket_new (self->ctx, ZMQ_ROUTER); self->clients = zhash_new (); self->config = zconfig_new ("root", NULL); server_config_self (self); self->mounts = zlist_new (); return self; }
int main(int argc, char * const *argv) { setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stderr, NULL, _IOLBF, 0); process_arguments(argc, argv); // load config if (!zsys_file_exists(config_file_name)) { fprintf(stderr, "[W] missing config file: %s\n", config_file_name); config = zconfig_new("", NULL); } else if (zsys_file_exists(config_file_name)) { // load config config_file_init(); config = zconfig_load((char*)config_file_name); } // configure graylog endpoint if (interface == NULL) interface = zconfig_resolve(config, "/graylog/endpoint", DEFAULT_INTERFACE); // set inbound high-water-mark if (rcv_hwm == -1) rcv_hwm = atoi(zconfig_resolve(config, "/logjam/high_water_mark", DEFAULT_RCV_HWM_STR)); // set outbound high-water-mark if (snd_hwm == -1) snd_hwm = atoi(zconfig_resolve(config, "/graylog/high_water_mark", DEFAULT_SND_HWM_STR)); if (!quiet) printf("[I] started %s\n" "[I] interface %s\n" "[I] rcv-hwm: %d\n" "[I] snd-hwm: %d\n" , argv[0], interface, rcv_hwm, snd_hwm); return graylog_forwarder_run_controller_loop(config, hosts, subscriptions, rcv_hwm, snd_hwm); }
zconfig_t * zconfig_load (char *filename) { FILE *file = fopen (filename, "r"); if (!file) return NULL; // File not found, or unreadable // Parse the file line by line zconfig_t *self = zconfig_new ("root", NULL); char cur_line [1024]; bool valid = true; int lineno = 0; while (fgets (cur_line, 1024, file)) { // Trim line int length = strlen (cur_line); while (length && isspace ((byte) cur_line [length - 1])) cur_line [--length] = 0; // Collect indentation level and name, if any lineno++; // Handle whole-line comment if present if (cur_line [0] == '#') { if (!self->comments) { self->comments = zlist_new (); zlist_autofree (self->comments); } zlist_append (self->comments, cur_line + 1); } char *scanner = cur_line; int level = s_collect_level (&scanner, lineno); if (level == -1) { valid = false; break; } char *name = s_collect_name (&scanner, lineno); if (name == NULL) { valid = false; break; } // If name is not empty, collect property value if (*name) { char *value = s_collect_value (&scanner, lineno); if (value == NULL) valid = false; else { // Navigate to parent for this element zconfig_t *parent = zconfig_at_depth (self, level); if (parent) { zconfig_t *item = zconfig_new (name, parent); item->value = value; } else { fprintf (stderr, "E: (%d) indentation error\n", lineno); free (value); valid = false; } } } else if (s_verify_eoln (scanner, lineno)) valid = false; free (name); if (!valid) break; } // Either the whole ZPL file is valid or none of it is if (!valid) zconfig_destroy (&self); fclose (file); return self; }
void zconfig_test (bool verbose) { printf (" * zconfig: "); // @selftest const char *SELFTEST_DIR_RW = "src/selftest-rw"; const char *testbasedir = ".test_zconfig"; const char *testfile = "test.cfg"; char *basedirpath = NULL; // subdir in a test, under SELFTEST_DIR_RW char *filepath = NULL; // pathname to testfile in a test, in dirpath basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir); assert (basedirpath); filepath = zsys_sprintf ("%s/%s", basedirpath, testfile); assert (filepath); // Make sure old aborted tests do not hinder us zdir_t *dir = zdir_new (basedirpath, NULL); if (dir) { zdir_remove (dir, true); zdir_destroy (&dir); } zsys_file_delete (filepath); zsys_dir_delete (basedirpath); // Create temporary directory for test files zsys_dir_create (basedirpath); zconfig_t *root = zconfig_new ("root", NULL); assert (root); zconfig_t *section, *item; section = zconfig_new ("headers", root); assert (section); item = zconfig_new ("email", section); assert (item); zconfig_set_value (item, "*****@*****.**"); item = zconfig_new ("name", section); assert (item); zconfig_set_value (item, "Justin Kayce"); zconfig_putf (root, "/curve/secret-key", "%s", "Top Secret"); zconfig_set_comment (root, " CURVE certificate"); zconfig_set_comment (root, " -----------------"); assert (zconfig_comments (root)); zconfig_save (root, filepath); zconfig_destroy (&root); root = zconfig_load (filepath); if (verbose) zconfig_save (root, "-"); assert (streq (zconfig_filename (root), filepath)); char *email = zconfig_get (root, "/headers/email", NULL); assert (email); assert (streq (email, "*****@*****.**")); char *passwd = zconfig_get (root, "/curve/secret-key", NULL); assert (passwd); assert (streq (passwd, "Top Secret")); zconfig_savef (root, "%s/%s", basedirpath, testfile); assert (!zconfig_has_changed (root)); int rc = zconfig_reload (&root); assert (rc == 0); assert (!zconfig_has_changed (root)); zconfig_destroy (&root); // Test chunk load/save root = zconfig_new ("root", NULL); assert (root); section = zconfig_new ("section", root); assert (section); item = zconfig_new ("value", section); assert (item); zconfig_set_value (item, "somevalue"); zconfig_t *search = zconfig_locate (root, "section/value"); assert (search == item); zchunk_t *chunk = zconfig_chunk_save (root); assert (strlen ((char *) zchunk_data (chunk)) == 32); char *string = zconfig_str_save (root); assert (string); assert (streq (string, (char *) zchunk_data (chunk))); freen (string); assert (chunk); zconfig_destroy (&root); root = zconfig_chunk_load (chunk); assert (root); char *value = zconfig_get (root, "/section/value", NULL); assert (value); assert (streq (value, "somevalue")); // Test config can't be saved to a file in a path that doesn't // exist or isn't writable rc = zconfig_savef (root, "%s/path/that/doesnt/exist/%s", basedirpath, testfile); assert (rc == -1); zconfig_destroy (&root); zchunk_destroy (&chunk); // Test subtree removal { zconfig_t *root = zconfig_str_load ( "context\n" " iothreads = 1\n" " verbose = 1 # Ask for a trace\n" "main\n" " type = zqueue # ZMQ_DEVICE type\n" " frontend\n" " option\n" " hwm = 1000\n" " swap = 25000000 # 25MB\n" " bind = 'inproc://addr1'\n" " bind = 'ipc://addr2'\n" " backend\n" " bind = inproc://addr3\n" ); zconfig_t *to_delete = zconfig_locate (root, "main/frontend"); assert (to_delete); zconfig_remove (to_delete); char *value = zconfig_get (root, "/main/type", NULL); assert (value); assert (streq (value, "zqueue")); value = zconfig_get (root, "/main/backend/bind", NULL); assert (value); assert (streq (value, "inproc://addr3")); value = zconfig_get (root, "/main/frontend", NULL); assert (value); value = zconfig_get (root, "/main/frontend/option", NULL); assert (value == NULL); value = zconfig_get (root, "/main/frontend/option/swap", NULL); assert (value == NULL); zconfig_destroy (&root); } // Test str_load zconfig_t *config = zconfig_str_load ( "malamute\n" " endpoint = ipc://@/malamute\n" " producer = STREAM\n" " consumer\n" " STREAM2 = .*\n" " STREAM3 = HAM\n" "server\n" " verbose = true\n" ); assert (config); assert (streq (zconfig_get (config, "malamute/endpoint", NULL), "ipc://@/malamute")); assert (streq (zconfig_get (config, "malamute/producer", NULL), "STREAM")); assert (zconfig_locate (config, "malamute/consumer")); zconfig_t *c = zconfig_child (zconfig_locate (config, "malamute/consumer")); assert (c); assert (streq (zconfig_name (c), "STREAM2")); assert (streq (zconfig_value (c), ".*")); c = zconfig_next (c); assert (c); assert (streq (zconfig_name (c), "STREAM3")); assert (streq (zconfig_value (c), "HAM")); c = zconfig_next (c); assert (!c); assert (streq (zconfig_get (config, "server/verbose", NULL), "true")); zconfig_destroy (&config); // Delete all test files dir = zdir_new (basedirpath, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); zstr_free (&basedirpath); zstr_free (&filepath); #if defined (__WINDOWS__) zsys_shutdown(); #endif // @end printf ("OK\n"); }
/// // Create new config item QmlZconfig *QmlZconfigAttached::construct (const QString &name, QmlZconfig *parent) { QmlZconfig *qmlSelf = new QmlZconfig (); qmlSelf->self = zconfig_new (name.toUtf8().data(), parent->self); return qmlSelf; };
int main (int argc, char *argv []) { puts (PRODUCT); puts (COPYRIGHT); puts (NOWARRANTY); int argn = 1; bool verbose = false; bool force_foreground = false; if (argc > argn && streq (argv [argn], "-v")) { verbose = true; argn++; } if (argc > argn && streq (argv [argn], "-f")) { force_foreground = true; argn++; } if (argc > argn && streq (argv [argn], "-h")) { puts ("Usage: malamute [ -v ] [ -f ] [ -h | config-file ]"); puts (" Default config-file is 'malamute.cfg'"); return 0; } // Collect configuration file name const char *config_file = "malamute.cfg"; if (argc > argn) { config_file = argv [argn]; argn++; } zsys_init (); // Keep old behavior unless specified otherwise. if (!getenv ("ZSYS_LOGSYSTEM")) { zsys_set_logsystem(true); } zsys_set_pipehwm (0); zsys_set_sndhwm (0); zsys_set_rcvhwm (0); // Load config file for our own use here zsys_info ("loading configuration from '%s'...", config_file); zconfig_t *config = zconfig_load (config_file); if (!config) { zsys_info ("'%s' is missing, creating with defaults:", config_file); config = zconfig_new ("root", NULL); zconfig_put (config, "server/timeout", "5000"); zconfig_put (config, "server/background", "0"); zconfig_put (config, "server/workdir", "."); zconfig_put (config, "server/verbose", "0"); zconfig_put (config, "mlm_server/security/mechanism", "null"); zconfig_put (config, "mlm_server/bind/endpoint", MLM_DEFAULT_ENDPOINT); zconfig_print (config); zconfig_save (config, config_file); } // Do we want to run broker in the background? int as_daemon = !force_foreground && atoi (zconfig_resolve (config, "server/background", "0")); const char *workdir = zconfig_resolve (config, "server/workdir", "."); if (as_daemon) { zsys_info ("switching Malamute to background..."); if (zsys_daemonize (workdir)) return -1; } // Switch to user/group to run process under, if any if (zsys_run_as ( zconfig_resolve (config, "server/lockfile", NULL), zconfig_resolve (config, "server/group", NULL), zconfig_resolve (config, "server/user", NULL))) return -1; // Install authenticator (NULL or PLAIN) zactor_t *auth = zactor_new (zauth, NULL); assert (auth); if (verbose || atoi (zconfig_resolve (config, "server/auth/verbose", "0"))) { zstr_sendx (auth, "VERBOSE", NULL); zsock_wait (auth); } // Do PLAIN password authentication if requested const char *passwords = zconfig_resolve (config, "server/auth/plain", NULL); if (passwords) { zstr_sendx (auth, "PLAIN", passwords, NULL); zsock_wait (auth); } // Start Malamute server instance zactor_t *server = zactor_new (mlm_server, "Malamute"); if (verbose) zstr_send (server, "VERBOSE"); zstr_sendx (server, "LOAD", config_file, NULL); // Accept and print any message back from server while (true) { char *message = zstr_recv (server); if (message) { puts (message); free (message); } else { puts ("interrupted"); break; } } // Shutdown all services zactor_destroy (&server); zactor_destroy (&auth); // Destroy config tree zconfig_destroy (&config); #if defined (__WINDOWS__) zsys_shutdown (); #endif return 0; }
void zconfig_test (bool verbose) { printf (" * zconfig: "); // @selftest // We create a config of this structure: // // root // type = zqueue // frontend // option // swap = 25000000 # 25MB // subscribe = #2 // hwm = 1000 // bind = tcp://*:5555 // backend // bind = tcp://*:5556 // zconfig_t *root, *type, *frontend, *option, *hwm, *swap, *subscribe, *bind, *backend; // Left is first child, next is next sibling root = zconfig_new ("root", NULL); type = zconfig_new ("type", root); zconfig_value_set (type, "zqueue"); frontend = zconfig_new ("frontend", root); option = zconfig_new ("option", frontend); swap = zconfig_new ("swap", option); zconfig_value_set (swap, "25000000"); subscribe = zconfig_new ("subscribe", option); zconfig_value_format (subscribe, "#%d", 2); hwm = zconfig_new ("hwm", option); zconfig_value_set (hwm, "1000"); bind = zconfig_new ("bind", frontend); zconfig_value_set (bind, "tcp://*:5555"); backend = zconfig_new ("backend", root); bind = zconfig_new ("bind", backend); zconfig_value_set (bind, "tcp://*:5556"); assert (atoi (zconfig_resolve (root, "frontend/option/hwm", "0")) == 1000); assert (streq (zconfig_resolve (root, "backend/bind", ""), "tcp://*:5556")); zconfig_path_set (root, "frontend/option/hwm", "500"); assert (atoi (zconfig_resolve (root, "frontend/option/hwm", "0")) == 500); zconfig_path_set (root, "frontend/option/lwm", "200"); assert (atoi (zconfig_resolve (root, "frontend/option/lwm", "0")) == 200); zconfig_destroy (&root); assert (root == NULL); // Test loading from a ZPL file zconfig_t *config = zconfig_load ("selftest.cfg"); assert (config); // Destructor should be safe to call twice zconfig_destroy (&config); zconfig_destroy (&config); assert (config == NULL); // @end printf ("OK\n"); }
void zconfig_test (bool verbose) { printf (" * zconfig: "); // @selftest // Create temporary directory for test files # define TESTDIR ".test_zconfig" zsys_dir_create (TESTDIR); zconfig_t *root = zconfig_new ("root", NULL); assert (root); zconfig_t *section, *item; section = zconfig_new ("headers", root); assert (section); item = zconfig_new ("email", section); assert (item); zconfig_set_value (item, "*****@*****.**"); item = zconfig_new ("name", section); assert (item); zconfig_set_value (item, "Justin Kayce"); zconfig_putf (root, "/curve/secret-key", "%s", "Top Secret"); zconfig_set_comment (root, " CURVE certificate"); zconfig_set_comment (root, " -----------------"); assert (zconfig_comments (root)); zconfig_save (root, TESTDIR "/test.cfg"); zconfig_destroy (&root); root = zconfig_load (TESTDIR "/test.cfg"); if (verbose) zconfig_save (root, "-"); assert (streq (zconfig_filename (root), TESTDIR "/test.cfg")); char *email = zconfig_get (root, "/headers/email", NULL); assert (email); assert (streq (email, "*****@*****.**")); char *passwd = zconfig_get (root, "/curve/secret-key", NULL); assert (passwd); assert (streq (passwd, "Top Secret")); zconfig_savef (root, "%s/%s", TESTDIR, "test.cfg"); assert (!zconfig_has_changed (root)); int rc = zconfig_reload (&root); assert (rc == 0); assert (!zconfig_has_changed (root)); zconfig_destroy (&root); // Test chunk load/save root = zconfig_new ("root", NULL); assert (root); section = zconfig_new ("section", root); assert (section); item = zconfig_new ("value", section); assert (item); zconfig_set_value (item, "somevalue"); zconfig_t *search = zconfig_locate (root, "section/value"); assert (search == item); zchunk_t *chunk = zconfig_chunk_save (root); assert (strlen ((char *) zchunk_data (chunk)) == 32); char *string = zconfig_str_save (root); assert (string); assert (streq (string, (char *) zchunk_data (chunk))); free (string); assert (chunk); zconfig_destroy (&root); root = zconfig_chunk_load (chunk); assert (root); char *value = zconfig_get (root, "/section/value", NULL); assert (value); assert (streq (value, "somevalue")); // Test config can't be saved to a file in a path that doesn't // exist or isn't writable rc = zconfig_savef (root, "%s/path/that/doesnt/exist/%s", TESTDIR, "test.cfg"); assert (rc == -1); zconfig_destroy (&root); zchunk_destroy (&chunk); // Delete all test files zdir_t *dir = zdir_new (TESTDIR, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); // @end printf ("OK\n"); }
zconfig_t * zconfig_chunk_load (zchunk_t *chunk) { // Parse the chunk line by line zconfig_t *self = zconfig_new ("root", NULL); if (!self) return NULL; bool valid = true; int lineno = 0; char *data_ptr = (char *) zchunk_data (chunk); size_t remaining = zchunk_size (chunk); while (remaining) { // Copy stuff into cur_line; not fastest but safest option // since chunk may not be null terminated, etc. char *eoln = (char *) memchr (data_ptr, '\n', remaining); size_t cur_size; if (eoln) cur_size = eoln - data_ptr; else cur_size = remaining; if (cur_size > 1024) cur_size = 1024; char cur_line [1024 + 1]; memcpy (cur_line, data_ptr, cur_size); cur_line [cur_size] = '\0'; data_ptr = eoln? eoln + 1: NULL; remaining -= cur_size + (eoln? 1: 0); // Trim line size_t length = strlen (cur_line); while (length && isspace ((byte) cur_line [length - 1])) cur_line [--length] = 0; // Collect indentation level and name, if any lineno++; // Handle whole-line comment if present if (cur_line [0] == '#') { if (!self->comments) { self->comments = zlist_new (); assert (self->comments); zlist_autofree (self->comments); } zlist_append (self->comments, cur_line + 1); } char *scanner = cur_line; int level = s_collect_level (&scanner, lineno); if (level == -1) { valid = false; break; } char *name = s_collect_name (&scanner, lineno); if (name == NULL) { valid = false; break; } // If name is not empty, collect property value if (*name) { char *value = s_collect_value (&scanner, lineno); if (value == NULL) valid = false; else { // Navigate to parent for this element zconfig_t *parent = zconfig_at_depth (self, level); if (parent) { zconfig_t *item = zconfig_new (name, parent); assert (item); item->value = value; } else { zclock_log ("E (zconfig): (%d) indentation error", lineno); free (value); valid = false; } } } else if (s_verify_eoln (scanner, lineno)) valid = false; free (name); if (!valid) break; } // Either the whole ZPL stream is valid or none of it is if (!valid) zconfig_destroy (&self); return self; }
int main (int argc, char *argv []) { puts (PRODUCT); puts (COPYRIGHT); puts (NOWARRANTY); int argn = 1; bool verbose = false; if (argn < argc && streq (argv [argn], "-h")) { puts ("syntax: hydrad [ directory ]"); puts (" -- defaults to .hydra in current directory"); exit (0); } if (argn < argc && streq (argv [argn], "-v")) { verbose = true; argn++; } // By default, current node runs in .hydra directory; create this if // it's missing (don't create directory passed as argument); char *workdir = ".hydra"; if (argn < argc) workdir = argv [argn++]; else zsys_dir_create (workdir); // ---------------------------------------------------------------------- // This code eventually goes into a reusable hydra actor class // Switch to working directory zsys_info ("hydrad: data store in %s directory", workdir); if (zsys_dir_change (workdir)) { zsys_error ("hydrad: cannot access %s: %s", workdir, strerror (errno)); return 1; } // Check we are the only process currently running here if (zsys_run_as ("hydrad.lock", NULL, NULL)) { zsys_error ("hydrad: cannot start process safely, exiting"); return 1; } // Get node identity from config file, or generate new identity zconfig_t *config = zconfig_load ("hydra.cfg"); if (!config) { // Set defaults for Hydra service config = zconfig_new ("root", NULL); zconfig_put (config, "/server/timeout", "5000"); zconfig_put (config, "/server/background", "0"); zconfig_put (config, "/server/verbose", "0"); } char *identity = zconfig_resolve (config, "/hydra/identity", NULL); if (!identity) { zuuid_t *uuid = zuuid_new (); zconfig_put (config, "/hydra/identity", zuuid_str (uuid)); zconfig_put (config, "/hydra/nickname", "Anonymous"); zconfig_save (config, "hydra.cfg"); zuuid_destroy (&uuid); } // Create store structure, if necessary zsys_dir_create ("content"); zsys_dir_create ("posts"); // Start server and bind to ephemeral TCP port. We can run many // servers on the same box, for testing. zactor_t *server = zactor_new (hydra_server, NULL); if (verbose) zstr_send (server, "VERBOSE"); // Bind Hydra service to ephemeral port and get that port number char *command; int port_nbr; zsock_send (server, "ss", "CONFIGURE", "hydra.cfg"); zsock_send (server, "ss", "BIND", "tcp://*:*"); zsock_send (server, "s", "PORT"); zsock_recv (server, "si", &command, &port_nbr); zsys_info ("hydrad: TCP server started on port=%d", port_nbr); assert (streq (command, "PORT")); free (command); // We're going to use Zyre for discovery and presence, and our own // Hydra protocol for content exchange zyre_t *zyre = zyre_new (NULL); if (verbose) zyre_set_verbose (zyre); char *hostname = zsys_hostname (); char *endpoint = zsys_sprintf ("tcp://%s:%d", hostname, port_nbr); zyre_set_header (zyre, "X-HYDRA", "%s", endpoint); zstr_free (&endpoint); zstr_free (&hostname); if (zyre_start (zyre)) { zsys_info ("hydrad: can't start Zyre discovery service"); zactor_destroy (&server); zyre_destroy (&zyre); return 1; } // When we get a new peer, handle it zpoller_t *poller = zpoller_new (zyre_socket (zyre), NULL); while (!zpoller_terminated (poller)) { void *which = zpoller_wait (poller, -1); if (which == zyre_socket (zyre)) { zyre_event_t *event = zyre_event_new (zyre); if (zyre_event_type (event) == ZYRE_EVENT_ENTER) { zsys_debug ("hydrad: new peer name=%s endpoint=%s", zyre_event_name (event), zyre_event_header (event, "X-HYDRA")); s_handle_peer (zyre_event_header (event, "X-HYDRA"), verbose); } zyre_event_destroy (&event); } else break; } zsys_info ("hydrad: shutting down..."); zpoller_destroy (&poller); // Shutdown all services zactor_destroy (&server); zyre_destroy (&zyre); zconfig_destroy (&config); return 0; }