From b2f81bf7c6cbaa909a0ddf6daf67324353a7ce8e Mon Sep 17 00:00:00 2001 From: Fabian Thies Date: Mon, 13 Feb 2023 18:56:34 +0100 Subject: [PATCH] [ADD] LocalConsole showing STDOUT and STDERR --- AltStore.xcodeproj/project.pbxproj | 21 ++++++++ .../xcshareddata/swiftpm/Package.resolved | 9 ++++ AltStore/AppDelegate.swift | 3 ++ AltStore/Manager/OutputCapturer.swift | 49 +++++++++++++++++++ AltStore/Views/Settings/SettingsView.swift | 5 ++ 5 files changed, 87 insertions(+) create mode 100644 AltStore/Manager/OutputCapturer.swift diff --git a/AltStore.xcodeproj/project.pbxproj b/AltStore.xcodeproj/project.pbxproj index 5bc0e3f6..af79f73a 100644 --- a/AltStore.xcodeproj/project.pbxproj +++ b/AltStore.xcodeproj/project.pbxproj @@ -77,6 +77,8 @@ 1FB96FCF292BBBCA007E68D1 /* SiriShortcutSetupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB96FCE292BBBC9007E68D1 /* SiriShortcutSetupView.swift */; }; 1FB96FEC292C171D007E68D1 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB96FEB292C171D007E68D1 /* NotificationManager.swift */; }; 1FB96FF3292D0539007E68D1 /* PillButtonProgressViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FB96FF2292D0539007E68D1 /* PillButtonProgressViewStyle.swift */; }; + 1FFA56C2299994390011B6F5 /* OutputCapturer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FFA56C1299994390011B6F5 /* OutputCapturer.swift */; }; + 1FFA56C52999978C0011B6F5 /* LocalConsole in Frameworks */ = {isa = PBXBuildFile; productRef = 1FFA56C42999978C0011B6F5 /* LocalConsole */; }; 1FFEF104298552DB0098374C /* AppVersionHistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FFEF103298552DB0098374C /* AppVersionHistoryView.swift */; }; 4879A95F2861046500FC1BBD /* AltSign in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A95E2861046500FC1BBD /* AltSign */; }; 4879A9622861049C00FC1BBD /* OpenSSL in Frameworks */ = {isa = PBXBuildFile; productRef = 4879A9612861049C00FC1BBD /* OpenSSL */; }; @@ -627,6 +629,7 @@ 1FB96FCE292BBBC9007E68D1 /* SiriShortcutSetupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiriShortcutSetupView.swift; sourceTree = ""; }; 1FB96FEB292C171D007E68D1 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; 1FB96FF2292D0539007E68D1 /* PillButtonProgressViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PillButtonProgressViewStyle.swift; sourceTree = ""; }; + 1FFA56C1299994390011B6F5 /* OutputCapturer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OutputCapturer.swift; sourceTree = ""; }; 1FFEF103298552DB0098374C /* AppVersionHistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppVersionHistoryView.swift; sourceTree = ""; }; B3146EC6284F580500BBC3FD /* Roxas.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Roxas.xcodeproj; path = Dependencies/Roxas/Roxas.xcodeproj; sourceTree = ""; }; B33FFBA9295F8F78002259E6 /* preboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = preboard.c; path = src/preboard.c; sourceTree = ""; }; @@ -1048,6 +1051,7 @@ BF1614F1250822F100767AEA /* Roxas.framework in Frameworks */, B3C395F7284F362400DA9E2F /* AppCenterAnalytics in Frameworks */, 1F07F5672955D16A00F7BE95 /* SFSafeSymbols in Frameworks */, + 1FFA56C52999978C0011B6F5 /* LocalConsole in Frameworks */, BF66EE852501AE50007EE018 /* AltStoreCore.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1250,6 +1254,7 @@ isa = PBXGroup; children = ( 1FB96FEB292C171D007E68D1 /* NotificationManager.swift */, + 1FFA56C1299994390011B6F5 /* OutputCapturer.swift */, ); path = Manager; sourceTree = ""; @@ -2302,6 +2307,7 @@ 1F74FF1D295263510047C051 /* AsyncImage */, 1F07F5662955D16A00F7BE95 /* SFSafeSymbols */, 1F1295802989B51F0048FCB9 /* ExpandableText */, + 1FFA56C42999978C0011B6F5 /* LocalConsole */, ); productName = AltStore; productReference = BFD2476A2284B9A500981D42 /* SideStore.app */; @@ -2377,6 +2383,7 @@ 1F74FF1C295263510047C051 /* XCRemoteSwiftPackageReference "AsyncImage" */, 1F07F5652955D16A00F7BE95 /* XCRemoteSwiftPackageReference "SFSafeSymbols" */, 1F12957F2989B51F0048FCB9 /* XCRemoteSwiftPackageReference "ExpandableText" */, + 1FFA56C32999978C0011B6F5 /* XCRemoteSwiftPackageReference "LocalConsole" */, ); productRefGroup = BFD2476B2284B9A500981D42 /* Products */; projectDirPath = ""; @@ -2797,6 +2804,7 @@ D5DAE0942804B0B80034D8D4 /* ScreenshotProcessor.swift in Sources */, 1FB96FBE292A20E5007E68D1 /* ObservableScrollView.swift in Sources */, BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */, + 1FFA56C2299994390011B6F5 /* OutputCapturer.swift in Sources */, BF41B806233423AE00C593A3 /* TabBarController.swift in Sources */, 1FB96FC9292ABDD0007E68D1 /* AddSourceView.swift in Sources */, 1F6E08DC292807D3005059C0 /* AppIconView.swift in Sources */, @@ -3743,6 +3751,14 @@ kind = branch; }; }; + 1FFA56C32999978C0011B6F5 /* XCRemoteSwiftPackageReference "LocalConsole" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/duraidabdul/LocalConsole.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 1.0.0; + }; + }; 4879A95D2861046500FC1BBD /* XCRemoteSwiftPackageReference "AltSign" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/SideStore/AltSign"; @@ -3848,6 +3864,11 @@ package = 1F74FF1C295263510047C051 /* XCRemoteSwiftPackageReference "AsyncImage" */; productName = AsyncImage; }; + 1FFA56C42999978C0011B6F5 /* LocalConsole */ = { + isa = XCSwiftPackageProductDependency; + package = 1FFA56C32999978C0011B6F5 /* XCRemoteSwiftPackageReference "LocalConsole" */; + productName = LocalConsole; + }; 4879A95E2861046500FC1BBD /* AltSign */ = { isa = XCSwiftPackageProductDependency; package = 4879A95D2861046500FC1BBD /* XCRemoteSwiftPackageReference "AltSign" */; diff --git a/AltStore.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/AltStore.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 183f1543..0eea3594 100644 --- a/AltStore.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/AltStore.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -54,6 +54,15 @@ "version" : "4.2.0" } }, + { + "identity" : "localconsole", + "kind" : "remoteSourceControl", + "location" : "https://github.com/duraidabdul/LocalConsole.git", + "state" : { + "revision" : "2c5d5e018acd4963fe6dfe858f6d6fecef7cbf2f", + "version" : "1.12.1" + } + }, { "identity" : "nuke", "kind" : "remoteSourceControl", diff --git a/AltStore/AppDelegate.swift b/AltStore/AppDelegate.swift index 34e1b073..f9fb90c1 100644 --- a/AltStore/AppDelegate.swift +++ b/AltStore/AppDelegate.swift @@ -58,6 +58,9 @@ final class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Copy STDOUT and STDERR to the logging console + _ = OutputCapturer.shared + // Register default settings before doing anything else. UserDefaults.registerDefaults() diff --git a/AltStore/Manager/OutputCapturer.swift b/AltStore/Manager/OutputCapturer.swift new file mode 100644 index 00000000..cf334f1e --- /dev/null +++ b/AltStore/Manager/OutputCapturer.swift @@ -0,0 +1,49 @@ +// +// OutputCapturer.swift +// SideStore +// +// Created by Fabian Thies on 12.02.23. +// Copyright © 2023 SideStore. All rights reserved. +// + +import Foundation +import LocalConsole + +class OutputCapturer { + + public static let shared = OutputCapturer() + + private let consoleManager = LCManager.shared + + private var inputPipe = Pipe() + private var errorPipe = Pipe() + + private init() { + // Setup pipe file handlers + self.inputPipe.fileHandleForReading.readabilityHandler = { [weak self] fileHandle in + self?.handle(data: fileHandle.availableData) + } + self.errorPipe.fileHandleForReading.readabilityHandler = { [weak self] fileHandle in + self?.handle(data: fileHandle.availableData, isError: true) + } + + // Intercept STDOUT and STDERR + dup2(self.inputPipe.fileHandleForWriting.fileDescriptor, STDOUT_FILENO) + dup2(self.errorPipe.fileHandleForWriting.fileDescriptor, STDERR_FILENO) + } + + deinit { + try? self.inputPipe.fileHandleForReading.close() + try? self.errorPipe.fileHandleForReading.close() + } + + private func handle(data: Data, isError: Bool = false) { + guard let string = String(data: data, encoding: .utf8) else { + return + } + + DispatchQueue.main.async { + self.consoleManager.print(string) + } + } +} diff --git a/AltStore/Views/Settings/SettingsView.swift b/AltStore/Views/Settings/SettingsView.swift index 5d51df7c..97e1891d 100644 --- a/AltStore/Views/Settings/SettingsView.swift +++ b/AltStore/Views/Settings/SettingsView.swift @@ -9,6 +9,7 @@ import SwiftUI import AsyncImage import SFSafeSymbols +import LocalConsole import AltStoreCore import Intents @@ -157,6 +158,10 @@ struct SettingsView: View { RefreshAttemptsView() } + SwiftUI.Button("Toggle Console") { + LCManager.shared.isVisible.toggle() + } + if MailComposeView.canSendMail { SwiftUI.Button("Send Feedback") { self.isShowingFeedbackMailView = true