launch 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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�"#