'\" t .\" Title: zsys .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets v1.79.1 .\" Date: 03/03/2019 .\" Manual: CZMQ Manual .\" Source: CZMQ 4.2.0 .\" Language: English .\" .TH "ZSYS" "3" "03/03/2019" "CZMQ 4\&.2\&.0" "CZMQ Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" zsys \- Class for system\-level methods .SH "SYNOPSIS" .sp .nf // This is a stable class, and may not change except for emergencies\&. It // is provided in stable builds\&. // This class has draft methods, which may change over time\&. They are not // in stable releases, by default\&. Use \-\-enable\-drafts to enable\&. // Callback for interrupt signal handler typedef void (zsys_handler_fn) ( int signal_value); // Initialize CZMQ zsys layer; this happens automatically when you create // a socket or an actor; however this call lets you force initialization // earlier, so e\&.g\&. logging is properly set\-up before you start working\&. // Not threadsafe, so call only from main thread\&. Safe to call multiple // times\&. Returns global CZMQ context\&. CZMQ_EXPORT void * zsys_init (void); // Optionally shut down the CZMQ zsys layer; this normally happens automatically // when the process exits; however this call lets you force a shutdown // earlier, avoiding any potential problems with atexit() ordering, especially // with Windows dlls\&. CZMQ_EXPORT void zsys_shutdown (void); // Get a new ZMQ socket, automagically creating a ZMQ context if this is // the first time\&. Caller is responsible for destroying the ZMQ socket // before process exits, to avoid a ZMQ deadlock\&. Note: you should not use // this method in CZMQ apps, use zsock_new() instead\&. // *** This is for CZMQ internal use only and may change arbitrarily *** CZMQ_EXPORT void * zsys_socket (int type, const char *filename, size_t line_nbr); // Destroy/close a ZMQ socket\&. You should call this for every socket you // create using zsys_socket()\&. // *** This is for CZMQ internal use only and may change arbitrarily *** CZMQ_EXPORT int zsys_close (void *handle, const char *filename, size_t line_nbr); // Return ZMQ socket name for socket type // *** This is for CZMQ internal use only and may change arbitrarily *** CZMQ_EXPORT char * zsys_sockname (int socktype); // Create a pipe, which consists of two PAIR sockets connected over inproc\&. // The pipe is configured to use the zsys_pipehwm setting\&. Returns the // frontend socket successful, NULL if failed\&. CZMQ_EXPORT zsock_t * zsys_create_pipe (zsock_t **backend_p); // Set interrupt handler; this saves the default handlers so that a // zsys_handler_reset () can restore them\&. If you call this multiple times // then the last handler will take affect\&. If handler_fn is NULL, disables // default SIGINT/SIGTERM handling in CZMQ\&. CZMQ_EXPORT void zsys_handler_set (zsys_handler_fn *handler_fn); // Reset interrupt handler, call this at exit if needed CZMQ_EXPORT void zsys_handler_reset (void); // Set default interrupt handler, so Ctrl\-C or SIGTERM will set // zsys_interrupted\&. Idempotent; safe to call multiple times\&. // Can be suppressed by ZSYS_SIGHANDLER=false // *** This is for CZMQ internal use only and may change arbitrarily *** CZMQ_EXPORT void zsys_catch_interrupts (void); // Return 1 if file exists, else zero CZMQ_EXPORT bool zsys_file_exists (const char *filename); // Return file modification time\&. Returns 0 if the file does not exist\&. CZMQ_EXPORT time_t zsys_file_modified (const char *filename); // Return file mode; provides at least support for the POSIX S_ISREG(m) // and S_ISDIR(m) macros and the S_IRUSR and S_IWUSR bits, on all boxes\&. // Returns a mode_t cast to int, or \-1 in case of error\&. CZMQ_EXPORT int zsys_file_mode (const char *filename); // Delete file\&. Does not complain if the file is absent CZMQ_EXPORT int zsys_file_delete (const char *filename); // Check if file is \*(Aqstable\*(Aq CZMQ_EXPORT bool zsys_file_stable (const char *filename); // Create a file path if it doesn\*(Aqt exist\&. The file path is treated as // printf format\&. CZMQ_EXPORT int zsys_dir_create (const char *pathname, \&.\&.\&.); // Remove a file path if empty; the pathname is treated as printf format\&. CZMQ_EXPORT int zsys_dir_delete (const char *pathname, \&.\&.\&.); // Move to a specified working directory\&. Returns 0 if OK, \-1 if this failed\&. CZMQ_EXPORT int zsys_dir_change (const char *pathname); // Set private file creation mode; all files created from here will be // readable/writable by the owner only\&. CZMQ_EXPORT void zsys_file_mode_private (void); // Reset default file creation mode; all files created from here will use // process file mode defaults\&. CZMQ_EXPORT void zsys_file_mode_default (void); // Return the CZMQ version for run\-time API detection; returns version // number into provided fields, providing reference isn\*(Aqt null in each case\&. CZMQ_EXPORT void zsys_version (int *major, int *minor, int *patch); // Format a string using printf formatting, returning a freshly allocated // buffer\&. If there was insufficient memory, returns NULL\&. Free the returned // string using zstr_free()\&. CZMQ_EXPORT char * zsys_sprintf (const char *format, \&.\&.\&.); // Format a string with a va_list argument, returning a freshly allocated // buffer\&. If there was insufficient memory, returns NULL\&. Free the returned // string using zstr_free()\&. CZMQ_EXPORT char * zsys_vprintf (const char *format, va_list argptr); // Create UDP beacon socket; if the routable option is true, uses // multicast (not yet implemented), else uses broadcast\&. This method // and related ones might _eventually_ be moved to a zudp class\&. // *** This is for CZMQ internal use only and may change arbitrarily *** CZMQ_EXPORT SOCKET zsys_udp_new (bool routable); // Close a UDP socket // *** This is for CZMQ internal use only and may change arbitrarily *** CZMQ_EXPORT int zsys_udp_close (SOCKET handle); // Send zframe to UDP socket, return \-1 if sending failed due to // interface having disappeared (happens easily with WiFi) // *** This is for CZMQ internal use only and may change arbitrarily *** CZMQ_EXPORT int zsys_udp_send (SOCKET udpsock, zframe_t *frame, inaddr_t *address, int addrlen); // Receive zframe from UDP socket, and set address of peer that sent it // The peername must be a char [INET_ADDRSTRLEN] array if IPv6 is disabled or // NI_MAXHOST if it\*(Aqs enabled\&. Returns NULL when failing to get peer address\&. // *** This is for CZMQ internal use only and may change arbitrarily *** CZMQ_EXPORT zframe_t * zsys_udp_recv (SOCKET udpsock, char *peername, int peerlen); // Handle an I/O error on some socket operation; will report and die on // fatal errors, and continue silently on "try again" errors\&. // *** This is for CZMQ internal use only and may change arbitrarily *** CZMQ_EXPORT void zsys_socket_error (const char *reason); // Return current host name, for use in public tcp:// endpoints\&. Caller gets // a freshly allocated string, should free it using zstr_free()\&. If the host // name is not resolvable, returns NULL\&. CZMQ_EXPORT char * zsys_hostname (void); // Move the current process into the background\&. The precise effect depends // on the operating system\&. On POSIX boxes, moves to a specified working // directory (if specified), closes all file handles, reopens stdin, stdout, // and stderr to the null device, and sets the process to ignore SIGHUP\&. On // Windows, does nothing\&. Returns 0 if OK, \-1 if there was an error\&. CZMQ_EXPORT int zsys_daemonize (const char *workdir); // Drop the process ID into the lockfile, with exclusive lock, and switch // the process to the specified group and/or user\&. Any of the arguments // may be null, indicating a no\-op\&. Returns 0 on success, \-1 on failure\&. // Note if you combine this with zsys_daemonize, run after, not before // that method, or the lockfile will hold the wrong process ID\&. CZMQ_EXPORT int zsys_run_as (const char *lockfile, const char *group, const char *user); // Returns true if the underlying libzmq supports CURVE security\&. // Uses a heuristic probe according to the version of libzmq being used\&. CZMQ_EXPORT bool zsys_has_curve (void); // Configure the number of I/O threads that ZeroMQ will use\&. A good // rule of thumb is one thread per gigabit of traffic in or out\&. The // default is 1, sufficient for most applications\&. If the environment // variable ZSYS_IO_THREADS is defined, that provides the default\&. // Note that this method is valid only before any socket is created\&. CZMQ_EXPORT void zsys_set_io_threads (size_t io_threads); // Configure the scheduling policy of the ZMQ context thread pool\&. // Not available on Windows\&. See the sched_setscheduler man page or sched\&.h // for more information\&. If the environment variable ZSYS_THREAD_SCHED_POLICY // is defined, that provides the default\&. // Note that this method is valid only before any socket is created\&. CZMQ_EXPORT void zsys_set_thread_sched_policy (int policy); // Configure the scheduling priority of the ZMQ context thread pool\&. // Not available on Windows\&. See the sched_setscheduler man page or sched\&.h // for more information\&. If the environment variable ZSYS_THREAD_PRIORITY is // defined, that provides the default\&. // Note that this method is valid only before any socket is created\&. CZMQ_EXPORT void zsys_set_thread_priority (int priority); // Configure the numeric prefix to each thread created for the internal // context\*(Aqs thread pool\&. This option is only supported on Linux\&. // If the environment variable ZSYS_THREAD_NAME_PREFIX is defined, that // provides the default\&. // Note that this method is valid only before any socket is created\&. CZMQ_EXPORT void zsys_set_thread_name_prefix (int prefix); // Return thread name prefix\&. CZMQ_EXPORT int zsys_thread_name_prefix (void); // Adds a specific CPU to the affinity list of the ZMQ context thread pool\&. // This option is only supported on Linux\&. // Note that this method is valid only before any socket is created\&. CZMQ_EXPORT void zsys_thread_affinity_cpu_add (int cpu); // Removes a specific CPU to the affinity list of the ZMQ context thread pool\&. // This option is only supported on Linux\&. // Note that this method is valid only before any socket is created\&. CZMQ_EXPORT void zsys_thread_affinity_cpu_remove (int cpu); // Configure the number of sockets that ZeroMQ will allow\&. The default // is 1024\&. The actual limit depends on the system, and you can query it // by using zsys_socket_limit ()\&. A value of zero means "maximum"\&. // Note that this method is valid only before any socket is created\&. CZMQ_EXPORT void zsys_set_max_sockets (size_t max_sockets); // Return maximum number of ZeroMQ sockets that the system will support\&. CZMQ_EXPORT size_t zsys_socket_limit (void); // Configure the maximum allowed size of a message sent\&. // The default is INT_MAX\&. CZMQ_EXPORT void zsys_set_max_msgsz (int max_msgsz); // Return maximum message size\&. CZMQ_EXPORT int zsys_max_msgsz (void); // Configure the default linger timeout in msecs for new zsock instances\&. // You can also set this separately on each zsock_t instance\&. The default // linger time is zero, i\&.e\&. any pending messages will be dropped\&. If the // environment variable ZSYS_LINGER is defined, that provides the default\&. // Note that process exit will typically be delayed by the linger time\&. CZMQ_EXPORT void zsys_set_linger (size_t linger); // Configure the default outgoing pipe limit (HWM) for new zsock instances\&. // You can also set this separately on each zsock_t instance\&. The default // HWM is 1,000, on all versions of ZeroMQ\&. If the environment variable // ZSYS_SNDHWM is defined, that provides the default\&. Note that a value of // zero means no limit, i\&.e\&. infinite memory consumption\&. CZMQ_EXPORT void zsys_set_sndhwm (size_t sndhwm); // Configure the default incoming pipe limit (HWM) for new zsock instances\&. // You can also set this separately on each zsock_t instance\&. The default // HWM is 1,000, on all versions of ZeroMQ\&. If the environment variable // ZSYS_RCVHWM is defined, that provides the default\&. Note that a value of // zero means no limit, i\&.e\&. infinite memory consumption\&. CZMQ_EXPORT void zsys_set_rcvhwm (size_t rcvhwm); // Configure the default HWM for zactor internal pipes; this is set on both // ends of the pipe, for outgoing messages only (sndhwm)\&. The default HWM is // 1,000, on all versions of ZeroMQ\&. If the environment var ZSYS_ACTORHWM is // defined, that provides the default\&. Note that a value of zero means no // limit, i\&.e\&. infinite memory consumption\&. CZMQ_EXPORT void zsys_set_pipehwm (size_t pipehwm); // Return the HWM for zactor internal pipes\&. CZMQ_EXPORT size_t zsys_pipehwm (void); // Configure use of IPv6 for new zsock instances\&. By default sockets accept // and make only IPv4 connections\&. When you enable IPv6, sockets will accept // and connect to both IPv4 and IPv6 peers\&. You can override the setting on // each zsock_t instance\&. The default is IPv4 only (ipv6 set to 0)\&. If the // environment variable ZSYS_IPV6 is defined (as 1 or 0), this provides the // default\&. Note: has no effect on ZMQ v2\&. CZMQ_EXPORT void zsys_set_ipv6 (int ipv6); // Return use of IPv6 for zsock instances\&. CZMQ_EXPORT int zsys_ipv6 (void); // Set network interface name to use for broadcasts, particularly zbeacon\&. // This lets the interface be configured for test environments where required\&. // For example, on Mac OS X, zbeacon cannot bind to 255\&.255\&.255\&.255 which is // the default when there is no specified interface\&. If the environment // variable ZSYS_INTERFACE is set, use that as the default interface name\&. // Setting the interface to "*" means "use all available interfaces"\&. CZMQ_EXPORT void zsys_set_interface (const char *value); // Return network interface to use for broadcasts, or "" if none was set\&. CZMQ_EXPORT const char * zsys_interface (void); // Set IPv6 address to use zbeacon socket, particularly for receiving zbeacon\&. // This needs to be set IPv6 is enabled as IPv6 can have multiple addresses // on a given interface\&. If the environment variable ZSYS_IPV6_ADDRESS is set, // use that as the default IPv6 address\&. CZMQ_EXPORT void zsys_set_ipv6_address (const char *value); // Return IPv6 address to use for zbeacon reception, or "" if none was set\&. CZMQ_EXPORT const char * zsys_ipv6_address (void); // Set IPv6 milticast address to use for sending zbeacon messages\&. This needs // to be set if IPv6 is enabled\&. If the environment variable // ZSYS_IPV6_MCAST_ADDRESS is set, use that as the default IPv6 multicast // address\&. CZMQ_EXPORT void zsys_set_ipv6_mcast_address (const char *value); // Return IPv6 multicast address to use for sending zbeacon, or "" if none was // set\&. CZMQ_EXPORT const char * zsys_ipv6_mcast_address (void); // Configure the automatic use of pre\-allocated FDs when creating new sockets\&. // If 0 (default), nothing will happen\&. Else, when a new socket is bound, the // system API will be used to check if an existing pre\-allocated FD with a // matching port (if TCP) or path (if IPC) exists, and if it does it will be // set via the ZMQ_USE_FD socket option so that the library will use it // instead of creating a new socket\&. CZMQ_EXPORT void zsys_set_auto_use_fd (int auto_use_fd); // Return use of automatic pre\-allocated FDs for zsock instances\&. CZMQ_EXPORT int zsys_auto_use_fd (void); // Set log identity, which is a string that prefixes all log messages sent // by this process\&. The log identity defaults to the environment variable // ZSYS_LOGIDENT, if that is set\&. CZMQ_EXPORT void zsys_set_logident (const char *value); // Set stream to receive log traffic\&. By default, log traffic is sent to // stdout\&. If you set the stream to NULL, no stream will receive the log // traffic (it may still be sent to the system facility)\&. CZMQ_EXPORT void zsys_set_logstream (FILE *stream); // Sends log output to a PUB socket bound to the specified endpoint\&. To // collect such log output, create a SUB socket, subscribe to the traffic // you care about, and connect to the endpoint\&. Log traffic is sent as a // single string frame, in the same format as when sent to stdout\&. The // log system supports a single sender; multiple calls to this method will // bind the same sender to multiple endpoints\&. To disable the sender, call // this method with a null argument\&. CZMQ_EXPORT void zsys_set_logsender (const char *endpoint); // Enable or disable logging to the system facility (syslog on POSIX boxes, // event log on Windows)\&. By default this is disabled\&. CZMQ_EXPORT void zsys_set_logsystem (bool logsystem); // Log error condition \- highest priority CZMQ_EXPORT void zsys_error (const char *format, \&.\&.\&.); // Log warning condition \- high priority CZMQ_EXPORT void zsys_warning (const char *format, \&.\&.\&.); // Log normal, but significant, condition \- normal priority CZMQ_EXPORT void zsys_notice (const char *format, \&.\&.\&.); // Log informational message \- low priority CZMQ_EXPORT void zsys_info (const char *format, \&.\&.\&.); // Log debug\-level message \- lowest priority CZMQ_EXPORT void zsys_debug (const char *format, \&.\&.\&.); // Self test of this class\&. CZMQ_EXPORT void zsys_test (bool verbose); #ifdef CZMQ_BUILD_DRAFT_API // *** Draft method, for development use, may change without warning *** // Check if default interrupt handler of Ctrl\-C or SIGTERM was called\&. // Does not work if ZSYS_SIGHANDLER is false and code does not call // set interrupted on signal\&. CZMQ_EXPORT bool zsys_is_interrupted (void); // *** Draft method, for development use, may change without warning *** // Set interrupted flag\&. This is done by default signal handler, however // this can be handy for language bindings or cases without default // signal handler\&. CZMQ_EXPORT void zsys_set_interrupted (void); // *** Draft method, for development use, may change without warning *** // Format a string using printf formatting, returning a freshly allocated // buffer\&. If there was insufficient memory, returns NULL\&. Free the returned // string using zstr_free()\&. The hinted version allows to optimize by using // a larger starting buffer size (known to/assumed by the developer) and so // avoid reallocations\&. CZMQ_EXPORT char * zsys_sprintf_hint (int hint, const char *format, \&.\&.\&.); // *** Draft method, for development use, may change without warning *** // Configure whether to use zero copy strategy in libzmq\&. If the environment // variable ZSYS_ZERO_COPY_RECV is defined, that provides the default\&. // Otherwise the default is 1\&. CZMQ_EXPORT void zsys_set_zero_copy_recv (int zero_copy); // *** Draft method, for development use, may change without warning *** // Return ZMQ_ZERO_COPY_RECV option\&. CZMQ_EXPORT int zsys_zero_copy_recv (void); // *** Draft method, for development use, may change without warning *** // Configure the threshold value of filesystem object age per st_mtime // that should elapse until we consider that object "stable" at the // current zclock_time() moment\&. // The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys\&.c // which generally depends on host OS, with fallback value of 5000\&. CZMQ_EXPORT void zsys_set_file_stable_age_msec (int64_t file_stable_age_msec); // *** Draft method, for development use, may change without warning *** // Return current threshold value of file stable age in msec\&. // This can be used in code that chooses to wait for this timeout // before testing if a filesystem object is "stable" or not\&. CZMQ_EXPORT int64_t zsys_file_stable_age_msec (void); // *** Draft method, for development use, may change without warning *** // Print formatted string\&. Format is specified by variable names // in Python\-like format style // // "%(KEY)s=%(VALUE)s", KEY=key, VALUE=value // become // "key=value" // // Returns freshly allocated string or NULL in a case of error\&. // Not enough memory, invalid format specifier, name not in args // Caller owns return value and must destroy it when done\&. CZMQ_EXPORT char * zsys_zprintf (const char *format, zhash_t *args); // *** Draft method, for development use, may change without warning *** // Return error string for given format/args combination\&. // Caller owns return value and must destroy it when done\&. CZMQ_EXPORT char * zsys_zprintf_error (const char *format, zhash_t *args); // *** Draft method, for development use, may change without warning *** // Print formatted string\&. Format is specified by variable names // in Python\-like format style // // "%(KEY)s=%(VALUE)s", KEY=key, VALUE=value // become // "key=value" // // Returns freshly allocated string or NULL in a case of error\&. // Not enough memory, invalid format specifier, name not in args // Caller owns return value and must destroy it when done\&. CZMQ_EXPORT char * zsys_zplprintf (const char *format, zconfig_t *args); // *** Draft method, for development use, may change without warning *** // Return error string for given format/args combination\&. // Caller owns return value and must destroy it when done\&. CZMQ_EXPORT char * zsys_zplprintf_error (const char *format, zconfig_t *args); #endif // CZMQ_BUILD_DRAFT_API Please add \*(Aq@interface\*(Aq section in \*(Aq\&./\&.\&./src/zsys\&.c\*(Aq\&. .fi .SH "DESCRIPTION" .sp The zsys class provides a portable wrapper for system calls\&. We collect them here to reduce the number of weird #ifdefs in other classes\&. As far as possible, the bulk of CZMQ classes are fully portable\&. .sp Please add \fI@discuss\fR section in \fI\&./\&.\&./src/zsys\&.c\fR\&. .SH "EXAMPLE" .PP \fBFrom zsys_test method\fR. .sp .if n \{\ .RS 4 .\} .nf zsys_catch_interrupts (); // Check capabilities without using the return value int rc = zsys_has_curve (); const char *SELFTEST_DIR_RW = "src/selftest\-rw"; if (verbose) { char *hostname = zsys_hostname (); zsys_info ("host name is %s", hostname); freen (hostname); zsys_info ("system limit is %zu ZeroMQ sockets", zsys_socket_limit ()); } #ifdef CZMQ_BUILD_DRAFT_API zsys_set_file_stable_age_msec (5123); assert (zsys_file_stable_age_msec() == 5123); zsys_set_file_stable_age_msec (\-1); assert (zsys_file_stable_age_msec() == 5123); #endif // CZMQ_BUILD_DRAFT_API zsys_set_linger (0); zsys_set_sndhwm (1000); zsys_set_rcvhwm (1000); zsys_set_pipehwm (2500); assert (zsys_pipehwm () == 2500); zsys_set_ipv6 (0); zsys_set_thread_priority (\-1); zsys_set_thread_sched_policy (\-1); zsys_set_thread_name_prefix (0); assert (0 == zsys_thread_name_prefix()); zsys_thread_affinity_cpu_add (0); zsys_thread_affinity_cpu_remove (0); zsys_set_zero_copy_recv(0); assert (0 == zsys_zero_copy_recv()); zsys_set_zero_copy_recv(1); assert (1 == zsys_zero_copy_recv()); // Test pipe creation zsock_t *pipe_back; zsock_t *pipe_front = zsys_create_pipe (&pipe_back); zstr_send (pipe_front, "Hello"); char *string = zstr_recv (pipe_back); assert (streq (string, "Hello")); freen (string); zsock_destroy (&pipe_back); zsock_destroy (&pipe_front); // Test file manipulation // Don\*(Aqt let anyone fool our workspace if (zsys_file_exists ("nosuchfile")) { zsys_warning ("zsys_test() had to remove \*(Aqnosuchfile\*(Aq which was not expected here at all"); zsys_file_delete ("nosuchfile"); } rc = zsys_file_delete ("nosuchfile"); assert (rc == \-1); bool rc_bool = zsys_file_exists ("nosuchfile"); assert (rc_bool != true); rc = (int) zsys_file_size ("nosuchfile"); assert (rc == \-1); time_t when = zsys_file_modified ("\&."); assert (when > 0); int mode = zsys_file_mode ("\&."); assert (S_ISDIR (mode)); assert (mode & S_IRUSR); assert (mode & S_IWUSR); const char *testbasedir = "\&.testsys"; const char *testsubdir = "subdir"; char *basedirpath = NULL; // subdir in a test, under SELFTEST_DIR_RW char *dirpath = NULL; // subdir in a test, under basedirpath char *relsubdir = NULL; // relative short "path" of subdir under testbasedir basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir); assert (basedirpath); dirpath = zsys_sprintf ("%s/%s", basedirpath, testsubdir); assert (dirpath); relsubdir = zsys_sprintf ("%s/%s", testbasedir, testsubdir); assert (relsubdir); // Normally tests clean up in the end, but if a selftest run dies // e\&.g\&. on assert(), workspace remains dirty\&. Better clean it up\&. // We do not really care about results here \- we clean up a possible // dirty exit of an older build\&. If there are permission errors etc\&. // the actual tests below would explode\&. if (zsys_file_exists(dirpath)) { if (verbose) zsys_debug ("zsys_test() has to remove \&./%s that should not have been here", dirpath); zsys_dir_delete (dirpath); } if (zsys_file_exists (basedirpath)) { if (verbose) zsys_debug ("zsys_test() has to remove \&./%s that should not have been here", basedirpath); zsys_dir_delete (basedirpath); } // Added tracing because this file\-age check fails on some systems // presumably due to congestion in a mass\-build and valgrind on top zsys_file_mode_private (); if (verbose) printf ("zsys_test() at timestamp %" PRIi64 ": " "Creating %s\en", zclock_time(), relsubdir ); rc = zsys_dir_create ("%s/%s", SELFTEST_DIR_RW, relsubdir); if (verbose) printf ("zsys_test() at timestamp %" PRIi64 ": " "Finished creating %s with return\-code %d\en", zclock_time(), relsubdir, rc ); assert (rc == 0); when = zsys_file_modified (dirpath); if (verbose) printf ("zsys_test() at timestamp %" PRIi64 ": " "Finished calling zsys_file_modified(), got age %jd\en", zclock_time(), (intmax_t)when ); assert (when > 0); if (verbose) printf ("zsys_test() at timestamp %" PRIi64 ": " "Checking if file is NOT stable (is younger than 1 sec)\en", zclock_time() ); assert (!s_zsys_file_stable (dirpath, verbose)); if (verbose) printf ("zsys_test() at timestamp %" PRIi64 ": " "Passed the test, file is not stable \- as expected\en", zclock_time() ); rc = zsys_dir_delete ("%s/%s", SELFTEST_DIR_RW, relsubdir); assert (rc == 0); rc = zsys_dir_delete ("%s/%s", SELFTEST_DIR_RW, testbasedir); assert (rc == 0); zsys_file_mode_default (); #if (defined (PATH_MAX)) char cwd[PATH_MAX]; #else # if (defined (_MAX_PATH)) char cwd[_MAX_PATH]; # else char cwd[1024]; # endif #endif memset (cwd, 0, sizeof(cwd)); #if (defined (WIN32)) if (_getcwd(cwd, sizeof(cwd)) != NULL) { #else if (getcwd(cwd, sizeof(cwd)) != NULL) { #endif if (verbose) printf ("zsys_test() at timestamp %" PRIi64 ": " "current working directory is %s\en", zclock_time(), cwd); assert (zsys_dir_change (SELFTEST_DIR_RW) == 0); assert (zsys_dir_change (cwd) == 0); } else { zsys_warning ("zsys_test() : got getcwd() error\&.\&.\&. " "testing zsys_dir_change() anyway, but it can confuse " "subsequent tests in this process"); assert (zsys_dir_change (SELFTEST_DIR_RW) == 0); } zstr_free (&basedirpath); zstr_free (&dirpath); zstr_free (&relsubdir); // Other subtests int major, minor, patch; zsys_version (&major, &minor, &patch); assert (major == CZMQ_VERSION_MAJOR); assert (minor == CZMQ_VERSION_MINOR); assert (patch == CZMQ_VERSION_PATCH); string = zsys_sprintf ("%s %02x", "Hello", 16); assert (streq (string, "Hello 10")); freen (string); char *str64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,\&."; int num10 = 1234567890; string = zsys_sprintf ("%s%s%s%s%d", str64, str64, str64, str64, num10); assert (strlen (string) == (4 * 64 + 10)); freen (string); // Test logging system zsys_set_logident ("czmq_selftest"); zsys_set_logsender ("inproc://logging"); void *logger = zsys_socket (ZMQ_SUB, NULL, 0); assert (logger); rc = zmq_connect (logger, "inproc://logging"); assert (rc == 0); rc = zmq_setsockopt (logger, ZMQ_SUBSCRIBE, "", 0); assert (rc == 0); if (verbose) { zsys_error ("This is an %s message", "error"); zsys_warning ("This is a %s message", "warning"); zsys_notice ("This is a %s message", "notice"); zsys_info ("This is a %s message", "info"); zsys_debug ("This is a %s message", "debug"); zsys_set_logident ("hello, world"); zsys_info ("This is a %s message", "info"); zsys_debug ("This is a %s message", "debug"); // Check that logsender functionality is working char *received = zstr_recv (logger); assert (received); zstr_free (&received); } zsys_close (logger, NULL, 0); { // zhash based printf zhash_t *args = zhash_new (); zhash_insert (args, "key", "value"); zhash_insert (args, "ham", "spam"); char *str = zsys_zprintf ("plain string", args); assert (streq (str, "plain string")); zstr_free (&str); str = zsys_zprintf ("%%a%%", args); assert (streq (str, "%a%")); zstr_free (&str); str = zsys_zprintf ("VALUE=%(key)s123", args); assert (streq (str, "VALUE=value123")); zstr_free (&str); str = zsys_zprintf ("VALUE=%(key)s123, %(ham)s, %(ham)s, %%(nospam)s!!!", args); assert (streq (str, "VALUE=value123, spam, spam, %(nospam)s!!!")); zstr_free (&str); str = zsys_zprintf ("VALUE=%(nokey)s123, %(ham)s, %(ham)s, %%(nospam)s!!!", args); assert (!str); str = zsys_zprintf_error ("VALUE=%(nokey)s123, %(ham)s, %(ham)s, %%(nospam)s!!!", args); assert (streq (str, "Key \*(Aqnokey\*(Aq not found in hash")); zstr_free (&str); str = zsys_zprintf ("VALUE=%(key)s/%%S", args); assert (streq (str, "VALUE=value/%S")); zstr_free (&str); zhash_destroy (&args); //ZPL based printf zconfig_t *root = zconfig_new ("root", NULL); zconfig_put (root, "zsp", ""); zconfig_put (root, "zsp/return_code", "0"); str = zsys_zplprintf ("return_code=%(zsp/return_code)s", root); assert (streq (str, "return_code=0")); zstr_free (&str); zconfig_destroy (&root); } .fi .if n \{\ .RE .\} .sp .SH "AUTHORS" .sp The czmq manual was written by the authors in the AUTHORS file\&. .SH "RESOURCES" .sp Main web site: \m[blue]\fB\%\fR\m[] .sp Report bugs to the email <\m[blue]\fBzeromq\-dev@lists\&.zeromq\&.org\fR\m[]\&\s-2\u[1]\d\s+2> .SH "COPYRIGHT" .sp Copyright (c) the Contributors as noted in the AUTHORS file\&. This file is part of CZMQ, the high\-level C binding for 0MQ: http://czmq\&.zeromq\&.org\&. This Source Code Form is subject to the terms of the Mozilla Public License, v\&. 2\&.0\&. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla\&.org/MPL/2\&.0/\&. LICENSE included with the czmq distribution\&. .SH "NOTES" .IP " 1." 4 zeromq-dev@lists.zeromq.org .RS 4 \%mailto:zeromq-dev@lists.zeromq.org .RE