Agreeing fully with BrowserUK’s previous comments on this (I think...), I would definitely suggest first of all that you leave the existing application completely alone, and that you build-out a graphic interface that knows how to talk to it. In particular, I would design the system with three fundamental working parts:
The existing (“legacy”) application, now running as a child process, entirely untouched.
An application or thread whose job it is to monitor the state of the existing-application process, to receive prompts from its STDOUT, and to supply inputs to its STDIN. This “shepherd process” always knows the present “state” of that application, and can generate notifications when that application moves from one “state” to another. A typical design for the shepherd process is a Finite-State Machine (FSM), or more likely, two FSMs.
A GUI front-end process, which receives notifications from the “shepherd” and which sends information and instructions to it (to be subsequently relayed by the shepherd to the legacy application in some appropriate fashion and at some appropriate near-future time). Build this in Perl/TK or in whatever else may suit you. (Could it, for example, be a web/CGI application, thereby shoving the user-interface issues off to a web browser? Sure, it could, if you wanted.)
The so-called “shepherd” is the go-between that connects the entirely synchronous nature of the legacy application, (indirectly) to the entirely asynchronous nature of the GUI, while by design holding itself at arm’s length from both. The connections between the three processes are asynchronous, buffered queues, i.e.
“pipes,” through which a well-established set of messages (or as the case may be, text-strings) are exchanged. The three parts are said to be loosely