_DISTRIBUTED COMPUTING NOW: DEVELOPMENT ENVIRONMENTS_ by Lowell Schneider [LISTING ONE] typedef struct { binding, /* the binding property */ princ_name, /* the rpi's principal name */ secpac, /* the rpi's security package */ ns_auth, /* the rpi's privileges in the NSI */ struct { name, /* property name */ argc, /* number of values */ argv[16] /* array of values */ } prop[24], /* property list */ propc, /* number of properties */ } INQUIRE; auto INQUIRE inq[ 24 ]; auto cexp = "(('student' in TABLES) or ('enroll' in TABLES ))", i = 0; *inq[ 0 ] = servers( "", /* subnet - "" means local subnet */ "/.:/", /* context - in this case every host */ cexp, /* constraint expression */ 000, /* secpac - in this case none */ "" /* CDS group -- "" means default which is /.:/eos */ ); while( inq[ i ]->binding ) *inq[ ++i ] = servers(); [LISTING TWO] /* Implements a C wrapper around an executable we have no source for that turns it into a server. */ #include #define MAXBUF 65536 char stdinb[ MAXBUF ]; int prlen = 10; char prompt[] = "\nbroker=> "; char buf[ 3 ][] = { "set stock ", "set shares ", "execute\n" }; char *arg[ 3 ] = { NULL, NULL, NULL }; char nul[] = ""; main( argc, argv ) int argc; char *argv[]; { char *c, *d, tmp[ 255 ]; int i, pid, j; FILE *fp[ 2 ]; int fdin[ 2 ], fdout[ 2 ]; /* create output pipe to server body */ if ( pipe( fdout ) == -1 ) exit( 1 ); if (!( fp[ 1 ] = fdopen( fdout[ 1 ], "w" ))) exit( 2 ); /* create input pipe from server body */ if ( pipe( fdin ) == -1 ) exit( 3 ); if (!( fp[ 0 ] = fdopen( fdin[ 0 ], "r" ))) exit ( 4 ); /* name of server body to exec */ strcpy( tmp, "/usr/bin/sbroker" ); argv[0] = tmp; /* start the a new process, which runs on its own. */ if ((pid = fork()) == -1) exit( 5 ); /* if in the server body */ if( pid == 0 ) { /* dup our output pipe to servers stdin */ close( 0 ); dup( fdout[ 0 ] ); /* dup our input pipe to servers stdout */ close( 1 ); dup( fdin[ 1 ] ); /* execute sbroker program. */ execlp( tmp, tmp, NULL ); exit( -1 ); } /* swallow the first prompt */ for( i = 0; i < prlen; i++ ) getc( fp[ 0 ] ); /* forever or until we're told to quit */ while( 1 ) { /* wait for sms to call us */ if ( !fgets( stdinb, MAXBUF, stdin )) break; /* if caller wants us to quit */ if ( !strcmp( stdinb, "quit\n" ) ) { fputs( stdinb, fp[ 1 ] ); fflush( fp[ 0 ] ); break; } /* parse arguments: should be stock, shares */ arg[ 0 ] = ( char * )strtok( stdinb, "," ); arg[ 1 ] = ( char * ) strtok( NULL, "," ); arg[ 2 ] = null; /* begin the "trick" code which turns our single input */ /* line into three outputs to the server after each of */ /* which we discard the prompt */ for ( i = 0; i < 3; i++ ) { fprintf( stdout, "%s %s\n", buf[ i ], arg[ i ] ); fflush( stdout ); d = c; for( j = 0; j < prlen; j++ ) { *c = getc( fp[ 0 ] ); if ( *c != prompt[ j ] ) { c++; break; } if ( *c == '\n' ) *c = '\0'; else c++; } *c = '\0'; if ( !strcmp( d, ( char *) prompt + 1 )) continue; fgets( stdinb, MAXBUF, fp[ 0 ] ); } /* this server is implemented as a void function */ fputs( "\n", stdout ); fflush( stdout ); } exit( 0 ); } [LISTING THREE] function "clientCB" { auto dir = "/users/me/stock", table = "portfolio", shares, row; stable current_portfolio_value; static SERVER model; static SERVER broker; /* import the model server */ model->TYPE = 112000; model->CONTEXT = "/.:/hosts/ferrari/ /.:/"; model->PROPC = 1; model->PROPV[ 0 ] = "'finsim' in sblist"; *model = rpi( *model ); (model->INITIALIZE)( "model", "finsim", "quit" ); /* import the broker server */ broker->TYPE = 112000; broker->CONTEXT = "/.:/"; broker->PROPC = 1; broker->PROPV[ 0 ] = "'sbroker' in sblist"; *broker = rpi( *broker ); (model->INITIALIZE)( "trade", "sbroker", "quit" ); /* open the portfolio table */ chdir( dir ); wattach( table ); for ( row = 1 ;( row ); row = nextrow() ) { shares = model( current_portfolio_value, table.* ); if ( !shares ) continue; trade( sprintf( "%s,%s", table.stock, shares )); } (model->DISCARD)(); (broker->DISCARD)(); wdetach(); return(); } Example 1: (a) sample .proplist file; (b) RPI-generated additions to the .proplist file (a) TABLE {'student' 'enroll' 'professors' 'course' 'dept'} STUDENT {'stu_id' 'lastname' 'major' 'stu_desc'} SERVERS {'sql_app' 'filexfer' 'syb2eos' 'eos2syb'} MIPS 144 DISK 1000000000 AUTH {'Pete' 'Lowell' 'Geoff' 'Andrew' 'Kyle' 'Clark'} (b) HOST 'ferrari' hostname 'ferrari.lri.com' binding '187.95.103.78[1234]' SECPAC '211' Example 2: Client initialization foo->PROPV[ 0 ] = "(student in TABLES) or (enroll in TABLES)"; foo->PROPV[ 1 ] = "sql_app in sblist"; foo->PROPV[ 2 ] = "MIPS > 50"; foo->PROPC = 3; Example 3: Command-line prompt % sbroker broker=> set stock IBM stock set to IBM broker=> set shares +20 order set to buy 20 broker=> execute placing order to buy 20 shares IBM broker=> quit