@@ -592,7 +592,7 @@ void initializeEnvironment() {
592592
593593 NSRange rSub = NSMakeRange (r1.location + r1.length , r2.location - r1.location - r1.length );
594594 NSString *variable_string = [argumentString substringWithRange: rSub];
595- const char * variable = getenv ([variable_string UTF8String ]);
595+ const char * variable = ios_getenv ([variable_string UTF8String ]);
596596 if (variable) {
597597 // Okay, so this one exists.
598598 NSString * replacement_string = [NSString stringWithCString: variable encoding: NSUTF8StringEncoding];
@@ -847,7 +847,7 @@ void __cd_to_dir(NSString *newDir, NSFileManager *fileManager) {
847847 }
848848}
849849
850- // For some Unix commands that call fchdir (including vim:
850+ // For some Unix commands that call fchdir (including vim) :
851851#undef fchdir
852852int ios_fchdir (const int fd) {
853853 NSLog (@" Locking for thread %x in ios_fchdir\n " , pthread_self ());
@@ -892,6 +892,38 @@ int ios_fchdir(const int fd) {
892892 return -1 ;
893893}
894894
895+ int ios_fchdir_nolock (const int fd) {
896+ // Same function as fchdir, except it does not lock. To be called when resetting directory after fork().
897+ while (cleanup_counter > 0 ) { } // Don't chdir while a command is ending.
898+ int result = fchdir (fd);
899+ if (result < 0 ) {
900+ return result;
901+ }
902+ // We managed to change the directory. Update currentSession as well:
903+ // Was that allowed?
904+ // Allowed "cd" = below miniRoot *or* below localMiniRoot
905+ NSFileManager *fileManager = [[NSFileManager alloc ] init ];
906+ NSString * resultDir = [fileManager currentDirectoryPath ];
907+
908+ if (__allowed_cd_to_path (resultDir)) {
909+ strcpy (currentSession->previousDirectory , currentSession->currentDir );
910+ strcpy (currentSession->currentDir , [resultDir UTF8String ]);
911+ errno = 0 ;
912+ return 0 ;
913+ }
914+
915+ errno = EACCES; // Permission denied
916+ // If the user tried to go above the miniRoot, set it to miniRoot
917+ if ([miniRoot hasPrefix: resultDir]) {
918+ [fileManager changeCurrentDirectoryPath: miniRoot];
919+ strcpy (currentSession->currentDir , [miniRoot UTF8String ]);
920+ strcpy (currentSession->previousDirectory , currentSession->currentDir );
921+ } else {
922+ // go back to where we were before:
923+ [fileManager changeCurrentDirectoryPath: [NSString stringWithCString: currentSession->currentDir encoding: NSUTF8StringEncoding]];
924+ }
925+ return -1 ;
926+ }
895927
896928int chdir_nolock (const char * path) {
897929 // Same function as chdir, except it does not lock. To be called from ios_releaseThread*()
@@ -1521,12 +1553,17 @@ int sh_main(int argc, char** argv) {
15211553 // Anything after "sh" that contains an equal sign must be an environment variable. Pass it to ios_setenv.
15221554 while (command[0 ] != NULL ) {
15231555 char * position = strstrquoted (command[0 ]," =" );
1524- char * firstSpace = strstrquoted (command[0 ]," " );
15251556 if (position == NULL ) { break ; }
1557+ char * firstSpace = strstrquoted (command[0 ]," " );
15261558 if (firstSpace < position) { break ; }
1559+ firstSpace = strstrquoted (position," " );
1560+ if (firstSpace != NULL ) { *firstSpace = 0 ; }
15271561 *position = 0 ;
15281562 ios_setenv (command[0 ], position+1 , 1 );
1529- command++;
1563+ if (firstSpace != NULL ) {
1564+ command[0 ] = firstSpace + 1 ;
1565+ }
1566+ else { command++; }
15301567 }
15311568 if (command[0 ] == NULL ) {
15321569 argv[0 ][0 ] = ' h' ; // prevent termination in cleanup_function
@@ -2185,6 +2222,21 @@ int ios_system(const char* inputCmd) {
21852222 }
21862223 } else command = cmd;
21872224 // fprintf(thread_stderr, "Command sent: %s \n", command);
2225+ // Environment variables before alias expansion:
2226+ char * commandForParsing = strdup (command);
2227+ char * commandForParsingFree = commandForParsing;
2228+ char * firstSpace = strstrquoted (commandForParsing, " " );
2229+ while (firstSpace != NULL ) {
2230+ *firstSpace = 0 ;
2231+ char * equalSign = strchr (commandForParsing, ' =' );
2232+ if (equalSign == NULL ) break ;
2233+ *equalSign = 0 ;
2234+ ios_setenv (commandForParsing, equalSign+1 , 1 );
2235+ command += (firstSpace - commandForParsing) + 1 ;
2236+ commandForParsing = firstSpace + 1 ;
2237+ firstSpace = strstrquoted (commandForParsing, " " );
2238+ }
2239+ free (commandForParsingFree);
21882240 // alias expansion *before* input, output and error redirection.
21892241 if ((command[0 ] != ' \\ ' ) && (aliasDictionary != nil )) {
21902242 // \command = cancel aliasing, get the original command
@@ -2728,8 +2780,6 @@ int ios_system(const char* inputCmd) {
27282780 NSString * commandName = [NSString stringWithCString: argv[0 ] encoding: NSUTF8StringEncoding];
27292781 // hasPrefix covers python, python3, python3.9.
27302782 if ([commandName hasPrefix: @" python" ]) {
2731- // Tell Python that we are running Python3.
2732- setenv (" PYTHONEXECUTABLE" , " python3" , 1 );
27332783 // Ability to start multiple python3 scripts (required for Jupyter notebooks):
27342784 // start by increasing the number of the interpreter, until we're out.
27352785 int numInterpreter = 0 ;
@@ -2745,6 +2795,8 @@ int ios_system(const char* inputCmd) {
27452795 display_alert (@" Too many Python scripts" , @" There are too many Python interpreters running at the same time. Try closing some of them." );
27462796 NSLog (@" %@ " , @" Too many python scripts running simultaneously. Try closing some notebooks.\n " );
27472797 commandName = @" notAValidCommand" ;
2798+ } else {
2799+ currentPythonInterpreter = numInterpreter;
27482800 }
27492801 }
27502802 if ((numInterpreter == 0 ) && (strlen (argv[0 ]) > 7 )) {
@@ -2986,6 +3038,7 @@ int ios_system(const char* inputCmd) {
29863038 NSString * result = [pathNormalizeArray ([path pathComponents ], !isAbsolute) componentsJoinedByString: @" /" ];
29873039
29883040 if (!result.length && !isAbsolute) {
3041+ // Same function as chdir, except it does not lock. To be called from ios_releaseThread*()
29893042 result = @" ." ;
29903043 }
29913044
@@ -3018,3 +3071,51 @@ int ios_system(const char* inputCmd) {
30183071
30193072 return pathNormalize (path);
30203073}
3074+
3075+ //
3076+ char * ios_getPythonLibraryName () {
3077+ // Ability to start multiple python3 scripts, expanded for commands that start python3 as a dynamic library.
3078+ // (mostly vim, right now)
3079+ // start by increasing the number of the interpreter, until we're out.
3080+ int numInterpreter = 0 ;
3081+ if (currentPythonInterpreter < numPythonInterpreters) {
3082+ numInterpreter = currentPythonInterpreter;
3083+ currentPythonInterpreter++;
3084+ } else {
3085+ while (numInterpreter < numPythonInterpreters) {
3086+ if (PythonIsRunning[numInterpreter] == false ) break ;
3087+ numInterpreter++;
3088+ }
3089+ if (numInterpreter >= numPythonInterpreters) {
3090+ // NSLog(@"ios_getPythonLibraryName: returning NULL\n");
3091+ return NULL ;
3092+ } else {
3093+ currentPythonInterpreter = numInterpreter;
3094+ }
3095+ }
3096+ char * libraryName = NULL ;
3097+ if ((numInterpreter >= 0 ) && (numInterpreter < numPythonInterpreters)) {
3098+ PythonIsRunning[numInterpreter] = true ;
3099+ if (numInterpreter > 0 ) {
3100+ libraryName = strdup (" pythonA" );
3101+ libraryName[6 ] = ' A' + (numInterpreter - 1 );
3102+ } else {
3103+ libraryName = strdup (" python3_ios" );
3104+ }
3105+ // NSLog(@"ios_getPythonLibraryName: returning %s\n", libraryName);
3106+ return libraryName;
3107+ }
3108+ // NSLog(@"ios_getPythonLibraryName: returning NULL\n");
3109+ return NULL ;
3110+ }
3111+
3112+ void ios_releasePythonLibraryName (char * name) {
3113+ char libNumber = name[6 ];
3114+ if (libNumber == ' 3' ) PythonIsRunning[0 ] = false ;
3115+ else {
3116+ libNumber -= ' A' - 1 ;
3117+ if ((libNumber > 0 ) && (libNumber < MaxPythonInterpreters))
3118+ PythonIsRunning[libNumber] = false ;
3119+ }
3120+ free (name);
3121+ }
0 commit comments