Code:
$ cat mysrc/bctl.c
/*************************************************************************
* $RCSfile: $
* $Source: $
* $Revision: $
* $Date: $
* $Author: $
* $State: $
* $Locker: $
*************************************************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>
#include <strings.h>
static char usage[] =
"\n"
"Usage: bctl <num_sim> [ -v ] [ -l <lines_per> ]\n"
"\n"
"Reads <lines_per> (default one) line commands from standard input and\n"
"executes <num_sim> of them at a time, under the ksh. The order of\n"
"termination has no control over the execution. Keeps <num_sim> lines\n"
"running, and when standard input is exhausted, waits for all chilren to\n"
"terminate. With -v, reports any abnormal child exit.\n"
"\n" ;
static int l = 1 ;
static int lct = 0 ;
static int v = 0 ;
static int i ;
static int x = 0 ;
static int c = 0 ;
static int cpid ;
static int cstat ;
static char buf[65536];
static char *bufp = buf ;
static char *argv2[4] = { "/usr/bin/ksh", "-c", buf, NULL };
static siginfo_t wsinfo ;
static int p_wait()
{
cstat = 0 ;
if ( 0 > ( cpid = wait( &cstat ) ) )
{
if ( errno == ECHILD )
return 0 ;
perror( "wait()" );
exit( 1 );
}
if ( !v )
return 1 ;
switch ( cstat & 0xff )
{
case 0:
if ( cstat )
fprintf( stderr, "\nProcess %d exit %d\n",
cpid, cstat>>8 );
break ;
case WSTOPFLG :
fprintf( stderr, "\nProcess %d stopped on signal %d\n",
cpid, cstat>>8 );
break ;
default:
if ( !( cstat & 0xff00 ) )
fprintf( stderr, "\nProcess %d term by sig %d\n",
cpid, cstat & 0xff );
else
fprintf( stderr, "\nProcess %d wait(%d-%d)\n",
cpid, cstat>>8, cstat & 0xff );
break ;
}
return 1 ;
}
main( int argc, char **argv )
{
for ( i = 1 ; i < argc ; i++ )
{
if ( !strcmp( argv[i], "-v" ) )
{
v = 1 ;
continue ;
}
if ( !strcmp( argv[i], "-l" )
&& ++i < argc
&& ( l = atoi( argv[i] ) ) > 0 )
{
continue ;
}
if ( 2 > ( x = atoi( argv[i] ) ) )
{
fputs( usage, stderr );
exit( 1 );
}
}
while ( fgets( bufp, sizeof buf + buf - bufp, stdin ) )
{
if ( !( bufp = strchr( bufp, '\n' ) ) )
{
fputs( "\nFatal: Command too large!\n", stderr );
exit( 1 );
}
else
bufp++ ;
if ( ++lct < l )
{
continue ;
}
else
{
bufp = buf ;
lct = 0 ;
}
if ( c == x )
{
p_wait();
}
else
c++ ;
switch( vfork() )
{
case -1:
perror( "vfork()" );
exit( 1 );
case 0: /* child */
execvp( *argv2, argv2 );
perror( "execvp(/usr/bin/ksh)" );
exit( 1 );
default: /* parent */
break ;
}
}
if ( ferror( stdin ) )
{
perror( "stdin" );
exit( 1 );
}
while ( p_wait() )
{
/* nothing else */
}
if ( lct )
{
fprintf( stderr,
"bctl: discarding incomplete command at EOF:\n"
"%s\n"
, buf );
}
exit( 0 );
}
/*************************************************************************
*
* Revision History:
*
* $Log: $
*
************************** End of File ********************************/