fdpass 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,35 @@
1
+ = Libarchive/Ruby
2
+
3
+ == Description
4
+
5
+ This is a library to transmit the file descriptor between the processes.
6
+
7
+ == Example
8
+ === Server (Reciever)
9
+ require 'fdpass'
10
+
11
+ begin
12
+ fdpass = FDPass.server('/tmp/fdpass.sock')
13
+
14
+ t = Thread.fork {
15
+ loop do
16
+ fd = fdpass.recv
17
+ io = IO.open(fd)
18
+ io.puts('%s: %s' % [fd, __FILE__])
19
+ end
20
+ }
21
+
22
+ t.join
23
+ ensure
24
+ fdpass.close
25
+ end
26
+
27
+ == Client (Sender)
28
+ require 'fdpass'
29
+
30
+ begin
31
+ fdpass = FDPass.client('/tmp/fdpass.sock')
32
+ fdpass.send($stderr.fileno)
33
+ ensure
34
+ fdpass.close if fdpass.closed?
35
+ end
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+ $CFLAGS += ' -Wall '
3
+ create_makefile('fdpass')
@@ -0,0 +1,25 @@
1
+ #include "fdpass.h"
2
+
3
+ VALUE rb_mFDPass;
4
+ VALUE rb_eFDPassError;
5
+ extern VALUE rb_cFDPassServer;
6
+ extern VALUE rb_cFDPassClient;
7
+
8
+ static VALUE rb_fdpass_server(VALUE self, VALUE path) {
9
+ return rb_funcall(rb_cFDPassServer, rb_intern("new"), 1, path);
10
+ }
11
+
12
+ static VALUE rb_fdpass_client(VALUE self, VALUE path) {
13
+ return rb_funcall(rb_cFDPassClient, rb_intern("new"), 1, path);
14
+ }
15
+
16
+ void Init_fdpass() {
17
+ rb_mFDPass = rb_define_module("FDPass");
18
+ rb_define_module_function(rb_mFDPass, "server", rb_fdpass_server, 1);
19
+ rb_define_module_function(rb_mFDPass, "client", rb_fdpass_client, 1);
20
+
21
+ rb_eFDPassError = rb_define_class_under(rb_mFDPass, "Error", rb_eStandardError);
22
+
23
+ Init_fdpass_server();
24
+ Init_fdpass_client();
25
+ }
@@ -0,0 +1,26 @@
1
+ #ifndef __FDPASS_H__
2
+ #define __FDPASS_C__
3
+
4
+ #include <string.h>
5
+
6
+ #include <sys/socket.h>
7
+ #include <sys/un.h>
8
+ #include <sys/types.h>
9
+ #include <sys/stat.h>
10
+ #include <unistd.h>
11
+
12
+ #include <errno.h>
13
+
14
+ #include <ruby.h>
15
+
16
+ #ifndef RSTRING_PTR
17
+ #define RSTRING_PTR(s) (RSTRING(s)->ptr)
18
+ #endif
19
+ #ifndef RSTRING_LEN
20
+ #define RSTRING_LEN(s) (RSTRING(s)->len)
21
+ #endif
22
+
23
+ void Init_fdpass_server();
24
+ void Init_fdpass_client();
25
+
26
+ #endif // __FDPASS_H__
@@ -0,0 +1,88 @@
1
+ #include "fdpass.h"
2
+ #include "fdpass_socket.h"
3
+
4
+ extern VALUE rb_mFDPass;
5
+ extern VALUE rb_eFDPassError;
6
+ VALUE rb_cFDPassClient;
7
+
8
+ static VALUE rd_fdpass_client_initialize(VALUE self, VALUE path) {
9
+ struct fdpass_socket *p;
10
+ char *cpath;
11
+ int sock;
12
+ struct sockaddr_un addr;
13
+
14
+ Data_Get_Struct(self, struct fdpass_socket, p);
15
+
16
+ Check_Type(path, T_STRING);
17
+ cpath = RSTRING_PTR(path);
18
+
19
+ sock = socket(PF_UNIX, SOCK_DGRAM, 0);
20
+
21
+ if (sock < 0) {
22
+ rb_raise(rb_eFDPassError, "%s", strerror(errno));
23
+ }
24
+
25
+ memset(&addr, 0, sizeof(addr));
26
+ addr.sun_family = AF_UNIX;
27
+ strncpy(addr.sun_path, cpath, sizeof(addr.sun_path) - 1);
28
+ addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
29
+
30
+ if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
31
+ rb_raise(rb_eFDPassError, "%s", strerror(errno));
32
+ }
33
+
34
+ p->sock = sock;
35
+ p->closed = 0;
36
+ p->path = path;
37
+ p->is_server = 0;
38
+
39
+ return Qnil;
40
+ }
41
+
42
+ static VALUE rb_fdpass_client_send(VALUE self, VALUE fd) {
43
+ struct fdpass_socket *p;
44
+ struct msghdr msg = { 0 };
45
+ struct cmsghdr *cmsg;
46
+ char cmsgbuf[CMSG_SPACE(sizeof(int))];
47
+ int ifd, *cmsg_data;
48
+ struct iovec iov;
49
+
50
+ ifd = NUM2INT(fd);
51
+
52
+ Data_Get_Struct(self, struct fdpass_socket, p);
53
+ Check_Socket(p);
54
+
55
+ iov.iov_base = "\0";
56
+ iov.iov_len = 1;
57
+
58
+ msg.msg_name = NULL;
59
+ msg.msg_namelen = 0;
60
+ msg.msg_iov = &iov;
61
+ msg.msg_iovlen = 1;
62
+ msg.msg_control = cmsgbuf;
63
+ msg.msg_controllen = sizeof(cmsgbuf);
64
+
65
+ cmsg = CMSG_FIRSTHDR(&msg);
66
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
67
+ cmsg->cmsg_level = SOL_SOCKET;
68
+ cmsg->cmsg_type = SCM_RIGHTS;
69
+
70
+ cmsg_data = (int *) CMSG_DATA(cmsg);
71
+ *cmsg_data = ifd;
72
+ msg.msg_controllen = cmsg->cmsg_len;
73
+
74
+ if (sendmsg(p->sock, &msg, 0) < 0) {
75
+ rb_raise(rb_eFDPassError, "%s", strerror(errno));
76
+ }
77
+
78
+ return Qnil;
79
+ }
80
+
81
+ void Init_fdpass_client() {
82
+ rb_cFDPassClient = rb_define_class_under(rb_mFDPass, "Client", rb_cObject);
83
+ rb_define_alloc_func(rb_cFDPassClient, fdpass_socket_alloc);
84
+ rb_define_private_method(rb_cFDPassClient, "initialize", rd_fdpass_client_initialize, 1);
85
+ rb_define_method(rb_cFDPassClient, "close", rd_fdpass_socket_close, 0);
86
+ rb_define_method(rb_cFDPassClient, "closed?", rd_fdpass_socket_is_closed, 0);
87
+ rb_define_method(rb_cFDPassClient, "send", rb_fdpass_client_send, 1);
88
+ }
@@ -0,0 +1,81 @@
1
+ #include "fdpass.h"
2
+ #include "fdpass_socket.h"
3
+
4
+ extern VALUE rb_mFDPass;
5
+ extern VALUE rb_eFDPassError;
6
+ VALUE rb_cFDPassServer;
7
+
8
+ static VALUE rd_fdpass_server_initialize(VALUE self, VALUE path) {
9
+ struct fdpass_socket *p;
10
+ char *cpath;
11
+ int sock;
12
+ struct sockaddr_un addr;
13
+
14
+ Data_Get_Struct(self, struct fdpass_socket, p);
15
+
16
+ Check_Type(path, T_STRING);
17
+ cpath = RSTRING_PTR(path);
18
+
19
+ sock = socket(PF_UNIX, SOCK_DGRAM, 0);
20
+
21
+ if (sock < 0) {
22
+ rb_raise(rb_eFDPassError, "%s", strerror(errno));
23
+ }
24
+
25
+ memset(&addr, 0, sizeof(addr));
26
+ addr.sun_family = AF_UNIX;
27
+ strncpy(addr.sun_path, cpath, sizeof(addr.sun_path) - 1);
28
+ addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
29
+
30
+ if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
31
+ rb_raise(rb_eFDPassError, "%s", strerror(errno));
32
+ }
33
+
34
+ p->sock = sock;
35
+ p->closed = 0;
36
+ p->path = path;
37
+ p->is_server = 1;
38
+
39
+ return Qnil;
40
+ }
41
+
42
+ static VALUE rb_fdpass_server_recv(VALUE self) {
43
+ struct fdpass_socket *p;
44
+ struct msghdr msg = { 0 };
45
+ struct cmsghdr *cmsg;
46
+ char cmsgbuf[CMSG_SPACE(sizeof(int))];
47
+ int *cmsg_data;
48
+ struct iovec iov;
49
+ char iov_data[1];
50
+
51
+ Data_Get_Struct(self, struct fdpass_socket, p);
52
+ Check_Socket(p);
53
+
54
+ iov.iov_base = iov_data;
55
+ iov.iov_len = sizeof(iov_data);
56
+
57
+ msg.msg_name = NULL;
58
+ msg.msg_namelen = 0;
59
+ msg.msg_iov = &iov;
60
+ msg.msg_iovlen = 1;
61
+ msg.msg_control = cmsgbuf;
62
+ msg.msg_controllen = sizeof(cmsgbuf);
63
+
64
+ if (recvmsg(p->sock, &msg, MSG_WAITALL) < 0) {
65
+ rb_raise(rb_eFDPassError, "%s", strerror(errno));
66
+ }
67
+
68
+ cmsg = CMSG_FIRSTHDR(&msg);
69
+ cmsg_data = (int *) CMSG_DATA(cmsg);
70
+
71
+ return INT2NUM(*cmsg_data);
72
+ }
73
+
74
+ void Init_fdpass_server() {
75
+ rb_cFDPassServer = rb_define_class_under(rb_mFDPass, "Server", rb_cObject);
76
+ rb_define_alloc_func(rb_cFDPassServer, fdpass_socket_alloc);
77
+ rb_define_private_method(rb_cFDPassServer, "initialize", rd_fdpass_server_initialize, 1);
78
+ rb_define_method(rb_cFDPassServer, "close", rd_fdpass_socket_close, 0);
79
+ rb_define_method(rb_cFDPassServer, "closed?", rd_fdpass_socket_is_closed, 0);
80
+ rb_define_method(rb_cFDPassServer, "recv", rb_fdpass_server_recv, 0);
81
+ }
@@ -0,0 +1,64 @@
1
+ #include "fdpass_socket.h"
2
+
3
+ extern VALUE rb_eFDPassError;
4
+
5
+ static void unlink_socket(struct fdpass_socket *p) {
6
+ #ifdef S_ISSOCK
7
+ char *cpath;
8
+ struct stat st;
9
+
10
+ if (!p->is_server || NIL_P(p->path)) {
11
+ return;
12
+ }
13
+
14
+ Check_Type(p->path, T_STRING);
15
+ cpath = RSTRING_PTR(p->path);
16
+
17
+ if (stat(cpath, &st) == 0 && S_ISSOCK(st.st_mode)) {
18
+ unlink(cpath);
19
+ }
20
+ #endif
21
+ }
22
+
23
+ static void fdpass_socket_mark(struct fdpass_socket *p) {
24
+ rb_gc_mark(p->path);
25
+ }
26
+
27
+ static void fdpass_socket_free(struct fdpass_socket *p) {
28
+ if (!p->closed) {
29
+ close(p->sock);
30
+ unlink_socket(p);
31
+ }
32
+
33
+ xfree(p);
34
+ }
35
+
36
+ VALUE fdpass_socket_alloc(VALUE klass) {
37
+ struct fdpass_socket *p = ALLOC(struct fdpass_socket);
38
+ p->sock = -1;
39
+ p->closed = 1;
40
+ p->path = Qnil;
41
+ return Data_Wrap_Struct(klass, fdpass_socket_mark, fdpass_socket_free, p);
42
+ }
43
+
44
+ VALUE rd_fdpass_socket_close(VALUE self) {
45
+ struct fdpass_socket *p;
46
+
47
+ Data_Get_Struct(self, struct fdpass_socket, p);
48
+
49
+ if (!p->closed) {
50
+ close(p->sock);
51
+ unlink_socket(p);
52
+ p->sock = -1;
53
+ p->closed = 1;
54
+ p->path = Qnil;
55
+ }
56
+
57
+ return Qnil;
58
+ }
59
+
60
+ VALUE rd_fdpass_socket_is_closed(VALUE self) {
61
+ struct fdpass_socket *p;
62
+ Data_Get_Struct(self, struct fdpass_socket, p);
63
+ return p->closed ? Qtrue : Qfalse;
64
+ }
@@ -0,0 +1,24 @@
1
+ #ifndef __FDPASS_SOCKET_H__
2
+ #define __FDPASS_SOCKET_C__
3
+
4
+ #include "fdpass.h"
5
+
6
+ struct fdpass_socket {
7
+ int sock;
8
+ int closed;
9
+ VALUE path;
10
+ int is_server;
11
+ };
12
+
13
+ #define Check_Socket(p) do { \
14
+ if ((p)->sock < 0 || (p)->closed || NIL_P((p)->path)) { \
15
+ rb_raise(rb_eFDPassError, "Invalid socket"); \
16
+ } \
17
+ Check_Type((p)->path, T_STRING); \
18
+ } while(0)
19
+
20
+ VALUE fdpass_socket_alloc(VALUE klass);
21
+ VALUE rd_fdpass_socket_close(VALUE self);
22
+ VALUE rd_fdpass_socket_is_closed(VALUE self);
23
+
24
+ #endif // __FDPASS_SOCKET_H__
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fdpass
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - winebarrel
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-01 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description:
23
+ email: sgwr_dts@yahoo.co.jp
24
+ executables: []
25
+
26
+ extensions:
27
+ - ext/extconf.rb
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - ext/fdpass.c
32
+ - ext/fdpass_client.c
33
+ - ext/fdpass_server.c
34
+ - ext/fdpass_socket.c
35
+ - ext/fdpass.h
36
+ - ext/fdpass_socket.h
37
+ - ext/extconf.rb
38
+ - README
39
+ has_rdoc: true
40
+ homepage: https://github.com/winebarrel/fdpass
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ hash: 3
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.7
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: This is a library to transmit the file descriptor between the processes.
73
+ test_files: []
74
+