Posts

Post not yet marked as solved
9 Replies
@eskimo, Thanks for the DTS suggestion. Just used one up to get support for this topic. Will reply back if we come to a resolution, thanks again!
Post not yet marked as solved
9 Replies
@eskimo, Reading up on "controlling terminal" was helpful to understand more about whats happening when spawning these processes, I'm still not sure how to actually apply this to my usecase as I've tried to use ioctl(childDescriptor, TIOCSCTTY) in my code to become the controlling terminal with the child part of the PTY and this returns back -1 indicating a failure. Reading online sources have been difficult to grasp as most of them seem be using fork and then ioctl but, from the compiler error I got, it seems fork is not supported in Swift. In addition to having a test tool that calls readpassphrase, you should create another test tool that deals with stdin and stdout in the usual way.  Took your advice here and created a simple program that just reads input and outputs some input: func main() { print("What is your name: ", terminator: "") let name = readLine() print("Hi, \(name ?? "Unknown")") } main() Going to work on getting this to function via Process as its a simpler use case and hopefully solving this can solve the readpassphrase issue. As to what I have so far, I have a Process setup: let process = Process() process.executableURL = executablePath.asURL // path to my basic name collection program process.arguments = arguments.values process.run() When launching this process I get: clide (remotes/origin/luis/foundation-process) > swift run clide [3/3] Build complete! What is your name: Which is great! However, when I input something and press enter, the program does nothing. It just adds a new line in my terminal and continues executing with no additional output. I'm really not sure why this is the case, to me it feels like all this complicated Unix stuff is what a higher-level API like Process is supposed to handle so it's a little confusing when this just doesn't work? Reading the docs for Process seem to indicate it should just setup stdin to be whatever the parent process is: If this method isn’t used, the standard input is inherited from the process that created the receiver. This method raises an NSInvalidArgumentException if the receiver has already been launched. But when actually running the program it doesn't seem like this is the case... Looking at other threads (like this one). Other developers seem to be running into the same issues here. I'm genuinely stuck here and having spent the last week reading up on this I'm not sure I'm any closer to solving this issue in Swift. It really feels like this should be easier to accomplish, but maybe I'm missing something.
Post not yet marked as solved
9 Replies
I’m not sure what xcodes is. Did you mean xcodebuild? Nope, this xcodes is an external tool that manages downloading different xcode versions. As part of this it reads apple id from the terminal and the password (both of which are causing issues with the standard Process setup I had, hence needing to look into PTYs) Apropos that, let me introduce you to the the readpassphrase function (-: You can call it from Swift like so Thanks for this! It's a good test bed to work from as it demonstrates the issue I'm facing. I created a small binary from the code you posted and ran it in my terminal by itself, and get the same result you do (it prompts, reads the password and displays it). I then tried to call that binary from within my CLI using the PTY stuff I have above and get essentially no output: clide (luis/foundation-process) > swift run clide [0/0] Build complete! password <<<<< This was me entering input on my terminal password <<<<< This was displayed after I hit enter I can see what you mean by "overriding stdin is sufficient, but that’s simply not the case" as it doesn't seem to be working here. In my code I read stdin and then write to the parent PTY handle, from my understanding that should then cause the child handle to interpret that as input, so I'm just confused why that doesn't behave like that? Or why I don't see the "Enter password" prompt at the beginning. Thanks again for following up, I'll check out the book but I'm hoping to be able to get this done in a reasonable amount of time. Currently, I'm just stuck because I'm not sure where I've gone wrong in my setup.
Post not yet marked as solved
9 Replies
@eskimo, you were the one I was hoping would reply since you had some thoughts for the original thread I saw, thanks for getting back to me! You mentioned Xcode so I’m presuming that this is on the Mac; let me know otherwise. Correct, we're building a CLI tool in Swift. It should ideally run on both macOS and Linux if at all possible (we have some plans to use the cli on a server at some point)  I recommend that you do your puppetstringing via expect, which takes care of all this silliness for you. Took a look at the expect manpage and while I can see it being useful to automate some aspects of this, or to add a special case for this particular tool were running, I'm really looking to solve this on a more generic basis. For some context: As I mentioned, we're building a CLI tool in Swift, that among other things can automate some of the iOS developer tasks we have at work. To do this, we leverage existing tools for example: git, swiftlint, etc and use the binaries from those programs to create an interface in the CLI that abstracts their usage. This has been working fine until we ran into issues using TSCBasic.Process to run the xcodes binary as it requires some user interactivity to enter a userID and password. The recommendation in that Swift bug was to move to Foundation.Process which were trying to do now. However, now I'm stuck with not being able to run thexcodes binary using Foundation.Process because of the issue posted in this thread. Any insight on how to get this working with Foundation.Process would be great! Essentially, I want to be able to execute some arbitrary binary and have it run as if it were run via a users terminal.