Difference between revisions of "Code Snippets"
(Added glib event loop for erlang port driver) |
|||
Line 43: | Line 43: | ||
sock.puts("HI!") | sock.puts("HI!") | ||
puts sock.gets | puts sock.gets | ||
+ | |||
+ | Here's a GLIB event loop for an erlang port program (that communicates with the VM over stdio). The port is set up for {packet, 2} mode which means all messages (sending and receiving) are prefixed with a 2 byte (16 bit) 'length' field. | ||
+ | |||
+ | #include <sys/uio.h> | ||
+ | #include <unistd.h> | ||
+ | #include <arpa/inet.h> | ||
+ | #include <glib.h> | ||
+ | |||
+ | gboolean socket_data(GIOChannel *source, GIOCondition condition, gpointer data) { | ||
+ | uint16_t len; | ||
+ | uint16_t inlen; | ||
+ | char *inbuf; | ||
+ | |||
+ | if (condition == G_IO_IN) { | ||
+ | read(0, &len, 2); | ||
+ | inlen = ntohs(len); | ||
+ | inbuf = malloc(inlen + 1); | ||
+ | |||
+ | memset(inbuf, 0, inlen+1); | ||
+ | |||
+ | read(0, inbuf, inlen); | ||
+ | |||
+ | write(1, &len, sizeof(uint16_t)); | ||
+ | write(1, inbuf, strlen(inbuf)); | ||
+ | free(inbuf); | ||
+ | } else { | ||
+ | g_main_loop_quit((GMainLoop*) data); | ||
+ | return FALSE; | ||
+ | } | ||
+ | |||
+ | return TRUE; | ||
+ | } | ||
+ | |||
+ | int main(int argc, char** argv) { | ||
+ | GMainLoop *mainloop = g_main_loop_new (NULL, FALSE); | ||
+ | GIOChannel *chan = g_io_channel_unix_new(0); | ||
+ | g_io_add_watch(chan, G_IO_IN | G_IO_HUP | G_IO_ERR, socket_data, mainloop); | ||
+ | |||
+ | g_main_loop_run (mainloop); | ||
+ | |||
+ | return 0; | ||
+ | } |
Revision as of 12:27, 17 August 2009
This page holds random code snippets that do cool things:
This snippet creates a subprocess with a bi-directional pipe between them for communication. It can be used for (for example) wrapping a ssh connection (if you call setsid ssh will use the command defined in SSH_ASKPASS to request the password), daemonizing a process (see also Daemonize) or many other things...
require 'socket'
# create a new stream socket pair in the unix domain input, output = Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM, 0) if pid = fork # forktastic Process.detach(pid) # if we exit, make sure the child doesn't zombie input.puts 'ho' sleep 10 input.puts 'bye' puts output.gets else Process.setsid # make the forked process run in a new session puts output.gets puts output.gets sleep 5 input.puts 'farewell' end
This snippet connects to a UNIX socket on the machine. If the server isn't running; it spawns one in a subprocess and detaches it. This is useful for robustness.
require 'socket'
PATH=File.join(ENV['HOME'], '.testsock')
begin sock = UNIXSocket.new(PATH) rescue Errno::ENOENT, Errno::ECONNREFUSED => e File.delete(PATH) if File.socket?(PATH) if pid = fork() Process.detach(pid) sleep 1 retry else server = UNIXServer.new(PATH) loop do sock = server.accept sock.puts("Echo: "+sock.gets) end end end
sock.puts("HI!") puts sock.gets
Here's a GLIB event loop for an erlang port program (that communicates with the VM over stdio). The port is set up for {packet, 2} mode which means all messages (sending and receiving) are prefixed with a 2 byte (16 bit) 'length' field.
#include <sys/uio.h> #include <unistd.h> #include <arpa/inet.h> #include <glib.h>
gboolean socket_data(GIOChannel *source, GIOCondition condition, gpointer data) { uint16_t len; uint16_t inlen; char *inbuf; if (condition == G_IO_IN) { read(0, &len, 2); inlen = ntohs(len); inbuf = malloc(inlen + 1); memset(inbuf, 0, inlen+1); read(0, inbuf, inlen); write(1, &len, sizeof(uint16_t)); write(1, inbuf, strlen(inbuf)); free(inbuf); } else { g_main_loop_quit((GMainLoop*) data); return FALSE; } return TRUE; } int main(int argc, char** argv) { GMainLoop *mainloop = g_main_loop_new (NULL, FALSE); GIOChannel *chan = g_io_channel_unix_new(0); g_io_add_watch(chan, G_IO_IN | G_IO_HUP | G_IO_ERR, socket_data, mainloop); g_main_loop_run (mainloop); return 0; }