rubyosa 0.2.0 → 0.3.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.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2006, Apple Computer, Inc. All rights reserved.
2
+ * Copyright (c) 2006-2007, Apple Inc. All rights reserved.
3
3
  *
4
4
  * Redistribution and use in source and binary forms, with or without
5
5
  * modification, are permitted provided that the following conditions
@@ -9,7 +9,7 @@
9
9
  * 2. Redistributions in binary form must reproduce the above copyright
10
10
  * notice, this list of conditions and the following disclaimer in the
11
11
  * documentation and/or other materials provided with the distribution.
12
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
12
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
13
13
  * its contributors may be used to endorse or promote products derived
14
14
  * from this software without specific prior written permission.
15
15
  *
@@ -34,13 +34,17 @@
34
34
  #include <sys/param.h>
35
35
 
36
36
  /* rbosa_sdef.c */
37
- VALUE rbosa_scripting_info (VALUE self, VALUE criterion, VALUE value);
37
+ VALUE rbosa_scripting_info (VALUE self, VALUE hash);
38
+ VALUE rbosa_remote_processes (VALUE self, VALUE machine);
38
39
 
39
40
  /* rbosa_conv.c */
40
41
  FourCharCode rbobj_to_fourchar (VALUE obj);
41
42
  VALUE rbosa_four_char_code (VALUE self, VALUE val);
42
43
  void rbobj_to_alias_handle (VALUE obj, AliasHandle *alias);
43
44
 
45
+ /* rbosa_err.c */
46
+ const char *error_code_to_string (const int code);
47
+
44
48
  /* helper macros */
45
49
  #define RVAL2CSTR(x) (StringValueCStr (x))
46
50
  #define CSTR2RVAL(x) (rb_str_new2 (x))
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2006, Apple Computer, Inc. All rights reserved.
2
+ * Copyright (c) 2006-2007, Apple Inc. All rights reserved.
3
3
  *
4
4
  * Redistribution and use in source and binary forms, with or without
5
5
  * modification, are permitted provided that the following conditions
@@ -9,7 +9,7 @@
9
9
  * 2. Redistributions in binary form must reproduce the above copyright
10
10
  * notice, this list of conditions and the following disclaimer in the
11
11
  * documentation and/or other materials provided with the distribution.
12
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
12
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
13
13
  * its contributors may be used to endorse or promote products derived
14
14
  * from this software without specific prior written permission.
15
15
  *
@@ -0,0 +1,105 @@
1
+ /*
2
+ * Copyright (c) 2006-2007, Apple Inc. All rights reserved.
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without
5
+ * modification, are permitted provided that the following conditions
6
+ * are met:
7
+ * 1. Redistributions of source code must retain the above copyright
8
+ * notice, this list of conditions and the following disclaimer.
9
+ * 2. Redistributions in binary form must reproduce the above copyright
10
+ * notice, this list of conditions and the following disclaimer in the
11
+ * documentation and/or other materials provided with the distribution.
12
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
13
+ * its contributors may be used to endorse or promote products derived
14
+ * from this software without specific prior written permission.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
17
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
20
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ * POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ #include <CoreServices/CoreServices.h>
30
+
31
+ const char *
32
+ error_code_to_string (const int code)
33
+ {
34
+ switch (code) {
35
+ case noPortErr: return "Client hasn't set 'SIZE' resource to indicate awareness of high-level events";
36
+ case destPortErr: return "Server hasn't set 'SIZE' resource to indicate awareness of high-level events, or else is not present";
37
+ case sessClosedErr: return "The kAEDontReconnect flag in the sendMode parameter was set and the server quit, then restarted";
38
+ case errAECoercionFail: return "Data could not be coerced to the requested descriptor type";
39
+ case errAEDescNotFound: return "Descriptor was not found";
40
+ case errAECorruptData: return "Data in an Apple event could not be read";
41
+ case errAEWrongDataType: return "Wrong descriptor type";
42
+ case errAENotAEDesc: return "Not a valid descriptor";
43
+ case errAEBadListItem: return "Operation involving a list item failed";
44
+ case errAENewerVersion: return "Need a newer version of the Apple Event Manager";
45
+ case errAENotAppleEvent: return "The event is not in AppleEvent format.";
46
+ case errAEEventNotHandled: return "Event wasn't handled by an Apple event handler";
47
+ case errAEReplyNotValid: return "AEResetTimer was passed an invalid repl";
48
+ case errAEUnknownSendMode: return "Invalid sending mode was passed";
49
+ case errAEWaitCanceled: return "User canceled out of wait loop for reply or receipt";
50
+ case errAETimeout: return "Apple event timed out";
51
+ case errAENoUserInteraction: return "No user interaction allowed";
52
+ case errAENotASpecialFunction: return "Wrong keyword for a special function";
53
+ case errAEParamMissed: return "A required parameter was not accessed.";
54
+ case errAEUnknownAddressType: return "Unknown Apple event address type";
55
+ case errAEHandlerNotFound: return "No handler found for an Apple event";
56
+ case errAEReplyNotArrived: return "Reply has not yet arrived";
57
+ case errAEIllegalIndex: return "Not a valid list index";
58
+ case errAEImpossibleRange: return "The range is not valid because it is impossible for a range to include the first and last objects that were specified; an example is a range in which the offset of the first object is greater than the offset of the last object";
59
+ case errAEWrongNumberArgs: return "The number of operands provided for the kAENOT logical operator is not 1";
60
+ case errAEAccessorNotFound: return "There is no object accessor function for the specified object class and container type";
61
+ case errAENoSuchLogical: return "The logical operator in a logical descriptor is not kAEAND, kAEOR, or kAENOT";
62
+ case errAEBadTestKey: return "The descriptor in a test key is neither a comparison descriptor nor a logical descriptor";
63
+ case errAENotAnObjSpec: return "The objSpecifier parameter of AEResolve is not an object specifier";
64
+ case errAENoSuchObject: return "Runtime resolution of an object failed.";
65
+ case errAENegativeCount: return "An object-counting function returned a negative result";
66
+ case errAEEmptyListContainer: return "The container for an Apple event object is specified by an empty list";
67
+ case errAEUnknownObjectType: return "The object type isn't recognized";
68
+ case errAERecordingIsAlreadyOn: return "Recording is already on";
69
+ case errAEReceiveTerminate: return "Break out of all levels of AEReceive to the topmost (1.1 or greater)";
70
+ case errAEReceiveEscapeCurrent: return "Break out of lowest level only of AEReceive (1.1 or greater)";
71
+ case errAEEventFiltered: return "Event has been filtered and should not be propagated (1.1 or greater)";
72
+ case errAEDuplicateHandler: return "Attempt to install handler in table for identical class and ID (1.1 or greater)";
73
+ case errAEStreamBadNesting: return "Nesting violation while streaming";
74
+ case errAEStreamAlreadyConverted: return "Attempt to convert a stream that has already been converted";
75
+ case errAEDescIsNull: return "Attempt to perform an invalid operation on a null descriptor";
76
+ case errAEBuildSyntaxError: return "AEBuildDesc and related functions detected a syntax error";
77
+ case errAEBufferTooSmall: return "Buffer for AEFlattenDesc too small";
78
+ case errASCantConsiderAndIgnore: return "Can't both consider and ignore <attribute>.";
79
+ case errASCantCompareMoreThan32k: return "Can't perform operation on text longer than 32K bytes.";
80
+ case errASTerminologyNestingTooDeep: return "Tell statements are nested too deeply.";
81
+ case errASIllegalFormalParameter: return "<name> is illegal as a formal parameter.";
82
+ case errASParameterNotForEvent: return "<name> is not a parameter name for the event <event>.";
83
+ case errASNoResultReturned: return "No result was returned for some argument of this expression.";
84
+ case errAEEventFailed: return "Apple event handler failed.";
85
+ case errAETypeError: return "A descriptor type mismatch occurred.";
86
+ case errAEBadKeyForm: return "Invalid key form.";
87
+ case errAENotModifiable: return "Can't set <object or data> to <object or data>. Access not allowed.";
88
+ case errAEPrivilegeError: return "A privilege violation occurred.";
89
+ case errAEReadDenied: return "The read operation was not allowed.";
90
+ case errAEWriteDenied: return "Can't set <object or data> to <object or data>.";
91
+ case errAEIndexTooLarge: return "The index of the event is too large to be valid.";
92
+ case errAENotAnElement: return "The specified object is a property, not an element.";
93
+ case errAECantSupplyType: return "Can't supply the requested descriptor type for the data.";
94
+ case errAECantHandleClass: return "The Apple event handler can't handle objects of this class.";
95
+ case errAEInTransaction: return "Couldn't handle this command because it wasn't part of the current transaction.";
96
+ case errAENoSuchTransaction: return "The transaction to which this command belonged isn't a valid transaction.";
97
+ case errAENoUserSelection: return "There is no user selection.";
98
+ case errAENotASingleObject: return "Handler only handles single objects.";
99
+ case errAECantUndo: return "Can't undo the previous Apple event or user action.";
100
+ case errAENotAnEnumMember: return "Enumerated value in SetData is not allowed for this property";
101
+ case errAECantPutThatThere: return "In make new, duplicate, etc. class can't be an element of container";
102
+ case errAEPropertiesClash: return "Illegal combination of properties settings for SetData, make new, or duplicate";
103
+ }
104
+ return GetMacOSStatusErrorString (code);
105
+ }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2006, Apple Computer, Inc. All rights reserved.
2
+ * Copyright (c) 2006-2007, Apple Inc. All rights reserved.
3
3
  *
4
4
  * Redistribution and use in source and binary forms, with or without
5
5
  * modification, are permitted provided that the following conditions
@@ -9,7 +9,7 @@
9
9
  * 2. Redistributions in binary form must reproduce the above copyright
10
10
  * notice, this list of conditions and the following disclaimer in the
11
11
  * documentation and/or other materials provided with the distribution.
12
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
12
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
13
13
  * its contributors may be used to endorse or promote products derived
14
14
  * from this software without specific prior written permission.
15
15
  *
@@ -29,6 +29,7 @@
29
29
  #include <ApplicationServices/ApplicationServices.h>
30
30
  #include <CoreFoundation/CoreFoundation.h>
31
31
  #include <unistd.h>
32
+ #include <st.h>
32
33
  #include "rbosa.h"
33
34
 
34
35
  static void
@@ -67,7 +68,7 @@ rbosa_translate_app (VALUE criterion, VALUE value, VALUE *app_signature, VALUE *
67
68
  *app_signature = Qnil;
68
69
  err = noErr;
69
70
 
70
- if (criterion == ID2SYM (rb_intern ("by_signature"))) {
71
+ if (criterion == ID2SYM (rb_intern ("signature"))) {
71
72
  err = LSFindApplicationForInfo (RVAL2FOURCHAR (value), NULL, NULL, fs_ref, &URL);
72
73
  *app_signature = value; /* Don't need to get the app signature, we already have it. */
73
74
  }
@@ -77,13 +78,13 @@ rbosa_translate_app (VALUE criterion, VALUE value, VALUE *app_signature, VALUE *
77
78
  str = CFStringCreateMutable (kCFAllocatorDefault, 0);
78
79
  CFStringAppendCString (str, RVAL2CSTR (value), kCFStringEncodingUTF8);
79
80
 
80
- if (criterion == ID2SYM (rb_intern ("by_path"))) {
81
+ if (criterion == ID2SYM (rb_intern ("path"))) {
81
82
  err = FSPathMakeRef ((const UInt8 *)RVAL2CSTR (value), fs_ref, NULL);
82
83
  if (err == noErr) {
83
84
  URL = CFURLCreateWithFileSystemPath (kCFAllocatorDefault, str, kCFURLPOSIXPathStyle, FALSE);
84
85
  }
85
86
  }
86
- else if (criterion == ID2SYM (rb_intern ("by_name"))) {
87
+ else if (criterion == ID2SYM (rb_intern ("name"))) {
87
88
  CFStringRef dot_app;
88
89
 
89
90
  dot_app = CFSTR (".app");
@@ -93,7 +94,7 @@ rbosa_translate_app (VALUE criterion, VALUE value, VALUE *app_signature, VALUE *
93
94
  err = LSFindApplicationForInfo (kLSUnknownCreator, NULL, str, fs_ref, &URL);
94
95
  *app_name = value; /* Don't need to get the app name, we already have it. */
95
96
  }
96
- else if (criterion == ID2SYM (rb_intern ("by_bundle_id"))) {
97
+ else if (criterion == ID2SYM (rb_intern ("bundle_id"))) {
97
98
  err = LSFindApplicationForInfo (kLSUnknownCreator, str, NULL, fs_ref, &URL);
98
99
  }
99
100
  else {
@@ -106,7 +107,7 @@ rbosa_translate_app (VALUE criterion, VALUE value, VALUE *app_signature, VALUE *
106
107
  }
107
108
 
108
109
  if (err != noErr) {
109
- *error = "Error when translating the application";
110
+ *error = "Can't locate the target bundle on the file system";
110
111
  return FALSE;
111
112
  }
112
113
 
@@ -115,36 +116,326 @@ rbosa_translate_app (VALUE criterion, VALUE value, VALUE *app_signature, VALUE *
115
116
  CFRelease (URL);
116
117
 
117
118
  if (NIL_P (*app_signature)) {
118
- *error = "Error when getting the application signature";
119
+ *error = "Can't get the target bundle signature";
119
120
  return FALSE;
120
121
  }
121
122
 
122
123
  return TRUE;
123
124
  }
124
125
 
126
+ static inline VALUE
127
+ __get_criterion (VALUE hash, const char *str, VALUE *psym)
128
+ {
129
+ VALUE sym;
130
+ VALUE val;
131
+
132
+ sym = ID2SYM (rb_intern (str));
133
+ val = rb_hash_delete (hash, sym);
134
+
135
+ if (!NIL_P (val)) {
136
+ if (TYPE (val) != T_STRING)
137
+ rb_raise (rb_eArgError, "argument '%s' must have a String value", RVAL2CSTR (sym));
138
+ if (psym != NULL)
139
+ *psym = sym;
140
+ }
141
+
142
+ return val;
143
+ }
144
+
145
+ static OSStatus
146
+ send_simple_remote_event (AEEventClass ec, AEEventID ei, const char *target_url, const AEDesc *dp, AppleEvent *reply)
147
+ {
148
+ OSStatus err;
149
+ AEDesc target, ev, root_reply;
150
+
151
+ if ((err = AECreateDesc ('aprl', target_url, strlen(target_url), &target)) != noErr)
152
+ return err;
153
+
154
+ if ((err = AECreateAppleEvent (ec, ei, &target, kAutoGenerateReturnID, kAnyTransactionID, &ev)) != noErr) {
155
+ AEDisposeDesc (&target);
156
+ return err;
157
+ }
158
+
159
+ if (dp != NULL)
160
+ AEPutParamDesc (&ev, keyDirectObject, dp);
161
+
162
+ err = AESend (&ev, &root_reply, kAEWaitReply, kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
163
+ if (err == noErr)
164
+ err = AEGetParamDesc (&root_reply, keyDirectObject, typeWildCard, reply);
165
+
166
+ // XXX we should check for application-level errors
167
+
168
+ AEDisposeDesc (&target);
169
+ AEDisposeDesc (&ev);
170
+ AEDisposeDesc (&root_reply);
171
+
172
+ return err;
173
+ }
174
+
175
+ #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
176
+ typedef SInt16 ResFileRefNum;
177
+ #endif
178
+
179
+ static VALUE
180
+ get_remote_app_sdef (const char *target_url)
181
+ {
182
+ AEDesc zero, reply, aete;
183
+ Size datasize;
184
+ void * data;
185
+ int fd;
186
+ FSRef fs;
187
+ CFDataRef sdef_data;
188
+ VALUE sdef;
189
+ ResFileRefNum res_num;
190
+ Handle res;
191
+ SInt32 z = 0;
192
+ OSErr osa_error;
193
+ HFSUniStr255 resourceForkName;
194
+ char tmp_res_path[] = "/tmp/FakeXXXXXX.osax";
195
+
196
+ #define BOOM(m) \
197
+ do { \
198
+ rb_raise (rb_eRuntimeError, \
199
+ "Can't get scripting definition of remote application (%s) : %s (%d)", \
200
+ m, error_code_to_string (osa_error), osa_error); \
201
+ } while (0)
202
+
203
+ // XXX we should try to get the sdef via ascr/gsdf before trying to convert the AETE!
204
+
205
+ AECreateDesc (typeSInt32, &z, sizeof (z), &zero);
206
+ osa_error = send_simple_remote_event ('ascr', 'gdte', target_url, &zero, &reply);
207
+ AEDisposeDesc (&zero);
208
+ if (osa_error != noErr)
209
+ BOOM ("sending event");
210
+
211
+ osa_error = AECoerceDesc (&reply, kAETerminologyExtension, &aete);
212
+ AEDisposeDesc (&reply);
213
+ if (osa_error != noErr)
214
+ BOOM ("coercing result");
215
+
216
+ datasize = AEGetDescDataSize (&aete);
217
+ data = (void *)malloc (datasize);
218
+ if (data == NULL)
219
+ BOOM ("cannot allocate memory");
220
+
221
+ osa_error = AEGetDescData (&aete, data, datasize);
222
+ AEDisposeDesc (&aete);
223
+ if (osa_error != noErr) {
224
+ free (data);
225
+ BOOM ("get data");
226
+ }
227
+
228
+ if (mkstemps (tmp_res_path, 5) == -1) {
229
+ free (data);
230
+ BOOM ("generate resource file name");
231
+ }
232
+
233
+ fd = open (tmp_res_path, O_CREAT|O_TRUNC|O_WRONLY, 0644);
234
+ if (fd == -1) {
235
+ free (data);
236
+ BOOM ("creating resource file");
237
+ }
238
+ close (fd);
239
+
240
+ FSPathMakeRef ((const UInt8 *)tmp_res_path, &fs, NULL);
241
+ FSGetResourceForkName (&resourceForkName);
242
+
243
+ osa_error = FSCreateResourceFork (&fs, resourceForkName.length, resourceForkName.unicode, 0);
244
+ if (osa_error != noErr) {
245
+ free (data);
246
+ BOOM ("creating resource fork");
247
+ }
248
+
249
+ osa_error = FSOpenResourceFile (&fs, resourceForkName.length, resourceForkName.unicode, fsRdWrPerm, &res_num);
250
+ if (osa_error != noErr) {
251
+ free (data);
252
+ BOOM ("opening resource fork");
253
+ }
254
+
255
+ res = NewHandle (datasize);
256
+ memcpy (*res, data, datasize);
257
+ AddResource (res, 'aete', 0, (ConstStr255Param)"");
258
+
259
+ free (data);
260
+ CloseResFile (res_num);
261
+
262
+ osa_error = OSACopyScriptingDefinition (&fs, kOSAModeNull, &sdef_data);
263
+ unlink (tmp_res_path);
264
+ if (osa_error != noErr)
265
+ rb_raise (rb_eRuntimeError, "Cannot get scripting definition : error %d", osa_error);
266
+
267
+ sdef = rb_str_new ((const char *)CFDataGetBytePtr (sdef_data),
268
+ CFDataGetLength (sdef_data));
269
+
270
+ CFRelease (sdef_data);
271
+
272
+ return sdef;
273
+ }
274
+
125
275
  VALUE
126
- rbosa_scripting_info (VALUE self, VALUE criterion, VALUE value)
276
+ rbosa_scripting_info (VALUE self, VALUE hash)
127
277
  {
128
278
  const char * error;
279
+ VALUE criterion;
280
+ VALUE value;
281
+ VALUE remote;
282
+ char c_remote[128];
129
283
  VALUE ary;
130
284
  VALUE name;
131
285
  VALUE signature;
132
- FSRef fs;
286
+ VALUE sdef;
133
287
  OSAError osa_error;
134
- CFDataRef sdef_data;
135
288
 
136
- if (!rbosa_translate_app (criterion, value, &signature, &name, &fs, &error))
137
- rb_raise (rb_eRuntimeError, error);
289
+ Check_Type (hash, T_HASH);
290
+
291
+ criterion = name = signature = Qnil;
292
+ value = __get_criterion (hash, "name", &criterion);
293
+ if (NIL_P (value))
294
+ value = __get_criterion (hash, "path", &criterion);
295
+ if (NIL_P (value))
296
+ value = __get_criterion (hash, "bundle_id", &criterion);
297
+ if (NIL_P (value))
298
+ value = __get_criterion (hash, "signature", &criterion);
299
+ if (NIL_P (value))
300
+ rb_raise (rb_eArgError, "expected :name, :path, :bundle_id or :signature key/value");
301
+
302
+ remote = __get_criterion (hash, "machine", NULL);
303
+ if (!NIL_P (remote)) {
304
+ VALUE username;
305
+ VALUE password;
306
+
307
+ if (NIL_P (value) || criterion != ID2SYM (rb_intern ("name")))
308
+ rb_raise (rb_eArgError, ":machine argument requires :name");
309
+ name = value;
138
310
 
139
- osa_error = OSACopyScriptingDefinition (&fs, kOSAModeNull, &sdef_data);
140
- if (osa_error != noErr)
141
- rb_raise (rb_eRuntimeError, "Cannot get scripting definition : error %d", osa_error);
311
+ username = __get_criterion (hash, "username", NULL);
312
+ password = __get_criterion (hash, "password", NULL);
142
313
 
143
- ary = rb_ary_new3 (3, name, signature,
144
- rb_str_new ((const char *)CFDataGetBytePtr (sdef_data),
145
- CFDataGetLength (sdef_data)));
314
+ if (NIL_P (username)) {
315
+ if (!NIL_P (password))
316
+ rb_raise (rb_eArgError, ":password argument requires :username");
317
+ snprintf (c_remote, sizeof c_remote, "eppc://%s/%s",
318
+ RVAL2CSTR (remote), RVAL2CSTR (value));
319
+ }
320
+ else {
321
+ if (NIL_P (password))
322
+ snprintf (c_remote, sizeof c_remote, "eppc://%s@%s/%s",
323
+ RVAL2CSTR (username), RVAL2CSTR (remote),
324
+ RVAL2CSTR (value));
325
+ else
326
+ snprintf (c_remote, sizeof c_remote, "eppc://%s:%s@%s/%s",
327
+ RVAL2CSTR (username), RVAL2CSTR (password),
328
+ RVAL2CSTR (remote), RVAL2CSTR (value));
329
+ }
146
330
 
147
- CFRelease (sdef_data);
331
+ remote = CSTR2RVAL (c_remote);
332
+ }
333
+
334
+ if (RHASH (hash)->tbl->num_entries > 0) {
335
+ VALUE keys;
336
+
337
+ keys = rb_funcall (hash, rb_intern ("keys"), 0);
338
+ rb_raise (rb_eArgError, "inappropriate argument(s): %s",
339
+ RSTRING (rb_inspect (keys))->ptr);
340
+ }
341
+
342
+ if (NIL_P (remote)) {
343
+ FSRef fs;
344
+ CFDataRef sdef_data;
345
+
346
+ if (!rbosa_translate_app (criterion, value, &signature, &name, &fs, &error))
347
+ rb_raise (rb_eRuntimeError, error);
348
+
349
+ osa_error = OSACopyScriptingDefinition (&fs, kOSAModeNull, &sdef_data);
350
+ if (osa_error != noErr)
351
+ rb_raise (rb_eRuntimeError, "Cannot get scripting definition : error %d", osa_error);
352
+
353
+ sdef = rb_str_new ((const char *)CFDataGetBytePtr (sdef_data),
354
+ CFDataGetLength (sdef_data));
355
+
356
+ CFRelease (sdef_data);
357
+ }
358
+ else {
359
+ sdef = get_remote_app_sdef (c_remote);
360
+ }
361
+
362
+ ary = rb_ary_new3 (3, name, NIL_P (remote) ? signature : remote, sdef);
148
363
 
149
364
  return ary;
150
365
  }
366
+
367
+ VALUE
368
+ rbosa_remote_processes (VALUE self, VALUE machine)
369
+ {
370
+ char buf[128];
371
+ CFStringRef str;
372
+ CFURLRef url;
373
+ AERemoteProcessResolverRef resolver;
374
+ CFArrayRef cfary;
375
+ CFStreamError cferr;
376
+ VALUE ary;
377
+ unsigned i, count;
378
+
379
+ snprintf (buf, sizeof buf, "eppc://%s", RVAL2CSTR (machine));
380
+ str = CFStringCreateWithCString (kCFAllocatorDefault, buf, kCFStringEncodingUTF8);
381
+ url = CFURLCreateWithString (kCFAllocatorDefault, str, NULL);
382
+ CFRelease (str);
383
+ resolver = AECreateRemoteProcessResolver (kCFAllocatorDefault, url);
384
+ CFRelease (url);
385
+
386
+ cfary = AERemoteProcessResolverGetProcesses (resolver, &cferr);
387
+ if (cfary == NULL) {
388
+ AEDisposeRemoteProcessResolver (resolver);
389
+ rb_raise (rb_eRuntimeError, "Can't resolve the remote processes on machine '%s' : error %d (domain %d)",
390
+ RVAL2CSTR (machine), cferr.error, cferr.domain);
391
+ }
392
+
393
+ ary = rb_ary_new ();
394
+ for (i = 0, count = CFArrayGetCount (cfary); i < count; i++) {
395
+ CFDictionaryRef dict;
396
+ VALUE hash;
397
+ CFNumberRef number;
398
+
399
+ dict = (CFDictionaryRef)CFArrayGetValueAtIndex (cfary, i);
400
+ hash = rb_hash_new ();
401
+
402
+ url = CFDictionaryGetValue (dict, kAERemoteProcessURLKey);
403
+ if (url == NULL)
404
+ continue;
405
+
406
+ url = CFURLCopyAbsoluteURL (url);
407
+ str = CFURLGetString (url);
408
+
409
+ rb_hash_aset (hash, ID2SYM (rb_intern ("url")), CSTR2RVAL (CFStringGetCStringPtr (str, CFStringGetFastestEncoding (str))));
410
+
411
+ CFRelease (url);
412
+
413
+ str = CFDictionaryGetValue (dict, kAERemoteProcessNameKey);
414
+ if (str == NULL)
415
+ continue;
416
+
417
+ rb_hash_aset (hash, ID2SYM (rb_intern ("name")), CSTR2RVAL (CFStringGetCStringPtr (str, CFStringGetFastestEncoding (str))));
418
+
419
+ number = CFDictionaryGetValue (dict, kAERemoteProcessUserIDKey);
420
+ if (number != NULL) {
421
+ int uid;
422
+
423
+ if (CFNumberGetValue (number, kCFNumberIntType, &uid))
424
+ rb_hash_aset (hash, ID2SYM (rb_intern ("uid")), INT2FIX (uid));
425
+ }
426
+
427
+ number = CFDictionaryGetValue (dict, kAERemoteProcessProcessIDKey);
428
+ if (number != NULL) {
429
+ int pid;
430
+
431
+ if (CFNumberGetValue (number, kCFNumberIntType, &pid))
432
+ rb_hash_aset (hash, ID2SYM (rb_intern ("pid")), INT2FIX (pid));
433
+ }
434
+
435
+ rb_ary_push (ary, hash);
436
+ }
437
+
438
+ AEDisposeRemoteProcessResolver (resolver);
439
+
440
+ return ary;
441
+ }