rubyosa 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }