#include "xbcomm.h" int inPipe[ 2 ], outPipe[ 2 ], errPipe[ 2 ]; FILE *toProc, *fromProc, *errProc; /* Returns a char* copy. Allocates sufficient space to contain the string */ /* given as argument, copy the argument string, and returns a pointer to */ /* the copy. */ char *copyString( val ) char *val; { char *str; if ( val IS NULL ) str = NULL; else { str = (char *)malloc( strlen( val ) + 1 ); strcpy( str, val ); } return( str ); } /* Resets a char* pointer to a new value. Allocates sufficient space to */ /* contain the string given as argument, copy the argument string, and */ /* gives back the new pointer, which now contains the copy. */ VOIDPARM setString( str, val ) char **str; char *val; { /* to be most correct, this should free any space that's already */ /* taken up by str - which it doesn't yet */ if ( val IS NULL ) *str = NULL; else { *str = (char *)malloc( strlen( val ) + 1 ); strcpy( *str, val ); } } /* Returns a char* concatenation of str1 (which may be null) with str2. */ /* Iff str1 is not null, str3 is used as a separating string (which may be */ /* null) between str1 and str2. Allocates sufficient space to contain the */ /* string(s) given as arguments, performs the concatenation, and returns a */ /* pointer to the concatenated string. */ char *addString( str1, str2, str3 ) char *str1, *str2, *str3; { char *str; if ( str1 IS NULL ) str = copyString( str2 ); else { if ( str3 IS NULL ) { str = (char *)malloc( strlen( str1 ) + strlen( str2 ) + 1 ); sprintf( str, "%s%s", str1, str2 ); } else { str = (char *)malloc( strlen( str1 ) + strlen( str2 ) + strlen( str3 ) + 1 ); sprintf( str, "%s%s%s", str1, str3, str2 ); } } return( str ); } /* Determine if b is contained in a, if so return a pointer to the */ /* occurrence of b in a. */ char *stringIn( a, b ) char *a; char *b; { int aLen=strlen( a ); int bLen=strlen( b ); char *ap=a; if ( aLen < bLen ) return( NULL ); while ( strlen( ap ) >= bLen ) { if ( NOT strncmp( ap, b, bLen ) ) return( ap ); ap++; } return( NULL ); } char *getAnswer( VOIDPARM ) { char ans[ 256 ], inpt; int count; fflush( stdout ); count = 0; ans[ count ] = NULLTERM; while ( read( 0, &inpt, 1 ) > 0 ) { if ( inpt IS EOL ) { ans[ count ] = NULLTERM; break; } else ans[ count ] = inpt; count++; } printf( "\n" ); return( copyString( ans ) ); } /* Return the "root" part of the filename (max 10 characters)*/ boolean getRootName( VOIDPARM ) { int nameLen, charPos, scriptPos, tmpChar; fileName = theFile; nameLen = strlen( theFile ); charPos = nameLen - 1; while ( charPos ) { tmpChar = theFile[ charPos ]; if ( tmpChar IS SLASH ) { fileName = copyString( theFile + charPos + 1 ); break; } charPos--; } nameLen = strlen( fileName ); charPos = nameLen - 1; while ( charPos ) { tmpChar = fileName[ charPos ]; if ( tmpChar IS DOT ) break; charPos--; } if ( charPos IS 0 ) { fileRoot = fileName; scriptPos = nameLen; } else { fileRoot = (char *)malloc( charPos + 1 ); strncpy( fileRoot, fileName, charPos ); fileRoot[ charPos ] = NULLTERM; scriptPos = charPos; } if ( scriptPos > 8 ) scriptPos = 8; scriptRoot = (char *)malloc( scriptPos + 1 ); strncpy( scriptRoot, fileName, scriptPos ); scriptRoot[ scriptPos ] = NULLTERM; partRoot = (char *)malloc( scriptPos + 1 ); strncpy( partRoot, fileName, scriptPos - 1 ); partRoot[ scriptPos - 1 ] = EQUALSIGN; partRoot[ scriptPos ] = NULLTERM; return( TRUE ); } boolean verifyEnvPath( var ) char *var; { char *envPath; envPath = (char *)getenv( var ); return( ( envPath ISNT NULL ) AND ( strlen( envPath ) ISNT 0 ) ); } char *descPath( VOIDPARM ) { char testPath[ MAXPATHLEN ]; char *envPath; sprintf( testPath, "%s.dsc", fileRoot ); if ( fileExists( testPath ) ) return( fileRoot ); envPath = (char *)getenv( "DSCDIR" ); if ( envPath ISNT NULL AND strlen( envPath ) ) { sprintf( testPath, "%s/%s.dsc", envPath, fileRoot ); if ( noConfirm OR fileExists( testPath ) ) return( addString( envPath, fileRoot, "/" ) ); else return( addString( tmpDir, fileRoot, "/" ) ); } else return( addString( tmpDir, fileRoot, "/" ) ); } #define fileIsFile( fil ) \ ( ( ( fil ).st_mode AND_ S_IFREG ) AND NOT \ ( ( fil ).st_mode AND_ ( S_IFREG XOR_ S_IFLNK ) ) ) /* Determine the existance of a file of a specified type. Returns TRUE */ /* iff the file exists and is of the type(s) specified. */ boolean fileExists( name ) char *name; { boolean statFailed; struct stat dirStat; statFailed = stat( name, &dirStat ); if ( NOT statFailed ) { if ( fileIsFile( dirStat ) ) return( TRUE ); } return( FALSE ); } /* Create a DE - allocates and nulls out a DE structure and returns a */ /* pointer to that structure. */ static DirEntry *cDE( dirName, fileName ) char *dirName, *fileName; { DirEntry *newDE; newDE = (DirEntry *)malloc( sizeof( DirEntry ) ); rDEName( newDE, addString( dirName, fileName, "/" ) ); nDE( newDE ) = NULL; lDE( newDE ) = NULL; return( newDE ); } /* Delete an existing DE. Free up the space it used. */ VOIDPARM kDE( theDE ) DirEntry *theDE; { free( gDEName( theDE ) ); nDE( theDE ) = NULL; lDE( theDE ) = NULL; free( theDE ); } /* Add a DE to the end of an existing linked list of varying size. */ static VOIDPARM aDEDE( parentDE, childDE ) DirEntry *parentDE, *childDE; { DirEntry *tmpDE; if ( DEBUG_PROC ) printf( "Adding DE %s to DE %s...\n", gDEName( childDE ), gDEName( parentDE ) ); if ( ( tmpDE = lDE( parentDE ) ) IS NULL ) nDE( parentDE ) = childDE; else nDE( tmpDE ) = childDE; if ( ( tmpDE = lDE( childDE ) ) IS NULL ) lDE( parentDE ) = childDE; else lDE( parentDE ) = tmpDE; } /* Return a sorted linked list of "DirEntry" structures, representing the */ /* directory entries of the specified type in the specified directory. */ static int comparator( dl1, dl2 ) DirEntry **dl1, **dl2; { if ( gDEName( *dl1 ) IS NULL ) /* dl1 should be BEFORE dl2 */ return( -1 ); else if ( gDEName( *dl2 ) IS NULL ) /* dl1 should be AFTER dl2 */ return( 1 ); else return( strcmp( gDEName( *dl1 ), gDEName( *dl2 ) ) ); } static DirEntry *sortDEs( currList ) DirEntry *currList; { DirEntry *DETable[ 512 ]; int index, count=0; char lastEntry[ MAXPATHLEN ]; DirEntry *result=NULL; if ( currList IS NULL ) return( currList ); /* first, put the current link list into an array for sorting... */ while ( currList ISNT NULL ) { DETable[ count++ ] = currList; currList = nDE( currList ); } DETable[ count ] = NULL; /* ...sort... */ qsort( (char *)DETable, count, sizeof( DirEntry * ), comparator ); /* ...then put the sorted array back into a linked list */ /* "lastEntry" is used to delete any duplicates... */ lastEntry[ 0 ] = NULLTERM; if ( DEBUG_PROC ) printf( "Sorted list follows:\n" ); for ( index = 0; index < count; index++ ) { if ( DEBUG_PROC ) printf( "%s...", gDEName( DETable[ index ] ) ); nDE( DETable[ index ] ) = NULL; lDE( DETable[ index ] ) = NULL; if ( ( lastEntry[ 0 ] IS NULLTERM ) OR ( ( gDEName( DETable[ index ] ) ISNT NULL ) AND ( strcmp( lastEntry, gDEName( DETable[ index ] ) ) ) ) ) { if ( DEBUG_PROC ) printf( "\n" ); if ( result IS NULL ) result = DETable[ index ]; else aDEDE( result, DETable[ index ] ); } else if ( DEBUG_PROC ) printf( "ELIMINATED\n" ); if ( gDEName( DETable[ index ] ) IS NULL ) strcpy( lastEntry, "(null)" ); else strcpy( lastEntry, gDEName( DETable[ index ] ) ); } if ( DEBUG_PROC ) printf( "End of sorted list.\n" ); topDECnt = count; return( result ); } VOIDPARM dirList( searchPatt ) char *searchPatt; { char dirName[ MAXPATHLEN + 2 ]; DirEntry *newDE, *currList=NULL; DIR *theDir; struct dirent *dirEntry; struct stat dirStat; char tmpStr[ 1024 ], filePath[ 1024 ]; char *fname; /* if ( NOT strcmp( tmpDir, "." ) ) { #ifdef SYSV if ( (char *)getcwd( dirName, MAXPATHLEN ) IS NULL ) { printf( "ERROR: Couldn't get current working directory\n" ); exit( -1 ); } #else if ( (char *)getwd( dirName ) IS NULL ) { printf( "ERROR: Couldn't get current working directory because:\n%s\n", dirName ); exit( -1 ); } #endif } else */ sprintf( dirName, "%s", tmpDir ); theDir = opendir( dirName ); while ( ( dirEntry = readdir( theDir ) ) ISNT NULL ) { newDE = NULL; fname = dirEntry->d_name; if ( DEBUG_PROC ) printf( "This directory entry: '%s'\n", fname ); if ( NOT ( strcmp( fname, "." ) AND strcmp( fname, ".." ) ) ) continue; if ( NOT stringIn( fname, searchPatt ) ) continue; sprintf( filePath, "%s/%s", dirName, fname ); if ( stat( filePath, &dirStat ) ) { sprintf( tmpStr, "\nERROR: Couldn't find file '%s'", filePath ); perror( tmpStr ); } else if ( ( newDE IS NULL ) AND fileIsFile( dirStat ) ) newDE = cDE( dirName, fname ); if ( newDE ISNT NULL ) { if ( currList IS NULL ) currList = newDE; else aDEDE( currList, newDE ); } } closedir( theDir ); topDE = sortDEs( currList ); } #define sendToProc( whatToSend, result ) \ { \ ( result) = fprintf( toProc, "%s;\n", whatToSend ); \ fflush( toProc ); \ if ( ( result ) > 0 ) \ ( result ) = 0; \ } char *shellResult( theCommand, returnVal ) char *theCommand; int *returnVal; { int n; boolean notDone; char buf[ BUFSIZ ]; char *realCommand; char *retPtr, *result; result = NULL; /* sprintf( realCommand, "%s; echo \": $?\"", theCommand ); */ realCommand = (char *)malloc( strlen( "; echo \": $?\"" ) + strlen( theCommand ) + 1 ); sprintf( realCommand, "%s; echo \": $?\"", theCommand ); if ( DEBUG_PROC ) printf( "Slave shell about to execute '%s'\n", realCommand ); sendToProc( realCommand, *returnVal ); /* command completed - get stdout and stderr info */ notDone = TRUE; while ( notDone ) { while ( ( n = read( inPipe[ 0 ], buf, BUFSIZ ) ) > 0 ) { buf[ n ] = NULLTERM; if ( DEBUG_PROC ) printf( "From shell output '%s'\n", buf ); if ( ( ( retPtr = stringIn( buf, ":" ) ) ISNT NULL ) AND ( sscanf( retPtr, ": %d", returnVal ) IS 1 ) ) { /* got the return status - command is done */ notDone = FALSE; retPtr[ 0 ] = NULLTERM; } if ( DEBUG_PROC ) printf( "(Modified) shell output '%s' (length %d)\n", buf, strlen( buf ) ); if ( strlen( buf ) ) { if ( DEBUG_PROC ) printf( "There WAS output!!\n" ); result = addString( result, buf, " " ); if ( DEBUG_PROC ) printf( "result is '%s'\n", result ); } } /* ...still waiting for proper return status... */ } /* Pass anything from shell's standard error */ /* to our standard error */ while ( ( n = read( errPipe[ 0 ], buf, BUFSIZ ) ) > 0 ) { buf[ n ] = '\0'; if ( DEBUG_PROC ) printf( "From shell error '%s'\n", buf ); } return( result ); } VOIDPARM closePipes( VOIDPARM ) { if ( toProc ISNT NULL ) fclose( toProc ); if ( fromProc ISNT NULL ) fclose( fromProc ); if ( errProc ISNT NULL ) fclose( errProc ); if ( inPipe[ 0 ] ISNT -1 ) close( inPipe[ 0 ] ); if ( inPipe[ 1 ] ISNT -1 ) close( inPipe[ 1 ] ); if ( outPipe[ 0 ] ISNT -1 ) close( outPipe[ 0 ] ); if ( outPipe[ 1 ] ISNT -1 ) close( outPipe[ 1 ] ); if ( errPipe[ 0 ] ISNT -1 ) close( errPipe[ 0 ] ); if ( errPipe[ 1 ] ISNT -1 ) close( errPipe[ 1 ] ); } boolean openTopShell( VOIDPARM ) { if ( DEBUG_PROC ) printf( "Opening top-level shell...\n" ); /* set up pipes to standard in, out, and error */ if ( pipe( inPipe ) IS -1 ) { if ( DEBUG_PROC ) printf( "Error opening up inPipe...\n" ); printf( "ERROR: cannot open slave shell...\n" ); return( FALSE ); } if ( pipe( outPipe ) IS -1 ) { if ( DEBUG_PROC ) printf( "Error opening up outPipe...\n" ); closePipes(); printf( "ERROR: cannot open slave shell...\n" ); return( FALSE ); } if ( pipe( errPipe ) IS -1 ) { if ( DEBUG_PROC ) printf( "Error opening up errPipe...\n" ); closePipes(); printf( "ERROR: cannot open slave shell...\n" ); return( FALSE ); } /* open from file descriptors */ toProc = fdopen( outPipe[ 1 ], "w" ); fromProc = fdopen( inPipe[ 0 ], "r" ); errProc = fdopen( errPipe[ 0 ], "r" ); if ( NOT ( toProc AND fromProc AND errProc ) ) { if ( DEBUG_PROC ) printf( "Error opening up process pipes...\n" ); closePipes(); printf( "ERROR: cannot open slave shell...\n" ); return( FALSE ); } /* make parent non-blocking */ fcntl( fileno( toProc ), F_SETFL, O_NDELAY ); fcntl( fileno( fromProc ), F_SETFL, O_NDELAY ); fcntl( fileno( errProc ), F_SETFL, O_NDELAY ); if ( fork() IS 0 ) { system( "sleep 5" ); /* redirect standard input */ close( outPipe[ 1 ] ); close( fileno( stdin ) ); dup( outPipe[ 0 ] ); close( outPipe[ 0 ] ); /* redirect standard error */ close( errPipe[ 0 ] ); close( fileno( stderr ) ); dup( errPipe[ 1 ] ); close( errPipe[ 1 ] ); /* redirect standard output */ close( inPipe[ 0 ] ); close( fileno( stdout ) ); dup( inPipe[ 1 ] ); close( inPipe[ 1 ] ); /* exec the shell! */ execl( "/bin/sh", "sh", "-s", NULL ); if ( DEBUG_PROC ) /* Will NEVER get here unless the exec fails */ printf( "Couldn't start 'sh -s'\n" ); printf( "ERROR: cannot open slave shell...\n" ); exit( 0 ); } /* close the stuff we don't need as parent */ close( outPipe[ 0 ] ); close( inPipe[ 1 ] ); close( errPipe[ 1 ] ); return( TRUE ); } boolean closeTopShell( VOIDPARM ) { int result; sendToProc( "exit", result ); system( "sleep 2" ); /* give the shell a chance to respond */ if ( DEBUG_PROC ) printf( "Closing top-level shell...\n" ); closePipes(); return( result IS 0 ); } /* Read a line from a file - return the line and the last character read. */ int lineRead( src, dst ) FILE *src; char dst[]; { char *lPtr; int c; dst[ 0 ] = NULLTERM; lPtr = dst; while ( ( ( c = getc( src ) ) ISNT EOL ) AND ( c ISNT EOF ) ) *lPtr++ = (char)c; *lPtr = NULLTERM; return( c ); } char *utilInPath( util, shouldBitch ) char *util; boolean shouldBitch; { static char *path; char *this, *next, *suggestion; char tmpPath[ MAXPATHLEN ], tmpFile[ MAXPATHLEN ]; if ( path IS NULL ) path = (char *)getenv( "PATH" ); /* Now the fun begins... search through the PATH setting to */ /* find out if the given utility is accessible... */ this = path; suggestion = NULL; while ( this ) { if ( ( next = (char *)strchr( this, ':' ) ) AND ( next > this ) ) { /* Extract out the current PATH element. */ strncpy( tmpPath, this, next - this ); tmpPath[ next - this ] = '\0'; next += 1; } else if ( next IS NULL ) { /* We are on the last element of the PATH variable. */ strcpy( tmpPath, this ); tmpPath[ strlen( this ) ] = '\0'; } else { /* If a ":" is present without a PATH element, a "." */ /* is implied. */ tmpPath[ 0 ] = '\0'; next += 1; } if ( tmpPath[ 0 ] ISNT NULLTERM ) sprintf( tmpFile, "%s/%s", tmpPath, util ); else sprintf( tmpFile, "%s", util ); /* Is it there? */ if ( fileExists( tmpFile ) ) suggestion = addString( suggestion, tmpFile, " or " ); this = next; } if ( ( suggestion == NULL ) AND shouldBitch ) printf( "ERROR: Can't find '%s' in the current path! Aborting...\n", util ); return( suggestion ); } VOIDPARM suggest( util, switches ) char *util, *switches; { char *suggestion; if ( suggestion = utilInPath( util, FALSE ) ) { if ( switches ) printf( "\t(%s {with %s option(s)} might be a good setting...)\n", suggestion, switches ); else printf( "\t(%s might be a good setting...)\n", suggestion ); } else { if ( switches ) printf( "\t(I'd suggest '%s %s' - but it's apparently not available...)\n", util, switches ); else printf( "\t(I'd suggest '%s' - but it's apparently not available...)\n", util ); } }