From 540e1132b996055e07ae0040b2dca8d87a1792bf Mon Sep 17 00:00:00 2001 From: HOLZSCHUCH Nicolas <nicolas.holzschuch@inria.fr> Date: Tue, 2 Nov 2021 17:15:24 +0100 Subject: [PATCH] Bug fixing with fork and environment variables --- awk-23.30.1/src/main.c | 1 + bsd_find/function.c | 11 ++-- ios_system.m | 113 +++++++++++++++++++++++++++++++-- shell_cmds/env/env.c | 1 + shell_cmds/printenv/printenv.c | 1 + 5 files changed, 116 insertions(+), 11 deletions(-) diff --git a/awk-23.30.1/src/main.c b/awk-23.30.1/src/main.c index 7236fc69..5e491ff8 100644 --- a/awk-23.30.1/src/main.c +++ b/awk-23.30.1/src/main.c @@ -39,6 +39,7 @@ const char *version = "version 20070501"; // #else #define COMPAT_MODE(func, mode) 1 // #endif +#include <TargetConditionals.h> #include "ios_error.h" extern char **environ; diff --git a/bsd_find/function.c b/bsd_find/function.c index d4747238..d4cd725b 100644 --- a/bsd_find/function.c +++ b/bsd_find/function.c @@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$"); #include <ctype.h> #include "find.h" +#include <TargetConditionals.h> #include "ios_error.h" @@ -614,6 +615,10 @@ c_empty(OPTION *option, char ***argvp __unused) * The primary -ok differs from -exec in that it requests affirmation * of the user before executing the utility. */ +// iOS addition: to reset the directory before execution of each command. +// Not sure this is necessary anymore. +extern int ios_fchdir_nolock(const int fd); + int f_exec(PLAN *plan, FTSENT *entry) { @@ -660,8 +665,6 @@ doexec: if ((plan->flags & F_NEEDOK) && !queryuser(plan->e_argv)) fflush(stdout); fflush(stderr); - char* pushDirectory = NULL; - pushDirectory = getcwd(pushDirectory, MAXPATHLEN); switch (pid = fork()) { case -1: err(1, "fork"); @@ -670,7 +673,7 @@ doexec: if ((plan->flags & F_NEEDOK) && !queryuser(plan->e_argv)) // case 0: { /* change dir back from where we started */ if (!(plan->flags & F_EXECDIR) && - !(ftsoptions & FTS_NOCHDIR) && fchdir(dotfd)) { + !(ftsoptions & FTS_NOCHDIR) && ios_fchdir_nolock(dotfd)) { warn("chdir"); _exit(1); } @@ -680,8 +683,6 @@ doexec: if ((plan->flags & F_NEEDOK) && !queryuser(plan->e_argv)) } } pid = waitpid(pid, &status, 0); - chdir(pushDirectory); - free(pushDirectory); if (plan->flags & F_EXECPLUS) { while (--plan->e_ppos >= plan->e_pbnum) free(plan->e_argv[plan->e_ppos]); diff --git a/ios_system.m b/ios_system.m index d6f725a0..5a65949e 100644 --- a/ios_system.m +++ b/ios_system.m @@ -592,7 +592,7 @@ void initializeEnvironment() { NSRange rSub = NSMakeRange(r1.location + r1.length, r2.location - r1.location - r1.length); NSString *variable_string = [argumentString substringWithRange:rSub]; - const char* variable = getenv([variable_string UTF8String]); + const char* variable = ios_getenv([variable_string UTF8String]); if (variable) { // Okay, so this one exists. NSString* replacement_string = [NSString stringWithCString:variable encoding:NSUTF8StringEncoding]; @@ -847,7 +847,7 @@ void __cd_to_dir(NSString *newDir, NSFileManager *fileManager) { } } -// For some Unix commands that call fchdir (including vim: +// For some Unix commands that call fchdir (including vim): #undef fchdir int ios_fchdir(const int fd) { NSLog(@"Locking for thread %x in ios_fchdir\n", pthread_self()); @@ -892,6 +892,38 @@ int ios_fchdir(const int fd) { return -1; } +int ios_fchdir_nolock(const int fd) { + // Same function as fchdir, except it does not lock. To be called when resetting directory after fork(). + while (cleanup_counter > 0) { } // Don't chdir while a command is ending. + int result = fchdir(fd); + if (result < 0) { + return result; + } + // We managed to change the directory. Update currentSession as well: + // Was that allowed? + // Allowed "cd" = below miniRoot *or* below localMiniRoot + NSFileManager *fileManager = [[NSFileManager alloc] init]; + NSString* resultDir = [fileManager currentDirectoryPath]; + + if (__allowed_cd_to_path(resultDir)) { + strcpy(currentSession->previousDirectory, currentSession->currentDir); + strcpy(currentSession->currentDir, [resultDir UTF8String]); + errno = 0; + return 0; + } + + errno = EACCES; // Permission denied + // If the user tried to go above the miniRoot, set it to miniRoot + if ([miniRoot hasPrefix:resultDir]) { + [fileManager changeCurrentDirectoryPath:miniRoot]; + strcpy(currentSession->currentDir, [miniRoot UTF8String]); + strcpy(currentSession->previousDirectory, currentSession->currentDir); + } else { + // go back to where we were before: + [fileManager changeCurrentDirectoryPath:[NSString stringWithCString:currentSession->currentDir encoding:NSUTF8StringEncoding]]; + } + return -1; +} int chdir_nolock(const char* path) { // 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) { // Anything after "sh" that contains an equal sign must be an environment variable. Pass it to ios_setenv. while (command[0] != NULL) { char* position = strstrquoted(command[0],"="); - char* firstSpace = strstrquoted(command[0]," "); if (position == NULL) { break; } + char* firstSpace = strstrquoted(command[0]," "); if (firstSpace < position) { break; } + firstSpace = strstrquoted(position," "); + if (firstSpace != NULL) { *firstSpace = 0; } *position = 0; ios_setenv(command[0], position+1, 1); - command++; + if (firstSpace != NULL) { + command[0] = firstSpace + 1; + } + else { command++; } } if (command[0] == NULL) { argv[0][0] = 'h'; // prevent termination in cleanup_function @@ -2185,6 +2222,21 @@ int ios_system(const char* inputCmd) { } } else command = cmd; // fprintf(thread_stderr, "Command sent: %s \n", command); + // Environment variables before alias expansion: + char* commandForParsing = strdup(command); + char* commandForParsingFree = commandForParsing; + char* firstSpace = strstrquoted(commandForParsing, " "); + while (firstSpace != NULL) { + *firstSpace = 0; + char* equalSign = strchr(commandForParsing, '='); + if (equalSign == NULL) break; + *equalSign = 0; + ios_setenv(commandForParsing, equalSign+1, 1); + command += (firstSpace - commandForParsing) + 1; + commandForParsing = firstSpace + 1; + firstSpace = strstrquoted(commandForParsing, " "); + } + free(commandForParsingFree); // alias expansion *before* input, output and error redirection. if ((command[0] != '\\') && (aliasDictionary != nil)) { // \command = cancel aliasing, get the original command @@ -2728,8 +2780,6 @@ int ios_system(const char* inputCmd) { NSString* commandName = [NSString stringWithCString:argv[0] encoding:NSUTF8StringEncoding]; // hasPrefix covers python, python3, python3.9. if ([commandName hasPrefix: @"python"]) { - // Tell Python that we are running Python3. - setenv("PYTHONEXECUTABLE", "python3", 1); // Ability to start multiple python3 scripts (required for Jupyter notebooks): // start by increasing the number of the interpreter, until we're out. int numInterpreter = 0; @@ -2745,6 +2795,8 @@ int ios_system(const char* inputCmd) { display_alert(@"Too many Python scripts", @"There are too many Python interpreters running at the same time. Try closing some of them."); NSLog(@"%@", @"Too many python scripts running simultaneously. Try closing some notebooks.\n"); commandName = @"notAValidCommand"; + } else { + currentPythonInterpreter = numInterpreter; } } if ((numInterpreter == 0) && (strlen(argv[0]) > 7)) { @@ -2986,6 +3038,7 @@ int ios_system(const char* inputCmd) { NSString * result = [pathNormalizeArray([path pathComponents], !isAbsolute) componentsJoinedByString: @"/"]; if (!result.length && !isAbsolute) { + // Same function as chdir, except it does not lock. To be called from ios_releaseThread*() result = @"."; } @@ -3018,3 +3071,51 @@ int ios_system(const char* inputCmd) { return pathNormalize(path); } + +// +char* ios_getPythonLibraryName() { + // Ability to start multiple python3 scripts, expanded for commands that start python3 as a dynamic library. + // (mostly vim, right now) + // start by increasing the number of the interpreter, until we're out. + int numInterpreter = 0; + if (currentPythonInterpreter < numPythonInterpreters) { + numInterpreter = currentPythonInterpreter; + currentPythonInterpreter++; + } else { + while (numInterpreter < numPythonInterpreters) { + if (PythonIsRunning[numInterpreter] == false) break; + numInterpreter++; + } + if (numInterpreter >= numPythonInterpreters) { + // NSLog(@"ios_getPythonLibraryName: returning NULL\n"); + return NULL; + } else { + currentPythonInterpreter = numInterpreter; + } + } + char* libraryName = NULL; + if ((numInterpreter >= 0) && (numInterpreter < numPythonInterpreters)) { + PythonIsRunning[numInterpreter] = true; + if (numInterpreter > 0) { + libraryName = strdup("pythonA"); + libraryName[6] = 'A' + (numInterpreter - 1); + } else { + libraryName = strdup("python3_ios"); + } + // NSLog(@"ios_getPythonLibraryName: returning %s\n", libraryName); + return libraryName; + } + // NSLog(@"ios_getPythonLibraryName: returning NULL\n"); + return NULL; +} + +void ios_releasePythonLibraryName(char* name) { + char libNumber = name[6]; + if (libNumber == '3') PythonIsRunning[0] = false; + else { + libNumber -= 'A' - 1; + if ((libNumber > 0) && (libNumber < MaxPythonInterpreters)) + PythonIsRunning[libNumber] = false; + } + free(name); +} diff --git a/shell_cmds/env/env.c b/shell_cmds/env/env.c index 549e7b68..392cc374 100644 --- a/shell_cmds/env/env.c +++ b/shell_cmds/env/env.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include <unistd.h> #include "envopts.h" +#include <TargetConditionals.h> #include "ios_error.h" extern char **environ; diff --git a/shell_cmds/printenv/printenv.c b/shell_cmds/printenv/printenv.c index 8b597fd9..951d9fbd 100644 --- a/shell_cmds/printenv/printenv.c +++ b/shell_cmds/printenv/printenv.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <string.h> #include <unistd.h> +#include <TargetConditionals.h> #include "ios_error.h" static void usage(void);