Returning a pipe?

i’m writting a RubyCocoa application for synchronizing folders of a
computer to folders of an usb key.

to let the user not bored, because it could takes time, i have a log
window where i print the messages coming from rsync.

on another side, i need the call to rsync to have root privileges,
then i’m writing a tinu ruby module in C to get the root privileges
for rsync.

the way it is done, for the time being :

C side:
±----+

if ( myStatus != errAuthorizationSuccess ) break;
{
FILE *myCommunicationsPipe = NULL;
char myReadBuffer[ LINE_MAX ];

myFlags = kAuthorizationFlagDefaults;

myStatus = AuthorizationExecuteWithPrivileges( myAuthorizationRef,
myToolPath, myFlags,
myArguments,
&myCommunicationsPipe );
if ( bufferOut != NULL )
{
if ( myStatus == errAuthorizationSuccess )
{
int i = 0;
int len;
while ( fgets( myReadBuffer, LINE_MAX, myCommunicationsPipe ) )
{
bufferOut[ i ] = strdup( myReadBuffer );
len = strlen( bufferOut[ i ] );
bufferOut[ i ] += len - 1;
*bufferOut[ i ] = 0; // ~= chomp
bufferOut[ i ] -= len - 1;
i++;
}
bufferOut[ i ] = NULL;
}
}
}

C ext to Ruby side:
±----------------+

VALUE ary = rb_ary_new2( LINES_MAX );
i = 0;
while( bufferOut[ i ] != NULL)
{
rb_ary_push( ary, (VALUE) rb_str_new2( bufferOut[ i ] ) );
i++;
}

return ary;

obviously, it works but i’m not satisfied of the returned result
because the user gets an array of it’s whole at a time, where i would
prefer continously outputting the values (string in this case)

then i wonder if there is a way somehow to return the
“myCommunicationsPipe” above directly (more directly) from C to ruby.

something like IO.popen…

BUT, i’ve tried IO.popen in my RubyCocoa app it doesn’t work as
expected, i get the whole result at a time intead of having the
results in a line by nline basis…

some light about that ?

On Wed, Sep 05, 2007 at 02:35:10AM +0900, unbewusst wrote:

then i wonder if there is a way somehow to return the
“myCommunicationsPipe” above directly (more directly) from C to ruby.

something like IO.popen…

I see at least two options:

  • Use the macros in rubyio.h to wrap the FILE* that you already have.
    This is “cheating” the ruby API a bit, since you’d be accessing
    structures that I don’t think Matz intended for us to access
    directly.

  • Use IO#fdopen to re-open the pipe once it is opened.

Paul

On 4 sep, 23:57, Paul B. [email protected] wrote:

structures that I don't think Matz intended for us to access
directly.
  • Use IO#fdopen to re-open the pipe once it is opened.

Paul

Luc Heinriwh gave me yesterday a third solution perfectly working,
from C ext to Ruby side i return : INT2FIX( fileno(myPipe))

and on ruby side i can use it as a standard IO pipe…

that’s all very simple and efficient :wink: