diff --git a/ios_error.h b/ios_error.h index 68f1ce29..aeb38973 100644 --- a/ios_error.h +++ b/ios_error.h @@ -17,6 +17,7 @@ extern "C" { #include #include #include +#include /* #define errx compileError #define err compileError @@ -67,6 +68,7 @@ extern __thread FILE* thread_stderr; #define unsetenv ios_unsetenv #define putenv ios_putenv #define fchdir ios_fchdir +#define signal ios_signal extern int ios_executable(const char* cmd); // is this command part of the "shell" commands? extern int ios_system(const char* inputCmd); // execute this command (executable file or builtin command) @@ -95,7 +97,10 @@ extern int ios_getCommandStatus(void); extern const char* ios_progname(void); extern pid_t ios_fork(void); extern void ios_waitpid(pid_t pid); -extern void ios_signal(int signal); +// Catch signal definition: +extern int canSetSignal(void); +extern sig_t ios_signal(int signal, sig_t function); + extern int ios_fchdir(const int fd); extern ssize_t ios_write(int fildes, const void *buf, size_t nbyte); @@ -105,6 +110,7 @@ extern int ios_fputs(const char* s, FILE *stream); extern int ios_fputc(int c, FILE *stream); extern int ios_putw(int w, FILE *stream); extern int ios_fflush(FILE *stream); +extern int ios_getstdin(void); extern int ios_gettty(void); extern int ios_opentty(void); extern void ios_closetty(void); diff --git a/ios_system.m b/ios_system.m index b658411f..1cd2e9fd 100644 --- a/ios_system.m +++ b/ios_system.m @@ -79,7 +79,7 @@ FILE* stdout; FILE* stderr; FILE* tty; - void* context; + const void* context; int global_errno; int numCommandsAllocated; int numCommand; @@ -167,7 +167,7 @@ void ios_setBookmarkDictionaryName(NSString* name) { // pointer to sessionParameters. thread-local variable so the entire system is thread-safe. // The sessionParameters pointer is shared by all threads in the same session. -static __thread sessionParameters* currentSession; +static __thread sessionParameters* currentSession = NULL; // Python3 multiple interpreters: // limit to 6 = 1 kernel, 4 notebooks, one extra. static const int MaxPythonInterpreters = 6; // const so we can allocate an array @@ -231,20 +231,25 @@ void _exit(int n) { } // -void ios_signal(int signal) { - // This function is probably obsolete now. If we keep using it, remember that currentSession is not necessarily the currentSession - // (if currentSession started sh_session, then we might be sending the signal to the wrong session). - // Signals the threads of the current session: - if (currentSession != NULL) { - if (currentSession->current_command_root_thread != NULL) { - pthread_kill(currentSession->current_command_root_thread, signal); - } - if (currentSession->lastThreadId != NULL) { - pthread_kill(currentSession->lastThreadId, signal); - } - if (currentSession->mainThreadId != NULL) { - pthread_kill(currentSession->mainThreadId, signal); - } +int canSetSignal() { + if (currentSession == NULL) { + return 1; + } + char* sessionId = (char*)currentSession->context; + if (strcmp(sessionId, "inExtension") == 0) { + return 0; + } + return 1; +} + +#undef signal +sig_t ios_signal(int value, sig_t function) { + // intercept calls to signal, prevent signal from doing anything when running in-extension. + // So that an in-extension command cannot break the signal handling from an in-app command. + if (canSetSignal()) { + return signal(value, function); + } else { + return NULL; } } @@ -290,6 +295,7 @@ void ios_setWindowSize(int width, int height, const void* sessionId) { } extern char* libc_getenv(const char* variableName); +static char randomValue[6]; char * ios_getenv(const char *name) { // intercept calls to getenv("COLUMNS") / getenv("LINES") if (strcmp(name, "COLUMNS") == 0) { @@ -304,6 +310,10 @@ void ios_setWindowSize(int width, int height, const void* sessionId) { if (strcmp(name, "PWD") == 0) { return currentSession->currentDir; } + if (strcmp(name, "RANDOM") == 0) { + sprintf(randomValue, "%d", random()&0x7FFF); + return randomValue; + } return libc_getenv(name); } @@ -490,16 +500,23 @@ static void cleanup_function(void* parameters) { } } if (mustCloseStdout) { + int fd = fileno(p->stdout); NSLog(@"Closing stdout (mustCloseStdout): %d \n", fileno(p->stdout)); int res = fclose(p->stdout); + // Add close(fd) as well? + NSLog(@"Result of closing stdout (mustCloseStdout): %d flag: %d\n", res, fcntl(fd, F_GETFD, 0)); } if (!isSh) { mustCloseStdin &= p->isPipeIn; if (currentSession != nil) { mustCloseStdin &= fileno(p->stdin) != fileno(currentSession->stdin); } - // we cannot close stdin for wasm commands: - mustCloseStdin &= !isWasm; + if (isWasm) { + // Don't close stdin for Wasm commands piped into others, but do it for files + char filePath[MAXPATHLEN]; + if (fcntl(fileno(p->stdin), F_GETPATH, filePath) < 0) + mustCloseStdin &= false; + } // commands started by Python: Python will close stdin (Lua and Perl? not broken, AFAIK) if ((currentSession->numCommand > 0) && (strncmp(currentSession->commandName[currentSession->numCommand - 1], "python", 6) == 0)) { // NSLog(@"Command started by Python, not closing stdin: %d \n", fileno(p->stdin)); @@ -537,7 +554,7 @@ static void cleanup_function(void* parameters) { currentSession->mainThreadId = 0; } cleanup_counter--; - NSLog(@"returning from cleanup_function\n"); + NSLog(@"returning from cleanup_function, session: %s\n", (char*)currentSession->context); } // Avoir calling crash_handler several times: @@ -666,6 +683,7 @@ void initializeEnvironment(void) { // XDG setup directories (~/Library/Caches, ~/Library/Preferences): setenv("XDG_CACHE_HOME", [libPath stringByAppendingPathComponent:@"Caches"].UTF8String, 0); setenv("XDG_CONFIG_HOME", [libPath stringByAppendingPathComponent:@"Preferences"].UTF8String, 0); + setenv("XDG_STATE_HOME", libPath.UTF8String, 0); setenv("XDG_DATA_HOME", libPath.UTF8String, 0); // if we use Python, we define a few more environment variables: setenv("PYTHONEXECUTABLE", "python3", 0); // Python executable name for python3 @@ -1363,7 +1381,7 @@ int ios_executable(const char* inputCmd) { static __thread FILE* child_stderr = NULL; FILE* ios_popen(const char* inputCmd, const char* type) { - // NSLog(@"ios_popen: %s mode %s", inputCmd, type); + NSLog(@"ios_popen: %s mode %s", inputCmd, type); // Save existing streams: int fd[2] = {0}; const char* command = inputCmd; @@ -1978,6 +1996,13 @@ int ios_execve(const char *path, char* const argv[], char* envp[]) { [dictionary addObject:variable]; i++; } + // Add our own variables: ROWS, PWD (COLUMNS and LINES are already set): + NSString* rowVariable = @"ROWS="; + rowVariable = [rowVariable stringByAppendingString: [NSString stringWithCString: currentSession->columns]]; + [dictionary addObject: rowVariable]; + NSString* pwdVariable = @"PWD="; + pwdVariable = [pwdVariable stringByAppendingString: [NSString stringWithCString: currentSession->currentDir]]; + [dictionary addObject: pwdVariable]; return [dictionary copy]; } @@ -2116,6 +2141,7 @@ int ios_killpid(pid_t pid, int sig) { void ios_switchSession(const void* sessionId) { char* sessionName = (char*) sessionId; + // NSLog(@"Switching to session: %s\n", sessionName); if ((currentSession != nil) && (parentSession != nil)) { if ((currentSession->context == sh_session) && (parentSession->context == sessionName)) { // If we are running a sh_session inside the requested sessionId, there is no need to change: @@ -2209,6 +2235,12 @@ int ios_gettty(void) { return fileno(currentSession->tty); } +int ios_getstdin(void) { + if (currentSession == NULL) return -1; + if (currentSession->stdin == NULL) return -1; + return fileno(currentSession->stdin); +} + // Allows commands that are not usually tty-based to get the tty (for password input in ssh/scp/sftp): int ios_opentty(void) { if (currentSession == nil) { return -1; } @@ -2291,19 +2323,19 @@ static int isInteractive(const char* command) { void ios_setContext(const void *context) { if (currentSession == NULL) return; + // NSLog(@"Setting session context to: %s\n", (char*)context); currentSession->context = context; } -void* ios_getContext(void) { +const void* ios_getContext(void) { if (currentSession == NULL) return NULL; + // NSLog(@"getting session context, %x currentSession->context: %s\n", currentSession, (char*)currentSession->context); if (currentSession->context != sh_session) return currentSession->context; else return parentSession->context; } - - // For customization: // replaces a function (e.g. ls_main) with another one, provided by the user (ls_mine_main) // if the function does not exist, add it to the list @@ -2316,7 +2348,7 @@ void replaceCommand(NSString* commandName, NSString* functionName, bool allOccur int (*function)(int ac, char** av) = NULL; function = dlsym(RTLD_MAIN_ONLY, functionName.UTF8String); if (!function) { - NSLog(@"replaceCommand: %@ does not exist", functionName); + NSLog(@"replaceCommand: %@ (%s) does not exist", functionName, functionName.UTF8String); return; // if not, we don't replace. } if (commandList == nil) initializeCommandList(); @@ -2575,10 +2607,15 @@ static bool isBackgroundCommand(char* command) { if (![fileManager fileExistsAtPath:path isDirectory:&isDir]) continue; if (!isDir) continue; // same in the (unlikely) event the path component is not a directory NSString* locationName; - // search for 2 possibilities: name and name.wasm + // search for 3 possibilities: name, name.wasm3 and name.wasm locationName = [path stringByAppendingPathComponent:scriptName]; bool fileFound = [fileManager fileExistsAtPath:locationName isDirectory:&isDir]; fileFound = fileFound && !isDir; + if (!fileFound) { + locationName = [[path stringByAppendingPathComponent:scriptName] stringByAppendingString:@".wasm3"]; + fileFound = [fileManager fileExistsAtPath:locationName isDirectory:&isDir]; + fileFound = fileFound && !isDir; + } if (!fileFound) { locationName = [[path stringByAppendingPathComponent:scriptName] stringByAppendingString:@".wasm"]; fileFound = [fileManager fileExistsAtPath:locationName isDirectory:&isDir]; @@ -2617,9 +2654,8 @@ static bool isBackgroundCommand(char* command) { } - int ios_system(const char* inputCmd) { - NSLog(@"command= %s pid= %d\n", inputCmd, ios_currentPid()); + NSLog(@"command = %s pid= %d\n", inputCmd, ios_currentPid()); char* command; // The names of the files for stdin, stdout, stderr @@ -2695,6 +2731,16 @@ int ios_system(const char* inputCmd) { firstSpace = strstrquoted(commandForParsing, " "); } free(commandForParsingFree); + // Is the command an environment variable? + if (command[0] == '$') { + const char* newName = ios_getenv(command + 1); + if (newName != NULL) { + free(originalCommand); + originalCommand = strdup(newName); + cmd = originalCommand; + command = originalCommand; + } + } // alias expansion *before* input, output and error redirection. if ((command[0] != '\\') && (aliasDictionary != nil)) { // \command = cancel aliasing, get the original command @@ -2774,11 +2820,16 @@ int ios_system(const char* inputCmd) { if (!inputFileMarker) inputFileMarker = command; outputFileMarker = inputFileMarker; functionParameters *params = (functionParameters*) malloc(sizeof(functionParameters)); + if (params == NULL) { + NSLog(@"Unable to allocate params in ios_system"); + return -1; + } // If child_streams have been defined (in dup2 or popen), the new thread takes them. params->stdin = child_stdin; params->stdout = child_stdout; params->stderr = child_stderr; params->session = currentSession; + NSLog(@"After params creation, stdout %x stderr %x \n", params->stdout, params->stderr); params->backgroundCommand = isBackgroundCommand(command); params->numInterpreter = 0; @@ -2995,6 +3046,7 @@ int ios_system(const char* inputCmd) { if (params->stdin == NULL) params->stdin = thread_stdin; if (params->stdout == NULL) params->stdout = thread_stdout; if (params->stderr == NULL) params->stderr = thread_stderr; + NSLog(@"After files parsing, stdout %x stderr %x \n", params->stdout, params->stderr); int argc = 0; size_t numSpaces = 0; // the number of arguments is *at most* the number of spaces plus one @@ -3142,6 +3194,11 @@ int ios_system(const char* inputCmd) { fileFound = [fileManager fileExistsAtPath:locationName isDirectory:&isDir]; fileFound = fileFound && !isDir; } + if (!fileFound) { + locationName = [[path stringByAppendingPathComponent:commandName] stringByAppendingString:@".wasm3"]; + fileFound = [fileManager fileExistsAtPath:locationName isDirectory:&isDir]; + fileFound = fileFound && !isDir; + } if (!fileFound) { locationName = [[path stringByAppendingPathComponent:commandName] stringByAppendingString:@".wasm"]; fileFound = [fileManager fileExistsAtPath:locationName isDirectory:&isDir]; @@ -3178,6 +3235,17 @@ int ios_system(const char* inputCmd) { strcpy(argv[1], locationName.UTF8String); argv[0] = strdup("wasm"); // this argument is new break; + } else if ([locationName hasSuffix:@".wasm3"]) { + // insert wasm3 in front of argument list: + // wasm3 is a WebAssembly interpreter that is faster than wasm, but does not handle exceptions or setjmp. + argc += 1; + argv = (char **)realloc(argv, sizeof(char*) * (argc + 1)); + // Move everything one step up + for (int i = argc-1; i >= 1; i--) { argv[i] = argv[i-1]; } + argv[1] = realloc(argv[1], locationName.length + 1); + strcpy(argv[1], locationName.UTF8String); + argv[0] = strdup("wasm3"); // this argument is new + break; } else { if (isRealCommand(locationName.UTF8String)) { cmdIsReal = true; @@ -3287,7 +3355,9 @@ int ios_system(const char* inputCmd) { strcpy(argv[0], newName); } } - NSLog(@"After command parsing, stdout %d stderr %d \n", fileno(params->stdout), fileno(params->stderr)); + NSLog(@"After command parsing, stdout %x stderr %x \n", params->stdout, params->stderr); + // This line causes an error, and the previous one is not executed. Recompile. + // NSLog(@"After command parsing, stdout %d stderr %d \n", fileno(params->stdout), fileno(params->stderr)); // fprintf(thread_stderr, "Command after parsing: "); // for (int i = 0; i < argc; i++) // fprintf(thread_stderr, "[%s] ", argv[i]); @@ -3594,12 +3664,20 @@ int ios_system(const char* inputCmd) { // params->session = currentSession; // Before starting, do we have enough file descriptors available? int numFileDescriptorsOpen = 0; + bool debugPath = false; // to understand where the file descr was allocated for (int fd = 0; fd < limitFilesOpen.rlim_cur; fd++) { errno = 0; int flags = fcntl(fd, F_GETFD, 0); if (flags == -1 && errno) { continue; } + if (debugPath) { + char filePath[MAXPATHLEN]; + if (fcntl(fd, F_GETPATH, filePath) >= 0) + NSLog(@"Descriptor still open = %d path= %s\n", fd, filePath); + else + NSLog(@"Descriptor still open = %d (no path)\n", fd); + } ++numFileDescriptorsOpen ; } NSLog(@"\nNum file descriptors opened = %d limit= %llu\n", numFileDescriptorsOpen, limitFilesOpen.rlim_cur); @@ -3610,8 +3688,8 @@ int ios_system(const char* inputCmd) { int res = setrlimit(RLIMIT_NOFILE, &limitFilesOpen); // Check the result: getrlimit(RLIMIT_NOFILE, &limitFilesOpen); - if (res == 0) NSLog(@"[Info] Increased file descriptor limit to = %llu OPEN_MAX= %d\n", limitFilesOpen.rlim_cur, OPEN_MAX); - else NSLog(@"[Warning] Failed to increased file descriptor limit to = %llu\n", limitFilesOpen.rlim_cur); + if (res == 0) NSLog(@"[Info] Increased file descriptors limit to = %llu OPEN_MAX= %d\n", limitFilesOpen.rlim_cur, OPEN_MAX); + else NSLog(@"[Warning] Failed to increased file descriptors limit to = %llu\n", limitFilesOpen.rlim_cur); } NSLog(@"Starting command: %s, currentSession->isMainThread: %d", commandName.UTF8String, currentSession->isMainThread); if ([commandName isEqualToString:@"wasm"]) diff --git a/ios_system.xcodeproj/project.pbxproj b/ios_system.xcodeproj/project.pbxproj index c7ee3ec9..e78a5174 100644 --- a/ios_system.xcodeproj/project.pbxproj +++ b/ios_system.xcodeproj/project.pbxproj @@ -58,8 +58,8 @@ 222419DC2A90A6C7003AB5B7 /* sha256.c in Sources */ = {isa = PBXBuildFile; fileRef = 222419DB2A90A6C6003AB5B7 /* sha256.c */; }; 222419DE2A90A706003AB5B7 /* curl_range.c in Sources */ = {isa = PBXBuildFile; fileRef = 222419DD2A90A706003AB5B7 /* curl_range.c */; }; 222419E02A90A728003AB5B7 /* rename.c in Sources */ = {isa = PBXBuildFile; fileRef = 222419DF2A90A728003AB5B7 /* rename.c */; }; + 2224F2A32C22D94E00E0BA40 /* b64.c in Sources */ = {isa = PBXBuildFile; fileRef = 2224F2A22C22D94D00E0BA40 /* b64.c */; }; 222CC4DC218CBF2300D3A11C /* strnsubst.c in Sources */ = {isa = PBXBuildFile; fileRef = 222CC4DA218CBF2300D3A11C /* strnsubst.c */; }; - 222CC4DD218CBF2300D3A11C /* pathnames.h in Headers */ = {isa = PBXBuildFile; fileRef = 222CC4DB218CBF2300D3A11C /* pathnames.h */; }; 222CC4DF218CBF2900D3A11C /* xargs.c in Sources */ = {isa = PBXBuildFile; fileRef = 222CC4DE218CBF2900D3A11C /* xargs.c */; }; 22319FA01FDC2332004D875A /* getopt.c in Sources */ = {isa = PBXBuildFile; fileRef = 22319F9E1FDC2332004D875A /* getopt.c */; }; 22327A9F209E3ADD0026B98C /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 22327A9E209E3ADD0026B98C /* md5.c */; }; @@ -450,6 +450,22 @@ 2254792D2B73814B005041FF /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = D28514A525B20351003405B4 /* config.h */; }; 225782911FDB4D390050F312 /* curl_config.h in Headers */ = {isa = PBXBuildFile; fileRef = 2257811A1FDB4D380050F312 /* curl_config.h */; }; 225E1B6F2067F39F005AC151 /* tar.h in Headers */ = {isa = PBXBuildFile; fileRef = 225E1B6D2067F39F005AC151 /* tar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 225E4F152C56989C00D5E1A9 /* wasm3.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F142C56989C00D5E1A9 /* wasm3.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI -Iwasm3/source"; }; }; + 225E4F252C569AB400D5E1A9 /* m3_compile.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F162C569AB200D5E1A9 /* m3_compile.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F262C569AB400D5E1A9 /* m3_parse.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F172C569AB200D5E1A9 /* m3_parse.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F272C569AB400D5E1A9 /* m3_api_tracer.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F182C569AB200D5E1A9 /* m3_api_tracer.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F282C569AB400D5E1A9 /* m3_exec.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F192C569AB300D5E1A9 /* m3_exec.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F292C569AB400D5E1A9 /* m3_bind.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F1A2C569AB300D5E1A9 /* m3_bind.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F2A2C569AB400D5E1A9 /* m3_info.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F1B2C569AB300D5E1A9 /* m3_info.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F2B2C569AB400D5E1A9 /* m3_function.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F1C2C569AB300D5E1A9 /* m3_function.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F2C2C569AB400D5E1A9 /* m3_module.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F1D2C569AB300D5E1A9 /* m3_module.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F2D2C569AB400D5E1A9 /* m3_code.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F1E2C569AB300D5E1A9 /* m3_code.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F2E2C569AB400D5E1A9 /* m3_env.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F1F2C569AB300D5E1A9 /* m3_env.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F2F2C569AB400D5E1A9 /* m3_core.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F202C569AB300D5E1A9 /* m3_core.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F302C569AB400D5E1A9 /* m3_api_wasi.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F212C569AB300D5E1A9 /* m3_api_wasi.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F312C569AB400D5E1A9 /* m3_api_meta_wasi.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F222C569AB400D5E1A9 /* m3_api_meta_wasi.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F322C569AB400D5E1A9 /* m3_api_uvwasi.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F232C569AB400D5E1A9 /* m3_api_uvwasi.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; + 225E4F332C569AB400D5E1A9 /* m3_api_libc.c in Sources */ = {isa = PBXBuildFile; fileRef = 225E4F242C569AB400D5E1A9 /* m3_api_libc.c */; settings = {COMPILER_FLAGS = "-Dd_m3HasWASI"; }; }; 225F06102016751900466685 /* getopt_long.c in Sources */ = {isa = PBXBuildFile; fileRef = 225F060F2016751800466685 /* getopt_long.c */; }; 2261379421F0E59E0097B3A0 /* explicit_bzero.c in Sources */ = {isa = PBXBuildFile; fileRef = 2261379221F0E59D0097B3A0 /* explicit_bzero.c */; }; 2261379621F0E5C40097B3A0 /* bsd-setres_id.c in Sources */ = {isa = PBXBuildFile; fileRef = 2261379521F0E5C40097B3A0 /* bsd-setres_id.c */; }; @@ -932,6 +948,7 @@ 222419DB2A90A6C6003AB5B7 /* sha256.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sha256.c; sourceTree = ""; }; 222419DD2A90A706003AB5B7 /* curl_range.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = curl_range.c; sourceTree = ""; }; 222419DF2A90A728003AB5B7 /* rename.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rename.c; sourceTree = ""; }; + 2224F2A22C22D94D00E0BA40 /* b64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = b64.c; path = file_cmds/base64/b64.c; sourceTree = SOURCE_ROOT; }; 222CC4DA218CBF2300D3A11C /* strnsubst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = strnsubst.c; path = shell_cmds/xargs/strnsubst.c; sourceTree = SOURCE_ROOT; }; 222CC4DB218CBF2300D3A11C /* pathnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pathnames.h; path = shell_cmds/xargs/pathnames.h; sourceTree = SOURCE_ROOT; }; 222CC4DE218CBF2900D3A11C /* xargs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = xargs.c; path = shell_cmds/xargs/xargs.c; sourceTree = SOURCE_ROOT; }; @@ -1283,6 +1300,22 @@ 225E1B6B2067F39F005AC151 /* tar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = tar.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 225E1B6D2067F39F005AC151 /* tar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tar.h; sourceTree = ""; }; 225E1B6E2067F39F005AC151 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 225E4F142C56989C00D5E1A9 /* wasm3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wasm3.c; sourceTree = ""; }; + 225E4F162C569AB200D5E1A9 /* m3_compile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_compile.c; path = wasm3/source/m3_compile.c; sourceTree = SOURCE_ROOT; }; + 225E4F172C569AB200D5E1A9 /* m3_parse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_parse.c; path = wasm3/source/m3_parse.c; sourceTree = SOURCE_ROOT; }; + 225E4F182C569AB200D5E1A9 /* m3_api_tracer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_api_tracer.c; path = wasm3/source/m3_api_tracer.c; sourceTree = SOURCE_ROOT; }; + 225E4F192C569AB300D5E1A9 /* m3_exec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_exec.c; path = wasm3/source/m3_exec.c; sourceTree = SOURCE_ROOT; }; + 225E4F1A2C569AB300D5E1A9 /* m3_bind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_bind.c; path = wasm3/source/m3_bind.c; sourceTree = SOURCE_ROOT; }; + 225E4F1B2C569AB300D5E1A9 /* m3_info.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_info.c; path = wasm3/source/m3_info.c; sourceTree = SOURCE_ROOT; }; + 225E4F1C2C569AB300D5E1A9 /* m3_function.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_function.c; path = wasm3/source/m3_function.c; sourceTree = SOURCE_ROOT; }; + 225E4F1D2C569AB300D5E1A9 /* m3_module.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_module.c; path = wasm3/source/m3_module.c; sourceTree = SOURCE_ROOT; }; + 225E4F1E2C569AB300D5E1A9 /* m3_code.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_code.c; path = wasm3/source/m3_code.c; sourceTree = SOURCE_ROOT; }; + 225E4F1F2C569AB300D5E1A9 /* m3_env.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_env.c; path = wasm3/source/m3_env.c; sourceTree = SOURCE_ROOT; }; + 225E4F202C569AB300D5E1A9 /* m3_core.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_core.c; path = wasm3/source/m3_core.c; sourceTree = SOURCE_ROOT; }; + 225E4F212C569AB300D5E1A9 /* m3_api_wasi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_api_wasi.c; path = wasm3/source/m3_api_wasi.c; sourceTree = SOURCE_ROOT; }; + 225E4F222C569AB400D5E1A9 /* m3_api_meta_wasi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_api_meta_wasi.c; path = wasm3/source/m3_api_meta_wasi.c; sourceTree = SOURCE_ROOT; }; + 225E4F232C569AB400D5E1A9 /* m3_api_uvwasi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_api_uvwasi.c; path = wasm3/source/m3_api_uvwasi.c; sourceTree = SOURCE_ROOT; }; + 225E4F242C569AB400D5E1A9 /* m3_api_libc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m3_api_libc.c; path = wasm3/source/m3_api_libc.c; sourceTree = SOURCE_ROOT; }; 225F060A20163C2000466685 /* tee.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tee.c; path = shell_cmds/tee/tee.c; sourceTree = SOURCE_ROOT; }; 225F060F2016751800466685 /* getopt_long.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = getopt_long.c; sourceTree = ""; }; 225F061120171B4300466685 /* ssh_main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ssh_main.c; sourceTree = ""; }; @@ -1508,8 +1541,8 @@ 22F6A16920683D5200E618F9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 22F6A1AF20683F4100E618F9 /* curl_ios.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = curl_ios.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 22F6A1B220683F4100E618F9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../curl_ios/Info.plist; sourceTree = ""; }; - D212F98A25B066E9007F5D2D /* libssh2.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = libssh2.xcframework; path = xcfs/.build/artifacts/xcfs/libssh2.xcframework; sourceTree = ""; }; - D212F99525B06810007F5D2D /* openssl.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = openssl.xcframework; path = xcfs/.build/artifacts/xcfs/openssl.xcframework; sourceTree = ""; }; + D212F98A25B066E9007F5D2D /* libssh2.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = libssh2.xcframework; path = xcfs/.build/artifacts/xcfs/libssh2/libssh2.xcframework; sourceTree = ""; }; + D212F99525B06810007F5D2D /* openssl.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = openssl.xcframework; path = xcfs/.build/artifacts/xcfs/openssl/openssl.xcframework; sourceTree = ""; }; D285143125B1D7CD003405B4 /* sshkey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sshkey.h; path = ssh_keygen/sshkey.h; sourceTree = ""; }; D285144325B1DE19003405B4 /* cipher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cipher.h; path = ssh_keygen/cipher.h; sourceTree = ""; }; D285145525B1DE61003405B4 /* ssherr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ssherr.h; path = ssh_keygen/ssherr.h; sourceTree = ""; }; @@ -1640,6 +1673,14 @@ name = vquic; sourceTree = ""; }; + 2224F2A12C22D93000E0BA40 /* base64 */ = { + isa = PBXGroup; + children = ( + 2224F2A22C22D94D00E0BA40 /* b64.c */, + ); + name = base64; + sourceTree = ""; + }; 222CC4D9218CBEED00D3A11C /* xarg */ = { isa = PBXGroup; children = ( @@ -2221,6 +2262,29 @@ path = tar; sourceTree = ""; }; + 225E4F132C56986F00D5E1A9 /* wasm3 */ = { + isa = PBXGroup; + children = ( + 225E4F142C56989C00D5E1A9 /* wasm3.c */, + 225E4F242C569AB400D5E1A9 /* m3_api_libc.c */, + 225E4F222C569AB400D5E1A9 /* m3_api_meta_wasi.c */, + 225E4F182C569AB200D5E1A9 /* m3_api_tracer.c */, + 225E4F232C569AB400D5E1A9 /* m3_api_uvwasi.c */, + 225E4F212C569AB300D5E1A9 /* m3_api_wasi.c */, + 225E4F1A2C569AB300D5E1A9 /* m3_bind.c */, + 225E4F1E2C569AB300D5E1A9 /* m3_code.c */, + 225E4F162C569AB200D5E1A9 /* m3_compile.c */, + 225E4F202C569AB300D5E1A9 /* m3_core.c */, + 225E4F1F2C569AB300D5E1A9 /* m3_env.c */, + 225E4F192C569AB300D5E1A9 /* m3_exec.c */, + 225E4F1C2C569AB300D5E1A9 /* m3_function.c */, + 225E4F1B2C569AB300D5E1A9 /* m3_info.c */, + 225E4F1D2C569AB300D5E1A9 /* m3_module.c */, + 225E4F172C569AB200D5E1A9 /* m3_parse.c */, + ); + name = wasm3; + sourceTree = ""; + }; 225F060920163BFC00466685 /* tee */ = { isa = PBXGroup; children = ( @@ -2232,6 +2296,7 @@ 226378091FDB3EC700AE8827 /* file_cmds_ios */ = { isa = PBXGroup; children = ( + 2224F2A12C22D93000E0BA40 /* base64 */, 226AAB4D2491329700492AFD /* less */, 226378411FDB3EE300AE8827 /* humanize_number.c */, 2263781D1FDB3EE200AE8827 /* ncurses_dll.h */, @@ -2433,6 +2498,7 @@ 226378CA1FDB3F2B00AE8827 /* shell_cmds_ios */ = { isa = PBXGroup; children = ( + 225E4F132C56986F00D5E1A9 /* wasm3 */, 2276339E29B0A5DE00DBF1C6 /* stty */, 22F0803620973712003C3BF0 /* sleep.c */, 221CD98D21E8B03D00F3B47C /* open.m */, @@ -2950,7 +3016,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 222CC4DD218CBF2300D3A11C /* pathnames.h in Headers */, 22B753052068DF8400F2B025 /* shell.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3261,6 +3326,7 @@ hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 223496A11FD5FC71007ED1A9; packageReferences = ( @@ -3816,6 +3882,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2224F2A32C22D94E00E0BA40 /* b64.c in Sources */, 226AAB5F249135D900492AFD /* edit.c in Sources */, 226AAB782491360D00492AFD /* optfunc.c in Sources */, 226AAB922491363800492AFD /* ttyin.c in Sources */, @@ -3888,24 +3955,33 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 225E4F302C569AB400D5E1A9 /* m3_api_wasi.c in Sources */, 22C505872098ADD800FDDFA9 /* ls.c in Sources */, 227633AC29B0A61B00DBF1C6 /* util.c in Sources */, 222CC4DC218CBF2300D3A11C /* strnsubst.c in Sources */, 22F6A11E2068395B00E618F9 /* fmt.c in Sources */, + 225E4F292C569AB400D5E1A9 /* m3_bind.c in Sources */, 22F6A1212068395B00E618F9 /* w.c in Sources */, 227633A229B0A60500DBF1C6 /* gfmt.c in Sources */, 227633A829B0A60E00DBF1C6 /* print.c in Sources */, 22C505882098ADD800FDDFA9 /* misc.c in Sources */, + 225E4F2C2C569AB400D5E1A9 /* m3_module.c in Sources */, + 225E4F282C569AB400D5E1A9 /* m3_exec.c in Sources */, + 225E4F332C569AB400D5E1A9 /* m3_api_libc.c in Sources */, 227633A729B0A60E00DBF1C6 /* key.c in Sources */, + 225E4F2E2C569AB400D5E1A9 /* m3_env.c in Sources */, + 225E4F2B2C569AB400D5E1A9 /* m3_function.c in Sources */, 227633A029B0A5FE00DBF1C6 /* cchar.c in Sources */, 22F6A11A2068394B00E618F9 /* id.c in Sources */, 22D0BD3E297A7CE2006907FC /* jsc.swift in Sources */, 22C5058A2098ADD800FDDFA9 /* function.c in Sources */, 22F6A11F2068395B00E618F9 /* pr_time.c in Sources */, 22C5058B2098ADD800FDDFA9 /* operator.c in Sources */, + 225E4F152C56989C00D5E1A9 /* wasm3.c in Sources */, 224DF7532B7956FF00F13C58 /* basename.c in Sources */, 22C5058C2098ADD800FDDFA9 /* main.c in Sources */, 22F6A1202068395B00E618F9 /* proc_compare.c in Sources */, + 225E4F252C569AB400D5E1A9 /* m3_compile.c in Sources */, 224DF7512B7945E600F13C58 /* dirname.c in Sources */, 22F6A11B2068394E00E618F9 /* printenv.c in Sources */, 224B48F4279491FE00D310A8 /* source.swift in Sources */, @@ -3913,17 +3989,24 @@ 22F6A11C2068395200E618F9 /* pwd.c in Sources */, 227633A629B0A60E00DBF1C6 /* modes.c in Sources */, 22C505862098ADD800FDDFA9 /* find.c in Sources */, + 225E4F262C569AB400D5E1A9 /* m3_parse.c in Sources */, 227633AA29B0A61500DBF1C6 /* stty.c in Sources */, + 225E4F2F2C569AB400D5E1A9 /* m3_core.c in Sources */, + 225E4F2A2C569AB400D5E1A9 /* m3_info.c in Sources */, + 225E4F312C569AB400D5E1A9 /* m3_api_meta_wasi.c in Sources */, 22F6A1172068394200E618F9 /* vary.c in Sources */, 22C505852098ADD800FDDFA9 /* y.tab.c in Sources */, + 225E4F2D2C569AB400D5E1A9 /* m3_code.c in Sources */, 22F6A1182068394700E618F9 /* env.c in Sources */, 22F6A1162068394200E618F9 /* date.c in Sources */, + 225E4F272C569AB400D5E1A9 /* m3_api_tracer.c in Sources */, 22F6A1142068393900E618F9 /* tee.c in Sources */, 22D99CC325AB5C83007F56C9 /* sleep.c in Sources */, 22F6A11D2068395600E618F9 /* uname.c in Sources */, 222CC4DF218CBF2900D3A11C /* xargs.c in Sources */, 22F6A1192068394700E618F9 /* envopts.c in Sources */, 22C505892098ADD800FDDFA9 /* option.c in Sources */, + 225E4F322C569AB400D5E1A9 /* m3_api_uvwasi.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4984,6 +5067,10 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); INFOPLIST_FILE = shell/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -4993,6 +5080,12 @@ "@loader_path/Frameworks", ); ONLY_ACTIVE_ARCH = NO; + OTHER_CFLAGS = ( + "-Wshorten-64-to-32", + "-Wno-ambiguous-macro", + "-Wunused-const-variable", + "-Wincompatible-pointer-types-discards-qualifiers", + ); OTHER_LDFLAGS = ( "-Xlinker", "-no_fixup_chains", @@ -5025,6 +5118,10 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); INFOPLIST_FILE = shell/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 14.0; @@ -5033,6 +5130,12 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); + OTHER_CFLAGS = ( + "-Wshorten-64-to-32", + "-Wno-ambiguous-macro", + "-Wunused-const-variable", + "-Wincompatible-pointer-types-discards-qualifiers", + ); OTHER_LDFLAGS = ( "-Xlinker", "-no_fixup_chains", diff --git a/ios_system/ios_system.h b/ios_system/ios_system.h index cd5317fd..4140ce48 100644 --- a/ios_system/ios_system.h +++ b/ios_system/ios_system.h @@ -58,7 +58,6 @@ extern NSArray* environmentAsArray(void); extern void storeEnvironment(char* envp[]); extern pid_t ios_fork(void); extern void ios_waitpid(pid_t pid); -extern void ios_signal(int signal); extern NSString *ios_getLogicalPWD(const void* sessionId); void ios_setWindowSize(int width, int height, const void* sessionId); @@ -76,10 +75,11 @@ extern void ios_switchSession(const void* sessionid); extern void ios_closeSession(const void* sessionid); extern void ios_setStreams(FILE* _stdin, FILE* _stdout, FILE* _stderr); extern void ios_settty(FILE* _tty); +extern int ios_getstdin(void); extern int ios_gettty(void); extern int ios_activePager(void); extern void ios_setContext(const void *context); -extern void* ios_getContext(void); +extern const void* ios_getContext(void); extern void ios_setDirectoryURL(NSURL* workingDirectoryURL); extern void newPreviousDirectory(void); extern void makeGlobal(void); diff --git a/libc_replacement.c b/libc_replacement.c index 5681adbd..c98a7daf 100644 --- a/libc_replacement.c +++ b/libc_replacement.c @@ -72,6 +72,8 @@ int printf (const char *format, ...) { return done; } + +// #define debugPrint int fprintf(FILE * restrict stream, const char * restrict format, ...) { va_list arg; int done; @@ -80,9 +82,12 @@ int fprintf(FILE * restrict stream, const char * restrict format, ...) { va_start (arg, format); if (fileno(stream) == STDOUT_FILENO) done = vfprintf (thread_stdout, format, arg); +#ifndef debugPrint else if (fileno(stream) == STDERR_FILENO) done = vfprintf (thread_stderr, format, arg); // iOS, debug: - // else if ((fileno(stream) == STDERR_FILENO) || (fileno(stream) == fileno(thread_stderr))) done = vfprintf (stderr, format, arg); +#else + else if ((fileno(stream) == STDERR_FILENO) || (fileno(stream) == fileno(thread_stderr))) done = vfprintf (stderr, format, arg); +#endif else done = vfprintf (stream, format, arg); va_end (arg); @@ -120,6 +125,9 @@ ssize_t ios_write(int fildes, const void *buf, size_t nbyte) { return write(fildes, buf, nbyte); } size_t ios_fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream) { +#ifdef debugPrint + return fwrite(ptr, size, nitems, stderr); +#endif if (thread_stdout == NULL) thread_stdout = stdout; if (thread_stderr == NULL) thread_stderr = stderr; if (fileno(stream) == STDOUT_FILENO) return fwrite(ptr, size, nitems, thread_stdout); @@ -134,6 +142,9 @@ int ios_puts(const char *s) { return returnValue; } int ios_fputs(const char* s, FILE *stream) { +#ifdef debugPrint + return fputs(s, stderr); +#endif if (thread_stdout == NULL) thread_stdout = stdout; if (thread_stderr == NULL) thread_stderr = stderr; if (fileno(stream) == STDOUT_FILENO) return fputs(s, thread_stdout); @@ -141,6 +152,9 @@ int ios_fputs(const char* s, FILE *stream) { return fputs(s, stream); } int ios_fputc(int c, FILE *stream) { +#ifdef debugPrint + return fputc(c, stderr); +#endif if (thread_stdout == NULL) thread_stdout = stdout; if (thread_stderr == NULL) thread_stderr = stderr; if (fileno(stream) == STDOUT_FILENO) return fputc(c, thread_stdout); diff --git a/shell_cmds/xargs/xargs.c b/shell_cmds/xargs/xargs.c index 1365f704..62d82587 100644 --- a/shell_cmds/xargs/xargs.c +++ b/shell_cmds/xargs/xargs.c @@ -628,15 +628,21 @@ run(char **argv) default: // ios_system: go through both branches // case 0: if (oflag) { +#if !TARGET_OS_IPHONE if ((fd = open(_PATH_TTY, O_RDONLY)) == -1) - err(1, "can't open /dev/tty"); +#else + if ((fd = ios_getstdin()) == -1) +#endif + err(1, "can't open /dev/tty"); } else { fd = open(_PATH_DEVNULL, O_RDONLY); } if (fd > STDIN_FILENO) { if (dup2(fd, STDIN_FILENO) != 0) err(1, "can't dup2 to stdin"); - close(fd); +#if !TARGET_OS_IPHONE + close(fd); +#endif } #if !TARGET_OS_IPHONE execvp(argv[0], argv); diff --git a/text_cmds/sort/sort.c b/text_cmds/sort/sort.c index 2c68b0a9..508e338e 100644 --- a/text_cmds/sort/sort.c +++ b/text_cmds/sort/sort.c @@ -467,6 +467,9 @@ sig_handler(int sig __unused, siginfo_t *siginfo __unused, static void set_signal_handler(void) { +#if TARGET_OS_IPHONE + if (canSetSignal()) { +#endif struct sigaction sa; memset(&sa, 0, sizeof(sa)); @@ -509,6 +512,9 @@ set_signal_handler(void) perror("sigaction"); return; } +#if TARGET_OS_IPHONE + } +#endif } /*