@@ -288,6 +288,7 @@ int ios_getCommandStatus() {
288288 sessionParameters* session;
289289} functionParameters;
290290
291+ extern pthread_mutex_t pid_mtx;
291292static void cleanup_function (void * parameters) {
292293 // This function is called when pthread_exit() or ios_kill() is called
293294 functionParameters *p = (functionParameters *) parameters;
@@ -369,6 +370,11 @@ static void cleanup_function(void* parameters) {
369370 mustCloseStderr &= fileno (p->stderr ) != fileno (currentSession->stdout );
370371 }
371372 }
373+ // Some programs stop waiting as soon as stdout/stderr close (which makes sense)
374+ if (isLastThread) {
375+ NSLog (@" Locking for thread %x in cleanup_function\n " , pthread_self ());
376+ pthread_mutex_lock (&pid_mtx); // Avoid multi-lock when several commands end together (for ls | grep)
377+ }
372378 if (mustCloseStderr) {
373379 NSLog (@" Closing stderr (mustCloseStderr): %d \n " , fileno (p->stderr ));
374380 fclose (p->stderr );
@@ -401,6 +407,9 @@ static void cleanup_function(void* parameters) {
401407 if (currentSession->mainThreadId == pthread_self ()) {
402408 currentSession->mainThreadId = 0 ;
403409 }
410+ if (isLastThread) {
411+ pthread_mutex_unlock (&pid_mtx);
412+ }
404413}
405414
406415// Avoir calling crash_handler several times:
@@ -841,20 +850,29 @@ void __cd_to_dir(NSString *newDir, NSFileManager *fileManager) {
841850// For some Unix commands that call fchdir (including vim:
842851#undef fchdir
843852int ios_fchdir (const int fd) {
853+ NSLog (@" Locking for thread %x in ios_fchdir\n " , pthread_self ());
854+ // We cannot have someone change the current directory while a command is starting or terminating.
855+ // hence the mutex_lock here.
856+ pthread_mutex_lock (&pid_mtx);
844857 int result = fchdir (fd);
845858 if (result < 0 ) {
859+ NSLog (@" Unlocking for thread %x in ios_fchdir\n " , pthread_self ());
860+ pthread_mutex_unlock (&pid_mtx);
846861 return result;
847862 }
848863 // We managed to change the directory. Update currentSession as well:
849864 // Was that allowed?
850865 // Allowed "cd" = below miniRoot *or* below localMiniRoot
851866 NSFileManager *fileManager = [[NSFileManager alloc ] init ];
852867 NSString * resultDir = [fileManager currentDirectoryPath ];
868+ NSLog (@" Inside fchdir, path: %s for session: %s \n " , resultDir.UTF8String , (char *)currentSession->context );
853869
854870 if (__allowed_cd_to_path (resultDir)) {
855871 strcpy (currentSession->previousDirectory , currentSession->currentDir );
856872 strcpy (currentSession->currentDir , [resultDir UTF8String ]);
857873 errno = 0 ;
874+ NSLog (@" Unlocking for thread %x in ios_fchdir\n " , pthread_self ());
875+ pthread_mutex_unlock (&pid_mtx);
858876 return 0 ;
859877 }
860878
@@ -868,30 +886,84 @@ int ios_fchdir(const int fd) {
868886 // go back to where we were before:
869887 [fileManager changeCurrentDirectoryPath: [NSString stringWithCString: currentSession->currentDir encoding: NSUTF8StringEncoding]];
870888 }
889+ NSLog (@" Unlocking for thread %x in ios_fchdir\n " , pthread_self ());
890+ pthread_mutex_unlock (&pid_mtx);
871891 return -1 ;
872892}
873893
874894
895+ int chdir_nolock (const char * path) {
896+ // Same function as chdir, except it does not lock. To be called from ios_releaseThread*()
897+ NSFileManager *fileManager = [[NSFileManager alloc ] init ];
898+ NSString * newDir = @(path);
899+ BOOL isDir;
900+ // Check for permission and existence:
901+ if (![fileManager fileExistsAtPath: newDir isDirectory: &isDir]) {
902+ errno = ENOENT; // No such file or directory
903+ return -1 ;
904+ }
905+ if (!isDir) {
906+ errno = ENOTDIR; // Not a directory
907+ return -1 ;
908+ }
909+ if (![fileManager isReadableFileAtPath: newDir] ||
910+ ![fileManager changeCurrentDirectoryPath: newDir]) {
911+ errno = EACCES; // Permission denied
912+ return -1 ;
913+ }
914+
915+ // We managed to change the directory.
916+ // Was that allowed?
917+ // Allowed "cd" = below miniRoot *or* below localMiniRoot
918+ NSString * resultDir = [fileManager currentDirectoryPath ];
919+
920+ if (__allowed_cd_to_path (resultDir)) {
921+ strcpy (currentSession->currentDir , [resultDir UTF8String ]);
922+ errno = 0 ;
923+ return 0 ;
924+ }
925+
926+ errno = EACCES; // Permission denied
927+ // If the user tried to go above the miniRoot, set it to miniRoot
928+ if ([miniRoot hasPrefix: resultDir]) {
929+ [fileManager changeCurrentDirectoryPath: miniRoot];
930+ strcpy (currentSession->currentDir , [miniRoot UTF8String ]);
931+ strcpy (currentSession->previousDirectory , currentSession->currentDir );
932+ } else {
933+ // go back to where we were before:
934+ [fileManager changeCurrentDirectoryPath: [NSString stringWithCString: currentSession->currentDir encoding: NSUTF8StringEncoding]];
935+ }
936+ return -1 ;
937+ }
875938
876939// For some Unix commands that call chdir:
877940// Is also called at the end of the execution of each command
878941int chdir (const char * path) {
879- // NSLog(@"Inside chdir, path: %s for session: %s\n", path, (char*)currentSession->context);
942+ NSLog (@" Locking for thread %x in chdir, cd %s , stdin= %d \n " , pthread_self (), path, fileno (thread_stdin));
943+ // We cannot have someone change the current directory while a command is starting or terminating.
944+ // hence the mutex_lock here.
945+ pthread_mutex_lock (&pid_mtx);
880946 NSFileManager *fileManager = [[NSFileManager alloc ] init ];
881947 NSString * newDir = @(path);
882948 BOOL isDir;
883949 // Check for permission and existence:
884950 if (![fileManager fileExistsAtPath: newDir isDirectory: &isDir]) {
885951 errno = ENOENT; // No such file or directory
952+ NSLog (@" Unlocking for thread %x in chdir\n " , pthread_self ());
953+ pthread_mutex_unlock (&pid_mtx);
886954 return -1 ;
887955 }
888956 if (!isDir) {
889957 errno = ENOTDIR; // Not a directory
958+ NSLog (@" Unlocking for thread %x in chdir\n " , pthread_self ());
959+ pthread_mutex_unlock (&pid_mtx);
890960 return -1 ;
891961 }
892962 if (![fileManager isReadableFileAtPath: newDir] ||
893963 ![fileManager changeCurrentDirectoryPath: newDir]) {
894964 errno = EACCES; // Permission denied
965+ NSLog (@" Unlocking for thread %x in chdir\n " , pthread_self ());
966+ pthread_mutex_unlock (&pid_mtx);
895967 return -1 ;
896968 }
897969
@@ -902,6 +974,8 @@ int chdir(const char* path) {
902974
903975 if (__allowed_cd_to_path (resultDir)) {
904976 strcpy (currentSession->currentDir , [resultDir UTF8String ]);
977+ NSLog (@" Unlocking for thread %x in chdir\n " , pthread_self ());
978+ pthread_mutex_unlock (&pid_mtx);
905979 errno = 0 ;
906980 return 0 ;
907981 }
@@ -916,6 +990,8 @@ int chdir(const char* path) {
916990 // go back to where we were before:
917991 [fileManager changeCurrentDirectoryPath: [NSString stringWithCString: currentSession->currentDir encoding: NSUTF8StringEncoding]];
918992 }
993+ NSLog (@" Unlocking for thread %x in chdir\n " , pthread_self ());
994+ pthread_mutex_unlock (&pid_mtx);
919995 return -1 ;
920996}
921997
@@ -2048,6 +2124,7 @@ static int isRealCommand(const char* fileName) {
20482124}
20492125
20502126int ios_system (const char * inputCmd) {
2127+ NSLog (@" command= %s pid= %d \n " , inputCmd, ios_currentPid ());
20512128 char * command;
20522129 // The names of the files for stdin, stdout, stderr
20532130 char * inputFileName = 0 ;
@@ -2061,7 +2138,6 @@ int ios_system(const char* inputCmd) {
20612138 char * scriptName = 0 ; // interpreted commands
20622139 bool sharedErrorOutput = false ;
20632140 NSFileManager *fileManager = [[NSFileManager alloc ] init ];
2064- NSLog (@" command= %s \n " , inputCmd);
20652141 // NSLog(@"ios_system, stdout %d \n", thread_stdout == NULL ? 0 : fileno(thread_stdout));
20662142 // NSLog(@"ios_system, stderr %d \n", thread_stderr == NULL ? 0 : fileno(thread_stderr));
20672143 if (currentSession == NULL ) {
@@ -2282,7 +2358,7 @@ int ios_system(const char* inputCmd) {
22822358 // scan until first ">"
22832359 bool appendToFileName = false ;
22842360 if (!sharedErrorOutput) {
2285- // output and append
2361+ // output and append.
22862362 outputFileMarker = strstrquoted (outputFileMarker, " >" );
22872363 if (outputFileMarker) {
22882364 if ((strlen (outputFileMarker) > 1 ) && (outputFileMarker[1 ] == ' >' )) { // >>
@@ -2293,7 +2369,8 @@ int ios_system(const char* inputCmd) {
22932369 }
22942370 }
22952371 } else {
2296- outputFileMarker = NULL ;
2372+ if (outputFileName == NULL )
2373+ outputFileMarker = NULL ;
22972374 }
22982375 if (outputFileName) {
22992376 while ((outputFileName[0 ] == ' ' ) && strlen (outputFileName) > 0 ) outputFileName++;
@@ -2546,19 +2623,21 @@ int ios_system(const char* inputCmd) {
25462623 cmdIsReal = true ;
25472624 NSData *data = [NSData dataWithContentsOfFile: locationName]; // You have the data. Conversion to String probably failed.
25482625 NSString *fileContent = [[NSString alloc ]initWithData:data encoding: NSUTF8StringEncoding];
2626+ if ((fileContent == nil ) && (data.length > 0 )) {
2627+ // Conversion to string failed with UTF8. Try with Ascii as a backup:
2628+ fileContent = [[NSString alloc ]initWithData:data encoding: NSASCIIStringEncoding];
2629+ }
25492630 NSString * firstLine;
25502631 if (fileContent != nil ) {
25512632 NSRange firstLineRange = [fileContent rangeOfString: @" \n " ];
2552- firstLineRange.length = firstLineRange.location ;
2633+ if (firstLineRange.length > 0 ) {
2634+ firstLineRange.length = firstLineRange.location ;
2635+ } else {
2636+ firstLineRange.length = fileContent.length ;
2637+ }
25532638 firstLineRange.location = 0 ;
25542639 firstLine = [fileContent substringWithRange: firstLineRange];
25552640 }
2556- // Detect WebAssembly file signature: '\0asm' (begins with 0, so not a string)
2557- if ((firstLine == nil ) && (data.length >0 ) && (((char *)data.bytes )[0 ] == 0 )) {
2558- fileContent = [[NSString alloc ]initWithData:data encoding: NSASCIIStringEncoding];
2559- NSRange signatureRange = NSMakeRange (1 , 3 );
2560- firstLine = [fileContent substringWithRange: signatureRange];
2561- }
25622641 if ([firstLine hasPrefix: @" #!" ]) {
25632642 // 1) get script language name
25642643 // The last word of the line is the command. This covers all of the cases encountered:
@@ -2599,19 +2678,27 @@ int ios_system(const char* inputCmd) {
25992678 // TODO: need to loop back if scriptName is itself a file.
26002679 break ;
26012680 }
2602- } else if ([firstLine isEqualToString: @" asm" ]) {
2603- // WebAssembly file, identified by signature:
2604- // Same code as above, but single command:
2605- argc += 1 ;
2606- argv = (char **)realloc (argv, sizeof (char *) * (argc + 1 ));
2607- // Move everything numComponents step up
2608- for (int i = argc; i >= 1 ; i--) { argv[i] = argv[i-1 ]; }
2609- // Change the location of the file (from "command" to "/actual/full/path/command"):
2610- // This pointer existed before
2611- argv[1 ] = realloc (argv[1 ], locationName.length + 1 );
2612- strcpy (argv[1 ], locationName.UTF8String );
2613- // Copy all arguments without change (except the first):
2614- argv[0 ] = strdup (" wasm" ); // creates new pointer
2681+ } else {
2682+ // Detect WebAssembly file signature: '\0asm' (begins with 0, so not a string)
2683+ if ((data.length >0 ) && (((char *)data.bytes )[0 ] == 0 )) {
2684+ // fileContent = [[NSString alloc]initWithData:data encoding:NSASCIIStringEncoding];
2685+ NSRange signatureRange = NSMakeRange (1 , 3 );
2686+ firstLine = [fileContent substringWithRange: signatureRange];
2687+ }
2688+ if ([firstLine isEqualToString: @" asm" ]) {
2689+ // WebAssembly file, identified by signature:
2690+ // Same code as above, but single command:
2691+ argc += 1 ;
2692+ argv = (char **)realloc (argv, sizeof (char *) * (argc + 1 ));
2693+ // Move everything numComponents step up
2694+ for (int i = argc; i >= 1 ; i--) { argv[i] = argv[i-1 ]; }
2695+ // Change the location of the file (from "command" to "/actual/full/path/command"):
2696+ // This pointer existed before
2697+ argv[1 ] = realloc (argv[1 ], locationName.length + 1 );
2698+ strcpy (argv[1 ], locationName.UTF8String );
2699+ // Copy all arguments without change (except the first):
2700+ argv[0 ] = strdup (" wasm" ); // creates new pointer
2701+ }
26152702 }
26162703 } else {
26172704 cmdIsReal = false ;
@@ -2721,14 +2808,16 @@ int ios_system(const char* inputCmd) {
27212808 else handle = dlopen (libraryName.UTF8String , RTLD_LAZY | RTLD_GLOBAL); // commands defined in dynamic library
27222809 if (handle == NULL ) {
27232810 NSLog (@" Failed loading %s from %s , cause = %s \n " , commandName.UTF8String , libraryName.UTF8String , dlerror ());
2724- if (sideLoading) fprintf (thread_stderr, " Failed loading %s from %s , cause = %s \n " , commandName.UTF8String , libraryName.UTF8String , dlerror ());
2811+ // if (sideLoading)
2812+ fprintf (thread_stderr, " Failed loading %s from %s , cause = %s \n " , commandName.UTF8String , libraryName.UTF8String , dlerror ());
27252813 NSString * fileLocation = [[NSBundle mainBundle ] pathForResource: libraryName ofType: nil ];
27262814 } else {
27272815 NSString * functionName = commandStructure[1 ];
27282816 function = dlsym (handle, functionName.UTF8String );
27292817 if (function == NULL ) {
27302818 NSLog (@" Failed loading %s from %s , cause = %s \n " , commandName.UTF8String , libraryName.UTF8String , dlerror ());
2731- if (sideLoading) fprintf (thread_stderr, " Failed loading %s from %s , cause = %s \n " , commandName.UTF8String , libraryName.UTF8String , dlerror ());
2819+ // if (sideLoading)
2820+ fprintf (thread_stderr, " Failed loading %s from %s , cause = %s \n " , functionName.UTF8String , libraryName.UTF8String , dlerror ());
27322821 }
27332822 }
27342823 }
0 commit comments