launch 1.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig ADDED
@@ -0,0 +1 @@
1
+ d�(4�äQIm�v��H�������Pp6f��#��P�Ob�JњL��.t�K2>���;��j��[�<v�I?7v���̸$D{C<�� �&7۲���L��M[WO�� �����ԋkU�)X^)?SƋ��6s'K,ǝ�o~D�ub��PN}�l���(�]/��7��t�|vy�Yr��3N��:����)�H}�������;dSš��a���ǵ���?�r`'��s`@�un�+��A}b����J|%[�U
data/.autotest ADDED
@@ -0,0 +1,8 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ Autotest.add_hook :initialize do |at|
6
+ at.testlib = 'minitest/autorun'
7
+ end
8
+
data/.gemtest ADDED
File without changes
data/History.txt ADDED
@@ -0,0 +1,5 @@
1
+ === 1.0 / 2011-02-26
2
+
3
+ * Major enhancements
4
+ * Birthday!
5
+
data/Manifest.txt ADDED
@@ -0,0 +1,11 @@
1
+ .autotest
2
+ History.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ ext/launch/extconf.rb
7
+ ext/launch/launch.c
8
+ lib/launch.rb
9
+ lib/launch/webrick.rb
10
+ sample/echo.rb
11
+ test/test_launch.rb
data/README.txt ADDED
@@ -0,0 +1,72 @@
1
+ = launch
2
+
3
+ * https://github.com/drbrain/launch
4
+ * http://docs.seattlerb.org/launch
5
+
6
+ == DESCRIPTION:
7
+
8
+ Launch allows agents and daemons launched by launchd to retrieve their list of
9
+ sockets. Launchd is an open source framework for launching and managing
10
+ daemons, programs and scripts provided by Apple.
11
+
12
+ == FEATURES/PROBLEMS:
13
+
14
+ * Provides the Launch module for easy integration with existing programs
15
+ * Allows on-demand execution of ruby programs through launchd
16
+
17
+ == SYNOPSIS:
18
+
19
+ require 'launch'
20
+
21
+ class MyDaemon
22
+ def initialize
23
+ launch_checkin
24
+ launch_sockets('MyDaemonSocket', TCPServer).each do |server|
25
+ # handle requests, see sample/echo.rb
26
+ end
27
+ end
28
+ end
29
+
30
+ MyDaemon.new
31
+
32
+ == REQUIREMENTS:
33
+
34
+ * An installed launchd
35
+
36
+ == INSTALL:
37
+
38
+ gem install launch
39
+
40
+ == DEVELOPERS:
41
+
42
+ After checking out the source, run:
43
+
44
+ $ rake newb
45
+
46
+ This task will install any missing dependencies, run the tests/specs,
47
+ and generate the RDoc.
48
+
49
+ == LICENSE:
50
+
51
+ (The MIT License)
52
+
53
+ Copyright (c) 2011 Eric Hodel
54
+
55
+ Permission is hereby granted, free of charge, to any person obtaining
56
+ a copy of this software and associated documentation files (the
57
+ 'Software'), to deal in the Software without restriction, including
58
+ without limitation the rights to use, copy, modify, merge, publish,
59
+ distribute, sublicense, and/or sell copies of the Software, and to
60
+ permit persons to whom the Software is furnished to do so, subject to
61
+ the following conditions:
62
+
63
+ The above copyright notice and this permission notice shall be
64
+ included in all copies or substantial portions of the Software.
65
+
66
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
67
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
69
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
70
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
71
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
72
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ # -*- ruby -*-
2
+
3
+ task :default => :compile
4
+
5
+ require 'rubygems'
6
+ require 'hoe'
7
+
8
+ Hoe.plugin :minitest
9
+ Hoe.plugin :git
10
+
11
+ hoe = Hoe.spec 'launch' do
12
+ developer 'Eric Hodel', 'drbrain@segment7.net'
13
+
14
+ rdoc_locations << 'docs.seattlerb.org:/data/www/docs.seattlerb.org/launch/'
15
+
16
+ extra_dev_deps << ['rake-compiler', '~> 0.7']
17
+ self.spec_extras[:extensions] = %w[ext/launch/extconf.rb]
18
+
19
+ self.spec_extras[:required_ruby_version] = '>= 1.9.2'
20
+
21
+ self.clean_globs = %[
22
+ lib/launch/launch.bundle
23
+ ]
24
+ end
25
+
26
+ begin
27
+ gem 'rake-compiler', '~> 0.7'
28
+ require 'rake/extensiontask'
29
+
30
+ Rake::ExtensionTask.new hoe.name, hoe.spec do |ext|
31
+ ext.lib_dir = File.join 'lib', 'launch'
32
+ end
33
+ rescue Gem::LoadError
34
+ warn 'You need to rake newb'
35
+ end
36
+
37
+ # vim: syntax=ruby
@@ -0,0 +1,6 @@
1
+ require 'mkmf'
2
+
3
+ abort unless have_header 'launch.h'
4
+
5
+ create_makefile 'launch/launch'
6
+
@@ -0,0 +1,355 @@
1
+ #include <ruby.h>
2
+ #include <launch.h>
3
+ #include <errno.h>
4
+ #include <stdio.h>
5
+
6
+ VALUE mLaunch;
7
+ VALUE mLaunchKey;
8
+ VALUE mLaunchJobKey;
9
+ VALUE mLaunchSocket;
10
+ VALUE mLaunchJobPolicy;
11
+ VALUE mLaunchData;
12
+ VALUE cLaunchError;
13
+
14
+ static VALUE launch_data_to_ruby(launch_data_t);
15
+
16
+ static void
17
+ launch_dict_iterator(launch_data_t item, const char * key, void * hash) {
18
+ rb_hash_aset((VALUE)hash, rb_str_new2(key), launch_data_to_ruby(item));
19
+ }
20
+
21
+ static VALUE
22
+ launch_data_to_ruby(launch_data_t item) {
23
+ VALUE out = Qnil;
24
+ launch_data_t temp = NULL;
25
+ launch_data_type_t item_type = launch_data_get_type(item);
26
+ int i = 0;
27
+ size_t length = 0;
28
+
29
+ switch(item_type) {
30
+ case LAUNCH_DATA_DICTIONARY:
31
+ out = rb_hash_new();
32
+
33
+ launch_data_dict_iterate(item, launch_dict_iterator, (void *)out);
34
+
35
+ break;
36
+ case LAUNCH_DATA_ARRAY:
37
+ length = launch_data_array_get_count(item);
38
+ out = rb_ary_new2(length);
39
+
40
+ for (i = 0; i < length; i++) {
41
+ temp = launch_data_array_get_index(item, i);
42
+ rb_ary_store(out, i, launch_data_to_ruby(temp));
43
+ }
44
+
45
+ break;
46
+ case LAUNCH_DATA_FD:
47
+ out = INT2NUM(launch_data_get_fd(item));
48
+ break;
49
+ case LAUNCH_DATA_INTEGER:
50
+ out = LONG2NUM(launch_data_get_integer(item));
51
+ break;
52
+ case LAUNCH_DATA_REAL:
53
+ out = DBL2NUM(launch_data_get_real(item));
54
+ break;
55
+ case LAUNCH_DATA_BOOL:
56
+ out = launch_data_get_bool(item) == TRUE ? Qtrue : Qfalse;
57
+ break;
58
+ case LAUNCH_DATA_STRING:
59
+ out = rb_str_new2(launch_data_get_string(item));
60
+ break;
61
+ case LAUNCH_DATA_OPAQUE:
62
+ out = rb_str_new(launch_data_get_opaque(item),
63
+ launch_data_get_opaque_size(item));
64
+ break;
65
+ case LAUNCH_DATA_ERRNO:
66
+ out = INT2NUM(launch_data_get_errno(item));
67
+ break;
68
+ case LAUNCH_DATA_MACHPORT:
69
+ break;
70
+ default:
71
+ rb_raise(cLaunchError, "unknown item type %d", item_type);
72
+ }
73
+
74
+ return out;
75
+ }
76
+
77
+ /*
78
+ * call-seq:
79
+ * launch_message(Launch::Key::CHECKIN) # => response
80
+ *
81
+ * launch_message wraps launch(3)'s launch_msg function. The argument is a
82
+ * message to send launchd from Launch::Key. Please use launch_checkin
83
+ * and launch_sockets instead of this method.
84
+ *
85
+ * The response from launchd is converted to a ruby structure and freed
86
+ * (usually a Hash). Currently the following data types in the response are
87
+ * indistinguishable in the ruby structure:
88
+ *
89
+ * * STRING and OPAQUE
90
+ * * INTEGER, FD and ERRNO
91
+ *
92
+ * Additionally, MACHPORT is ignored.
93
+ *
94
+ * If there was a failure to retrieve checkin data an error will be raised.
95
+ */
96
+ static VALUE
97
+ message(VALUE self, VALUE message) {
98
+ VALUE out, tmp;
99
+ launch_data_t send, response;
100
+ launch_data_type_t response_type;
101
+
102
+ message = rb_str_to_str(message);
103
+
104
+ send = launch_data_new_string(StringValueCStr(message));
105
+
106
+ if (send == NULL) {
107
+ tmp = rb_inspect(message);
108
+ rb_raise(cLaunchError, "unable to create message %s",
109
+ StringValueCStr(tmp));
110
+ }
111
+
112
+ response = launch_msg(send);
113
+
114
+ if (response == NULL)
115
+ rb_sys_fail("launch_msg");
116
+
117
+ response_type = launch_data_get_type(response);
118
+
119
+ if (response_type == LAUNCH_DATA_ERRNO) {
120
+ errno = launch_data_get_errno(response);
121
+ rb_sys_fail("launch_msg");
122
+ }
123
+
124
+ out = launch_data_to_ruby(response);
125
+
126
+ launch_data_free(response);
127
+
128
+ return out;
129
+ }
130
+
131
+ void
132
+ Init_launch() {
133
+ mLaunch = rb_define_module("Launch");
134
+ cLaunchError = rb_define_class_under(mLaunch, "Error", rb_eRuntimeError);
135
+
136
+ rb_define_method(mLaunch, "launch_message", message, 1);
137
+
138
+ rb_const_set(mLaunch, rb_intern("JOBINETDCOMPATIBILITY_WAIT"),
139
+ rb_str_new2(LAUNCH_JOBINETDCOMPATIBILITY_WAIT));
140
+
141
+ /*
142
+ * Launch::Key holds launch message types
143
+ */
144
+ mLaunchKey = rb_define_module_under(mLaunch, "Key");
145
+ rb_const_set(mLaunchKey, rb_intern("SUBMITJOB"),
146
+ rb_str_new2(LAUNCH_KEY_SUBMITJOB));
147
+ rb_const_set(mLaunchKey, rb_intern("REMOVEJOB"),
148
+ rb_str_new2(LAUNCH_KEY_REMOVEJOB));
149
+ rb_const_set(mLaunchKey, rb_intern("STARTJOB"),
150
+ rb_str_new2(LAUNCH_KEY_STARTJOB));
151
+ rb_const_set(mLaunchKey, rb_intern("STOPJOB"),
152
+ rb_str_new2(LAUNCH_KEY_STOPJOB));
153
+ rb_const_set(mLaunchKey, rb_intern("GETJOB"),
154
+ rb_str_new2(LAUNCH_KEY_GETJOB));
155
+ rb_const_set(mLaunchKey, rb_intern("GETJOBS"),
156
+ rb_str_new2(LAUNCH_KEY_GETJOBS));
157
+ rb_const_set(mLaunchKey, rb_intern("CHECKIN"),
158
+ rb_str_new2(LAUNCH_KEY_CHECKIN));
159
+
160
+ /*
161
+ * Launch::JobKey holds various keys returned in a message response
162
+ */
163
+ mLaunchJobKey = rb_define_module_under(mLaunch, "JobKey");
164
+ rb_const_set(mLaunchJobKey, rb_intern("LABEL"),
165
+ rb_str_new2(LAUNCH_JOBKEY_LABEL));
166
+ rb_const_set(mLaunchJobKey, rb_intern("DISABLED"),
167
+ rb_str_new2(LAUNCH_JOBKEY_DISABLED));
168
+ rb_const_set(mLaunchJobKey, rb_intern("USERNAME"),
169
+ rb_str_new2(LAUNCH_JOBKEY_USERNAME));
170
+ rb_const_set(mLaunchJobKey, rb_intern("GROUPNAME"),
171
+ rb_str_new2(LAUNCH_JOBKEY_GROUPNAME));
172
+ rb_const_set(mLaunchJobKey, rb_intern("TIMEOUT"),
173
+ rb_str_new2(LAUNCH_JOBKEY_TIMEOUT));
174
+ rb_const_set(mLaunchJobKey, rb_intern("EXITTIMEOUT"),
175
+ rb_str_new2(LAUNCH_JOBKEY_EXITTIMEOUT));
176
+ rb_const_set(mLaunchJobKey, rb_intern("INITGROUPS"),
177
+ rb_str_new2(LAUNCH_JOBKEY_INITGROUPS));
178
+ rb_const_set(mLaunchJobKey, rb_intern("SOCKETS"),
179
+ rb_str_new2(LAUNCH_JOBKEY_SOCKETS));
180
+ rb_const_set(mLaunchJobKey, rb_intern("MACHSERVICES"),
181
+ rb_str_new2(LAUNCH_JOBKEY_MACHSERVICES));
182
+ rb_const_set(mLaunchJobKey, rb_intern("MACHSERVICELOOKUPPOLICIES"),
183
+ rb_str_new2(LAUNCH_JOBKEY_MACHSERVICELOOKUPPOLICIES));
184
+ rb_const_set(mLaunchJobKey, rb_intern("INETDCOMPATIBILITY"),
185
+ rb_str_new2(LAUNCH_JOBKEY_INETDCOMPATIBILITY));
186
+ rb_const_set(mLaunchJobKey, rb_intern("ENABLEGLOBBING"),
187
+ rb_str_new2(LAUNCH_JOBKEY_ENABLEGLOBBING));
188
+ rb_const_set(mLaunchJobKey, rb_intern("PROGRAMARGUMENTS"),
189
+ rb_str_new2(LAUNCH_JOBKEY_PROGRAMARGUMENTS));
190
+ rb_const_set(mLaunchJobKey, rb_intern("PROGRAM"),
191
+ rb_str_new2(LAUNCH_JOBKEY_PROGRAM));
192
+ rb_const_set(mLaunchJobKey, rb_intern("ONDEMAND"),
193
+ rb_str_new2(LAUNCH_JOBKEY_ONDEMAND));
194
+ rb_const_set(mLaunchJobKey, rb_intern("KEEPALIVE"),
195
+ rb_str_new2(LAUNCH_JOBKEY_KEEPALIVE));
196
+ rb_const_set(mLaunchJobKey, rb_intern("LIMITLOADTOHOSTS"),
197
+ rb_str_new2(LAUNCH_JOBKEY_LIMITLOADTOHOSTS));
198
+ rb_const_set(mLaunchJobKey, rb_intern("LIMITLOADFROMHOSTS"),
199
+ rb_str_new2(LAUNCH_JOBKEY_LIMITLOADFROMHOSTS));
200
+ rb_const_set(mLaunchJobKey, rb_intern("LIMITLOADTOSESSIONTYPE"),
201
+ rb_str_new2(LAUNCH_JOBKEY_LIMITLOADTOSESSIONTYPE));
202
+ rb_const_set(mLaunchJobKey, rb_intern("RUNATLOAD"),
203
+ rb_str_new2(LAUNCH_JOBKEY_RUNATLOAD));
204
+ rb_const_set(mLaunchJobKey, rb_intern("ROOTDIRECTORY"),
205
+ rb_str_new2(LAUNCH_JOBKEY_ROOTDIRECTORY));
206
+ rb_const_set(mLaunchJobKey, rb_intern("WORKINGDIRECTORY"),
207
+ rb_str_new2(LAUNCH_JOBKEY_WORKINGDIRECTORY));
208
+ rb_const_set(mLaunchJobKey, rb_intern("ENVIRONMENTVARIABLES"),
209
+ rb_str_new2(LAUNCH_JOBKEY_ENVIRONMENTVARIABLES));
210
+ rb_const_set(mLaunchJobKey, rb_intern("USERENVIRONMENTVARIABLES"),
211
+ rb_str_new2(LAUNCH_JOBKEY_USERENVIRONMENTVARIABLES));
212
+ rb_const_set(mLaunchJobKey, rb_intern("UMASK"),
213
+ rb_str_new2(LAUNCH_JOBKEY_UMASK));
214
+ rb_const_set(mLaunchJobKey, rb_intern("NICE"),
215
+ rb_str_new2(LAUNCH_JOBKEY_NICE));
216
+ rb_const_set(mLaunchJobKey, rb_intern("HOPEFULLYEXITSFIRST"),
217
+ rb_str_new2(LAUNCH_JOBKEY_HOPEFULLYEXITSFIRST));
218
+ rb_const_set(mLaunchJobKey, rb_intern("HOPEFULLYEXITSLAST"),
219
+ rb_str_new2(LAUNCH_JOBKEY_HOPEFULLYEXITSLAST));
220
+ rb_const_set(mLaunchJobKey, rb_intern("LOWPRIORITYIO"),
221
+ rb_str_new2(LAUNCH_JOBKEY_LOWPRIORITYIO));
222
+ rb_const_set(mLaunchJobKey, rb_intern("SESSIONCREATE"),
223
+ rb_str_new2(LAUNCH_JOBKEY_SESSIONCREATE));
224
+ rb_const_set(mLaunchJobKey, rb_intern("STARTONMOUNT"),
225
+ rb_str_new2(LAUNCH_JOBKEY_STARTONMOUNT));
226
+ rb_const_set(mLaunchJobKey, rb_intern("SOFTRESOURCELIMITS"),
227
+ rb_str_new2(LAUNCH_JOBKEY_SOFTRESOURCELIMITS));
228
+ rb_const_set(mLaunchJobKey, rb_intern("HARDRESOURCELIMITS"),
229
+ rb_str_new2(LAUNCH_JOBKEY_HARDRESOURCELIMITS));
230
+ rb_const_set(mLaunchJobKey, rb_intern("STANDARDINPATH"),
231
+ rb_str_new2(LAUNCH_JOBKEY_STANDARDINPATH));
232
+ rb_const_set(mLaunchJobKey, rb_intern("STANDARDOUTPATH"),
233
+ rb_str_new2(LAUNCH_JOBKEY_STANDARDOUTPATH));
234
+ rb_const_set(mLaunchJobKey, rb_intern("STANDARDERRORPATH"),
235
+ rb_str_new2(LAUNCH_JOBKEY_STANDARDERRORPATH));
236
+ rb_const_set(mLaunchJobKey, rb_intern("DEBUG"),
237
+ rb_str_new2(LAUNCH_JOBKEY_DEBUG));
238
+ rb_const_set(mLaunchJobKey, rb_intern("WAITFORDEBUGGER"),
239
+ rb_str_new2(LAUNCH_JOBKEY_WAITFORDEBUGGER));
240
+ rb_const_set(mLaunchJobKey, rb_intern("QUEUEDIRECTORIES"),
241
+ rb_str_new2(LAUNCH_JOBKEY_QUEUEDIRECTORIES));
242
+ rb_const_set(mLaunchJobKey, rb_intern("WATCHPATHS"),
243
+ rb_str_new2(LAUNCH_JOBKEY_WATCHPATHS));
244
+ rb_const_set(mLaunchJobKey, rb_intern("STARTINTERVAL"),
245
+ rb_str_new2(LAUNCH_JOBKEY_STARTINTERVAL));
246
+ rb_const_set(mLaunchJobKey, rb_intern("STARTCALENDARINTERVAL"),
247
+ rb_str_new2(LAUNCH_JOBKEY_STARTCALENDARINTERVAL));
248
+ rb_const_set(mLaunchJobKey, rb_intern("BONJOURFDS"),
249
+ rb_str_new2(LAUNCH_JOBKEY_BONJOURFDS));
250
+ rb_const_set(mLaunchJobKey, rb_intern("LASTEXITSTATUS"),
251
+ rb_str_new2(LAUNCH_JOBKEY_LASTEXITSTATUS));
252
+ rb_const_set(mLaunchJobKey, rb_intern("PID"),
253
+ rb_str_new2(LAUNCH_JOBKEY_PID));
254
+ rb_const_set(mLaunchJobKey, rb_intern("THROTTLEINTERVAL"),
255
+ rb_str_new2(LAUNCH_JOBKEY_THROTTLEINTERVAL));
256
+ rb_const_set(mLaunchJobKey, rb_intern("LAUNCHONLYONCE"),
257
+ rb_str_new2(LAUNCH_JOBKEY_LAUNCHONLYONCE));
258
+ rb_const_set(mLaunchJobKey, rb_intern("ABANDONPROCESSGROUP"),
259
+ rb_str_new2(LAUNCH_JOBKEY_ABANDONPROCESSGROUP));
260
+ rb_const_set(mLaunchJobKey, rb_intern("IGNOREPROCESSGROUPATSHUTDOWN"),
261
+ rb_str_new2(LAUNCH_JOBKEY_IGNOREPROCESSGROUPATSHUTDOWN));
262
+ rb_const_set(mLaunchJobKey, rb_intern("POLICIES"),
263
+ rb_str_new2(LAUNCH_JOBKEY_POLICIES));
264
+ rb_const_set(mLaunchJobKey, rb_intern("ENABLETRANSACTIONS"),
265
+ rb_str_new2(LAUNCH_JOBKEY_ENABLETRANSACTIONS));
266
+
267
+ rb_const_set(mLaunchJobKey, rb_intern("MACH_RESETATCLOSE"),
268
+ rb_str_new2(LAUNCH_JOBKEY_MACH_RESETATCLOSE));
269
+ rb_const_set(mLaunchJobKey, rb_intern("MACH_HIDEUNTILCHECKIN"),
270
+ rb_str_new2(LAUNCH_JOBKEY_MACH_HIDEUNTILCHECKIN));
271
+ rb_const_set(mLaunchJobKey, rb_intern("MACH_DRAINMESSAGESONCRASH"),
272
+ rb_str_new2(LAUNCH_JOBKEY_MACH_DRAINMESSAGESONCRASH));
273
+
274
+ rb_const_set(mLaunchJobKey, rb_intern("KEEPALIVE_SUCCESSFULEXIT"),
275
+ rb_str_new2(LAUNCH_JOBKEY_KEEPALIVE_SUCCESSFULEXIT));
276
+ rb_const_set(mLaunchJobKey, rb_intern("KEEPALIVE_NETWORKSTATE"),
277
+ rb_str_new2(LAUNCH_JOBKEY_KEEPALIVE_NETWORKSTATE));
278
+ rb_const_set(mLaunchJobKey, rb_intern("KEEPALIVE_PATHSTATE"),
279
+ rb_str_new2(LAUNCH_JOBKEY_KEEPALIVE_PATHSTATE));
280
+ rb_const_set(mLaunchJobKey, rb_intern("KEEPALIVE_OTHERJOBACTIVE"),
281
+ rb_str_new2(LAUNCH_JOBKEY_KEEPALIVE_OTHERJOBACTIVE));
282
+ rb_const_set(mLaunchJobKey, rb_intern("KEEPALIVE_OTHERJOBENABLED"),
283
+ rb_str_new2(LAUNCH_JOBKEY_KEEPALIVE_OTHERJOBENABLED));
284
+ rb_const_set(mLaunchJobKey, rb_intern("KEEPALIVE_AFTERINITIALDEMAND"),
285
+ rb_str_new2(LAUNCH_JOBKEY_KEEPALIVE_AFTERINITIALDEMAND));
286
+
287
+ rb_const_set(mLaunchJobKey, rb_intern("CAL_MINUTE"),
288
+ rb_str_new2(LAUNCH_JOBKEY_CAL_MINUTE));
289
+ rb_const_set(mLaunchJobKey, rb_intern("CAL_HOUR"),
290
+ rb_str_new2(LAUNCH_JOBKEY_CAL_HOUR));
291
+ rb_const_set(mLaunchJobKey, rb_intern("CAL_DAY"),
292
+ rb_str_new2(LAUNCH_JOBKEY_CAL_DAY));
293
+ rb_const_set(mLaunchJobKey, rb_intern("CAL_WEEKDAY"),
294
+ rb_str_new2(LAUNCH_JOBKEY_CAL_WEEKDAY));
295
+ rb_const_set(mLaunchJobKey, rb_intern("CAL_MONTH"),
296
+ rb_str_new2(LAUNCH_JOBKEY_CAL_MONTH));
297
+
298
+ rb_const_set(mLaunchJobKey, rb_intern("RESOURCELIMIT_CORE"),
299
+ rb_str_new2(LAUNCH_JOBKEY_RESOURCELIMIT_CORE));
300
+ rb_const_set(mLaunchJobKey, rb_intern("RESOURCELIMIT_CPU"),
301
+ rb_str_new2(LAUNCH_JOBKEY_RESOURCELIMIT_CPU));
302
+ rb_const_set(mLaunchJobKey, rb_intern("RESOURCELIMIT_DATA"),
303
+ rb_str_new2(LAUNCH_JOBKEY_RESOURCELIMIT_DATA));
304
+ rb_const_set(mLaunchJobKey, rb_intern("RESOURCELIMIT_FSIZE"),
305
+ rb_str_new2(LAUNCH_JOBKEY_RESOURCELIMIT_FSIZE));
306
+ rb_const_set(mLaunchJobKey, rb_intern("RESOURCELIMIT_MEMLOCK"),
307
+ rb_str_new2(LAUNCH_JOBKEY_RESOURCELIMIT_MEMLOCK));
308
+ rb_const_set(mLaunchJobKey, rb_intern("RESOURCELIMIT_NOFILE"),
309
+ rb_str_new2(LAUNCH_JOBKEY_RESOURCELIMIT_NOFILE));
310
+ rb_const_set(mLaunchJobKey, rb_intern("RESOURCELIMIT_NPROC"),
311
+ rb_str_new2(LAUNCH_JOBKEY_RESOURCELIMIT_NPROC));
312
+ rb_const_set(mLaunchJobKey, rb_intern("RESOURCELIMIT_RSS"),
313
+ rb_str_new2(LAUNCH_JOBKEY_RESOURCELIMIT_RSS));
314
+ rb_const_set(mLaunchJobKey, rb_intern("RESOURCELIMIT_STACK"),
315
+ rb_str_new2(LAUNCH_JOBKEY_RESOURCELIMIT_STACK));
316
+
317
+ rb_const_set(mLaunchJobKey, rb_intern("DISABLED_MACHINETYPE"),
318
+ rb_str_new2(LAUNCH_JOBKEY_DISABLED_MACHINETYPE));
319
+ rb_const_set(mLaunchJobKey, rb_intern("DISABLED_MODELNAME"),
320
+ rb_str_new2(LAUNCH_JOBKEY_DISABLED_MODELNAME));
321
+
322
+ /*
323
+ * Launch::Socket holds various socket keys
324
+ */
325
+ mLaunchSocket = rb_define_module_under(mLaunch, "Socket");
326
+ rb_const_set(mLaunchSocket, rb_intern("TYPE"),
327
+ rb_str_new2(LAUNCH_JOBSOCKETKEY_TYPE));
328
+ rb_const_set(mLaunchSocket, rb_intern("PASSIVE"),
329
+ rb_str_new2(LAUNCH_JOBSOCKETKEY_PASSIVE));
330
+ rb_const_set(mLaunchSocket, rb_intern("BONJOUR"),
331
+ rb_str_new2(LAUNCH_JOBSOCKETKEY_BONJOUR));
332
+ rb_const_set(mLaunchSocket, rb_intern("SECUREWITHKEY"),
333
+ rb_str_new2(LAUNCH_JOBSOCKETKEY_SECUREWITHKEY));
334
+ rb_const_set(mLaunchSocket, rb_intern("PATHNAME"),
335
+ rb_str_new2(LAUNCH_JOBSOCKETKEY_PATHNAME));
336
+ rb_const_set(mLaunchSocket, rb_intern("PATHMODE"),
337
+ rb_str_new2(LAUNCH_JOBSOCKETKEY_PATHMODE));
338
+ rb_const_set(mLaunchSocket, rb_intern("NODENAME"),
339
+ rb_str_new2(LAUNCH_JOBSOCKETKEY_NODENAME));
340
+ rb_const_set(mLaunchSocket, rb_intern("SERVICENAME"),
341
+ rb_str_new2(LAUNCH_JOBSOCKETKEY_SERVICENAME));
342
+ rb_const_set(mLaunchSocket, rb_intern("FAMILY"),
343
+ rb_str_new2(LAUNCH_JOBSOCKETKEY_FAMILY));
344
+ rb_const_set(mLaunchSocket, rb_intern("PROTOCOL"),
345
+ rb_str_new2(LAUNCH_JOBSOCKETKEY_PROTOCOL));
346
+ rb_const_set(mLaunchSocket, rb_intern("MULTICASTGROUP"),
347
+ rb_str_new2(LAUNCH_JOBSOCKETKEY_MULTICASTGROUP));
348
+
349
+ /*
350
+ * Launch::JobPolicy holds the job policy keys
351
+ */
352
+ mLaunchJobPolicy = rb_define_module_under(mLaunch, "JobPolicy");
353
+ rb_const_set(mLaunchJobPolicy, rb_intern("DENYCREATINGOTHERJOBS"),
354
+ rb_str_new2(LAUNCH_JOBPOLICY_DENYCREATINGOTHERJOBS));
355
+ }
data/lib/launch.rb ADDED
@@ -0,0 +1,86 @@
1
+ ##
2
+ # Launch is a wrapper for the launch(3) API for daemons and agents spawned by
3
+ # launchd(8).
4
+ #
5
+ # Launch agents and daemons MUST NOT:
6
+ #
7
+ # * Call daemon(3)
8
+ # * Do the equivalent of daemon(3) by calling fork and having the parent exit
9
+ #
10
+ # Launch agents and daemons SHOULD NOT do the following as part of their
11
+ # starup initialization:
12
+ #
13
+ # * Set the user ID or group ID (Process::Sys.setuid, Process::Sys.setgid and
14
+ # friends)
15
+ # * Setup the working directory (Dir.chdir)
16
+ # * chroot(2)
17
+ # * setsid(2) (Process.setsid)
18
+ # * Close "stray" file descriptors
19
+ # * Change stdio(3) to /dev/null (STDOUT.reopen and friends)
20
+ # * Setup resource limits with setrusage (Process.setrlimit)
21
+ # * Ignore the SIGTERM signal (trap 'TERM', 'IGNORE')
22
+ #
23
+ # The above is from launchd.plist(5). Please read it for further details.
24
+ #
25
+ # To shut down cleanly <tt>trap 'TERM'</tt> and perform any shutdown steps
26
+ # before exiting.
27
+
28
+ module Launch
29
+
30
+ ##
31
+ # The version of launch you are using
32
+
33
+ VERSION = '1.0'
34
+
35
+ ##
36
+ # Checks in with launch and retrieves the agent's configuration. The
37
+ # configuration can be retrieved later through <tt>@launch_checkin<tt>.
38
+
39
+ def launch_checkin
40
+ response = launch_message Launch::Key::CHECKIN
41
+
42
+ return if response.nil?
43
+
44
+ @launch_checkin = response
45
+ end
46
+
47
+ ##
48
+ # Creates ruby sockets from the sockets list in +name+.
49
+ # <tt>socket_class.for_fd</tt> is called for each socket in the named list.
50
+ #
51
+ # +name+ comes from the socket's name key in the launchd plist.
52
+ #
53
+ # Example plist Sockets dictionary:
54
+ #
55
+ # <key>Sockets</key>
56
+ # <dict>
57
+ # <key>EchoSocket</key>
58
+ # <dict>
59
+ # <key>SockServiceName</key>
60
+ # <string>12345</string>
61
+ # </dict>
62
+ # </dict>
63
+ #
64
+ # Example call:
65
+ #
66
+ # servers = launch_sockets 'Echo', TCPServer
67
+ #
68
+ # p servers.map { |server| server.addr }
69
+
70
+ def launch_sockets name, socket_class
71
+ require 'socket'
72
+
73
+ sockets = @launch_checkin[Launch::JobKey::SOCKETS][name]
74
+
75
+ raise Error, "no sockets found for #{name.inspect}" unless sockets
76
+
77
+ sockets.map do |fd|
78
+ socket_class.for_fd fd
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ require 'launch/launch'
85
+ require 'socket'
86
+
@@ -0,0 +1,78 @@
1
+ require 'launch'
2
+ require 'webrick'
3
+
4
+ ##
5
+ # Launch::WEBrickHTTPServer adds launchd support to WEBrick.
6
+ #
7
+ # To use, replace WEBrick::HTTPServer with Launch::WEBrickHTTPServer.
8
+ #
9
+ # By default Launch::WEBrickHTTPServer expects to find the socket list under
10
+ # <tt>'WEBrickSockets'</tt> but this may be overridden through the
11
+ # +:LaunchdSockets+ option.
12
+ #
13
+ # The server will automatically shut down when a TERM signal is sent. If you
14
+ # wish to perform other shutdown actions override TERM but be sure to shut
15
+ # down webrick.
16
+ #
17
+ # An example WEBrick server using Launch::WEBrickHTTPServer would be:
18
+ #
19
+ # require 'launch/webrick'
20
+ #
21
+ # Launch::WEBrickHTTPServer.new(:DocumentRoot => ARGV.shift).start
22
+ #
23
+ # Here is an example plist for this server which listens on port 8000:
24
+ #
25
+ # <?xml version="1.0" encoding="UTF-8"?>
26
+ # <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
27
+ # <plist version="1.0">
28
+ # <dict>
29
+ # <key>Label</key>
30
+ # <string>net.segment7.launch.webrick</string>
31
+ # <key>ProgramArguments</key>
32
+ # <array>
33
+ # <string>/path/to/ruby</string>
34
+ # <string>/path/to/webrick</string>
35
+ # <string>/Users/your_user/Sites</string>
36
+ # </array>
37
+ # <key>ServiceIPC</key>
38
+ # <true/>
39
+ # <key>Sockets</key>
40
+ # <dict>
41
+ # <key>WEBrickSockets</key>
42
+ # <dict>
43
+ # <key>SockServiceName</key>
44
+ # <string>8000</string>
45
+ # </dict>
46
+ # </dict>
47
+ # </dict>
48
+ # </plist>
49
+
50
+ class Launch::WEBrickHTTPServer < WEBrick::HTTPServer
51
+
52
+ include Launch
53
+
54
+ ##
55
+ # Initializes an HTTP server with +options+ and set the server's listeners
56
+ # using Launch. A TERM handler to shut down the server is automatically
57
+ # set.
58
+ #
59
+ # +:LaunchdSockets+ may be set to change the socket key from the default of
60
+ # <tt>'WEBrickSockets'</tt>
61
+
62
+ def initialize options = {}
63
+ options[:DoNotListen] = true
64
+ sockets_key = options.delete(:LaunchdSockets) || 'WEBrickSockets'
65
+
66
+ super
67
+
68
+ launch_checkin
69
+
70
+ servers = launch_sockets sockets_key, TCPServer
71
+
72
+ listeners.replace servers
73
+
74
+ trap 'TERM' do shutdown end
75
+ end
76
+
77
+ end
78
+
data/sample/echo.rb ADDED
@@ -0,0 +1,107 @@
1
+ require 'rubygems'
2
+ require 'launch'
3
+
4
+ ##
5
+ # This is an echo server that runs using launchd on port 12345.
6
+ #
7
+ # To start, run:
8
+ #
9
+ # ruby echo.rb net.segment7.launch.echo.plist
10
+ # launchctl load net.segment7.launch.echo.plist
11
+ #
12
+ # To use the echo server run:
13
+ #
14
+ # telnet localhost 12345
15
+ #
16
+ # To quit the echo server type ^] followed by ^D
17
+ #
18
+ # To stop run:
19
+ #
20
+ # launchctl unload net.segment7.launch.echo.plist
21
+
22
+ class Echo
23
+
24
+ include Launch
25
+
26
+ def self.plist name
27
+ file = File.expand_path __FILE__
28
+ root = File.expand_path '../..', __FILE__
29
+
30
+ plist = <<-PLIST
31
+ <?xml version="1.0" encoding="UTF-8"?>
32
+ <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33
+ <plist version="1.0">
34
+ <dict>
35
+ <key>Label</key>
36
+ <string>#{name}</string>
37
+ <key>ProgramArguments</key>
38
+ <array>
39
+ <string>#{Gem.ruby}</string>
40
+ <string>-I#{root}/lib</string>
41
+ <string>-I#{root}/ext</string>
42
+ <string>#{file}</string>
43
+ </array>
44
+ <key>ServiceIPC</key>
45
+ <true/>
46
+ <key>Sockets</key>
47
+ <dict>
48
+ <key>EchoSocket</key>
49
+ <dict>
50
+ <key>SockServiceName</key>
51
+ <string>12345</string>
52
+ </dict>
53
+ </dict>
54
+ </dict>
55
+ </plist>
56
+ PLIST
57
+
58
+ open name, 'w' do |io|
59
+ io.write plist
60
+ end
61
+ end
62
+
63
+ def initialize
64
+ launch_checkin
65
+ end
66
+
67
+ ##
68
+ # echo lines sent from +socket+
69
+
70
+ def echo socket
71
+ Thread.start do
72
+ loop do
73
+ socket.puts socket.gets
74
+ end
75
+ end
76
+ end
77
+
78
+ ##
79
+ # Listens on +server+ for connections to echo on.
80
+
81
+ def listen server
82
+ Thread.start do
83
+ loop do
84
+ echo server.accept
85
+ end
86
+ end
87
+ end
88
+
89
+ ##
90
+ # Starts listening on the sockets given by launchd and waits forever
91
+
92
+ def run
93
+ launch_sockets('EchoSocket', TCPServer).each do |server|
94
+ listen server
95
+ end
96
+
97
+ sleep
98
+ end
99
+
100
+ end
101
+
102
+ if ARGV.empty? then
103
+ Echo.new.run
104
+ else
105
+ Echo.plist ARGV.first
106
+ end
107
+
@@ -0,0 +1,55 @@
1
+ require 'minitest/autorun'
2
+ require 'launch'
3
+
4
+ class TestLaunch < MiniTest::Unit::TestCase
5
+
6
+ include Launch
7
+
8
+ def launch_message message
9
+ @message = message
10
+
11
+ return { 'response' => 'hash' }
12
+ end
13
+
14
+ def test_launch_checkin
15
+ response = launch_checkin
16
+
17
+ assert_equal Launch::Key::CHECKIN, @message
18
+
19
+ expected = { 'response' => 'hash' }
20
+
21
+ assert_equal expected, response
22
+ assert_equal expected, @launch_checkin
23
+ end
24
+
25
+ def test_launch_sockets
26
+ @launch_checkin = {
27
+ Launch::JobKey::SOCKETS => {
28
+ 'MySockets' => [STDIN.to_i, STDOUT.to_i]
29
+ }
30
+ }
31
+
32
+ sockets = launch_sockets 'MySockets', IO
33
+
34
+ assert_equal 2, sockets.length
35
+
36
+ assert_instance_of IO, sockets.first
37
+ assert_instance_of IO, sockets.last
38
+
39
+ assert_equal [0, 1], sockets.map { |io| io.to_i }
40
+ end
41
+
42
+ def test_launch_sockets_none
43
+ @launch_checkin = {
44
+ Launch::JobKey::SOCKETS => {
45
+ }
46
+ }
47
+
48
+ e = assert_raises Launch::Error do
49
+ launch_sockets 'NoSockets', IO
50
+ end
51
+
52
+ assert_equal 'no sockets found for "NoSockets"', e.message
53
+ end
54
+
55
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: launch
3
+ version: !ruby/object:Gem::Version
4
+ hash: 15
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ version: "1.0"
10
+ platform: ruby
11
+ authors:
12
+ - Eric Hodel
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain:
16
+ - |
17
+ -----BEGIN CERTIFICATE-----
18
+ MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRAwDgYDVQQDDAdkcmJy
19
+ YWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZFgNu
20
+ ZXQwHhcNMDcxMjIxMDIwNDE0WhcNMDgxMjIwMDIwNDE0WjBBMRAwDgYDVQQDDAdk
21
+ cmJyYWluMRgwFgYKCZImiZPyLGQBGRYIc2VnbWVudDcxEzARBgoJkiaJk/IsZAEZ
22
+ FgNuZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbbgLrGLGIDE76
23
+ LV/cvxdEzCuYuS3oG9PrSZnuDweySUfdp/so0cDq+j8bqy6OzZSw07gdjwFMSd6J
24
+ U5ddZCVywn5nnAQ+Ui7jMW54CYt5/H6f2US6U0hQOjJR6cpfiymgxGdfyTiVcvTm
25
+ Gj/okWrQl0NjYOYBpDi+9PPmaH2RmLJu0dB/NylsDnW5j6yN1BEI8MfJRR+HRKZY
26
+ mUtgzBwF1V4KIZQ8EuL6I/nHVu07i6IkrpAgxpXUfdJQJi0oZAqXurAV3yTxkFwd
27
+ g62YrrW26mDe+pZBzR6bpLE+PmXCzz7UxUq3AE0gPHbiMXie3EFE0oxnsU3lIduh
28
+ sCANiQ8BAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
29
+ BBS5k4Z75VSpdM0AclG2UvzFA/VW5DANBgkqhkiG9w0BAQUFAAOCAQEAHagT4lfX
30
+ kP/hDaiwGct7XPuVGbrOsKRVD59FF5kETBxEc9UQ1clKWngf8JoVuEoKD774dW19
31
+ bU0GOVWO+J6FMmT/Cp7nuFJ79egMf/gy4gfUfQMuvfcr6DvZUPIs9P/TlK59iMYF
32
+ DIOQ3DxdF3rMzztNUCizN4taVscEsjCcgW6WkUJnGdqlu3OHWpQxZBJkBTjPCoc6
33
+ UW6on70SFPmAy/5Cq0OJNGEWBfgD9q7rrs/X8GGwUWqXb85RXnUVi/P8Up75E0ag
34
+ 14jEc90kN+C7oI/AGCBN0j6JnEtYIEJZibjjDJTSMWlUKKkj30kq7hlUC2CepJ4v
35
+ x52qPcexcYZR7w==
36
+ -----END CERTIFICATE-----
37
+
38
+ date: 2011-02-27 00:00:00 -08:00
39
+ default_executable:
40
+ dependencies:
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ prerelease: false
44
+ requirement: &id001 !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ hash: 11
50
+ segments:
51
+ - 2
52
+ - 0
53
+ - 2
54
+ version: 2.0.2
55
+ type: :development
56
+ version_requirements: *id001
57
+ - !ruby/object:Gem::Dependency
58
+ name: rake-compiler
59
+ prerelease: false
60
+ requirement: &id002 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ hash: 5
66
+ segments:
67
+ - 0
68
+ - 7
69
+ version: "0.7"
70
+ type: :development
71
+ version_requirements: *id002
72
+ - !ruby/object:Gem::Dependency
73
+ name: hoe
74
+ prerelease: false
75
+ requirement: &id003 !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ hash: 43
81
+ segments:
82
+ - 2
83
+ - 9
84
+ - 0
85
+ version: 2.9.0
86
+ type: :development
87
+ version_requirements: *id003
88
+ description: |-
89
+ Launch allows agents and daemons launched by launchd to retrieve their list of
90
+ sockets. Launchd is an open source framework for launching and managing
91
+ daemons, programs and scripts provided by Apple.
92
+ email:
93
+ - drbrain@segment7.net
94
+ executables: []
95
+
96
+ extensions:
97
+ - ext/launch/extconf.rb
98
+ extra_rdoc_files:
99
+ - History.txt
100
+ - Manifest.txt
101
+ - README.txt
102
+ files:
103
+ - .autotest
104
+ - History.txt
105
+ - Manifest.txt
106
+ - README.txt
107
+ - Rakefile
108
+ - ext/launch/extconf.rb
109
+ - ext/launch/launch.c
110
+ - lib/launch.rb
111
+ - lib/launch/webrick.rb
112
+ - sample/echo.rb
113
+ - test/test_launch.rb
114
+ - .gemtest
115
+ has_rdoc: true
116
+ homepage: https://github.com/drbrain/launch
117
+ licenses: []
118
+
119
+ post_install_message:
120
+ rdoc_options:
121
+ - --main
122
+ - README.txt
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ hash: 55
131
+ segments:
132
+ - 1
133
+ - 9
134
+ - 2
135
+ version: 1.9.2
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ hash: 3
142
+ segments:
143
+ - 0
144
+ version: "0"
145
+ requirements: []
146
+
147
+ rubyforge_project: launch
148
+ rubygems_version: 1.5.3
149
+ signing_key:
150
+ specification_version: 3
151
+ summary: Launch allows agents and daemons launched by launchd to retrieve their list of sockets
152
+ test_files:
153
+ - test/test_launch.rb
metadata.gz.sig ADDED
@@ -0,0 +1,2 @@
1
+ }��K������g��1�OM��u+5��U#_�&���a�d�OO�f�A<yM��S��#�DE��~� �~&�wN$�H��[Ǽ�j?��E���5�s��ݍ�Ը3�q�+�����&��B"�j�������-{`��5�!���3�&~u��(���G�_8-����Yn��lF�>L�?';��*��
2
+ �,F� ��:#@~�E�<�"�m8�a�b����q �vP�b/����v:�ZF��^E]��v�"#