Interactive AND Portable?

S

SeeBelow

Is there any way, in C, of interacting with a running program, but still
using code that is portable, at least between linux and Windows?

By "interacting" it could be something as simple as detecting a key
board hit so that it could invoke scanf(). So a portable key board data
available routine would satisfy my minimum requirements. But more
generally I want to know if one can write portable C code that allows a
user to change the course of execution of a running program.

Thanks,

Mitchell Timin

--
"Many are stubborn in pursuit of the path they have chosen, few in
pursuit of the goal." - Friedrich Nietzsche

http://annevolve.sourceforge.net is what I'm into nowadays.
Humans may write to me at this address: zenguy at telus dot net
 
J

Joona I Palaste

(e-mail address removed) scribbled the following:
Is there any way, in C, of interacting with a running program, but still
using code that is portable, at least between linux and Windows?
By "interacting" it could be something as simple as detecting a key
board hit so that it could invoke scanf(). So a portable key board data
available routine would satisfy my minimum requirements. But more
generally I want to know if one can write portable C code that allows a
user to change the course of execution of a running program.

No. The moment you do anything at all directly with the keyboard, you're
off to OS-specific land, and you have no hope of the same code working
on Linux and Windows.
What's wrong with using the standard input stream? In most cases that is
coming from the keyboard. It's just a matter of having to press Enter.
 
L

Lew Pitcher

Is there any way, in C, of interacting with a running program, but still
using code that is portable, at least between linux and Windows?

Yes, if you stick with the stdio I/O functions (i.e. scanf(), printf(), and the
like), you can easily write a portable interactive program.
By "interacting" it could be something as simple as detecting a key
board hit so that it could invoke scanf().

Now you've taken yourself out of the world of portability.
1) C doesn't have any portible way of "detecting a keyboard hit"
(the C language doesn't even recognize such a thing), and
2) In Linux (at least), an "interactive" program may be run /without/ a
recognizable 'keyboard' at all (thinks "expect" scripts, or just plain
scripting). To require the code to "detect a keyboard hit" is to make
it unportable.
So a portable key board data
available routine would satisfy my minimum requirements.

Such exists, in the form of the standard I/O routines like scanf() and getc()
But more
generally I want to know if one can write portable C code that allows a
user to change the course of execution of a running program.

Yes, of course. Use the stdio functions.

--
Lew Pitcher
IT Consultant, Enterprise Technology Solutions
Toronto Dominion Bank Financial Group

(Opinions expressed are my own, not my employers')
 
S

SeeBelow

Joona said:
(e-mail address removed) scribbled the following:


No. The moment you do anything at all directly with the keyboard, you're
off to OS-specific land, and you have no hope of the same code working
on Linux and Windows.
What's wrong with using the standard input stream? In most cases that is
coming from the keyboard. It's just a matter of having to press Enter.

I guess I wasn't clear; I don't want the program to be doing nothing
while waiting for an "enter" from the KB. My program may be running for
hours, doing simulated evolution. I need to occaisonally give it some
data, or make a decision for it. I don't mind if it pauses while
interacting with me, but after that it must continue processing.

Is there a way of doing that with the standard input stream?

m

--
"Many are stubborn in pursuit of the path they have chosen, few in
pursuit of the goal." - Friedrich Nietzsche

http://annevolve.sourceforge.net is what I'm into nowadays.
Humans may write to me at this address: zenguy at telus dot net
 
S

SeeBelow

Lew said:
Yes, if you stick with the stdio I/O functions (i.e. scanf(), printf(), and the
like), you can easily write a portable interactive program.


Now you've taken yourself out of the world of portability.
1) C doesn't have any portible way of "detecting a keyboard hit"
(the C language doesn't even recognize such a thing), and
2) In Linux (at least), an "interactive" program may be run /without/ a
recognizable 'keyboard' at all (thinks "expect" scripts, or just plain
scripting). To require the code to "detect a keyboard hit" is to make
it unportable.


Such exists, in the form of the standard I/O routines like scanf() and getc()


Yes, of course. Use the stdio functions.

Can that be done without the program pausing? I guess I wasn't clear; I
don't want the program to be doing nothing while waiting for an "enter"
from the KB. My program may be running for hours, doing simulated
evolution. I need to occaisonally give it some data, or make a decision
for it. I don't mind if it pauses while interacting with me, but after
that it must continue processing.

Is there a portable way of doing that?

Mitchell Timin

--
"Many are stubborn in pursuit of the path they have chosen, few in
pursuit of the goal." - Friedrich Nietzsche

http://annevolve.sourceforge.net is what I'm into nowadays.
Humans may write to me at this address: zenguy at telus dot net
 
J

Joona I Palaste

(e-mail address removed) scribbled the following:
I guess I wasn't clear; I don't want the program to be doing nothing
while waiting for an "enter" from the KB. My program may be running for
hours, doing simulated evolution. I need to occaisonally give it some
data, or make a decision for it. I don't mind if it pauses while
interacting with me, but after that it must continue processing.
Is there a way of doing that with the standard input stream?

It took me some time to figure out what you want the program to do.
You say you want your program to be *both* processing its data *and*
looking for input from you at the same time? I don't think that it's
possible within the standard C I/O model.
Standard C input functions are blocking. If there is not enough data
available in the stream they are reading from, they block until there
is. If the stream is closed, they return immediately with an error
code.
Therefore your program would need to either wait every now and then
for you to give it input - or process a "batch" of input you've
given it in advance. All it wants is a stream of bytes. It doesn't
care where that stream is coming from.
If C had multi-threading support as standard, you could have one
thread processing the data and another doing blocking I/O, but as it
doesn't, you can't.
So, unfortunately, the answer is no: you can't do what you ask with
standard I/O. Your program must either block while accepting input
or process ready-written input without ex-tempore additions.
 
D

Dave Vandervies

I guess I wasn't clear; I don't want the program to be doing nothing
while waiting for an "enter" from the KB. My program may be running for
hours, doing simulated evolution. I need to occaisonally give it some
data, or make a decision for it. I don't mind if it pauses while
interacting with me, but after that it must continue processing.

Is there a way of doing that with the standard input stream?

Not directly, but if you have a reliable way of generating SIGINT
(ctrl-C should do this on both Unix and Windows), you can fake it.

You'll need a flag that the signal handler will set to indicate that
the user wants to talk to the program:
--------
#include <signal.h>
volatile sig_atomic_t stop_and_get_input;
--------

You'll need a signal handler that looks something like this:
--------
#include <signal.h>

void sigint_handler(int sig)
{
stop_and_get_input=1;

/*Reinstate the signal handler. May or may not be required
(N869 7.14.1.1#3), but causes no problems if done when not
required (N869 7.14.1.1#5).
*/
#ifdef PARANOID
/*Set failed_to_reinstate_handler (which should be a volatile
sig_atomic_t) to indicate that something went wrong and we
won't be able to request an interactive session again
*/
if(signal(sig,sigint_handler) == SIG_ERR)
failed_to_reinstate_handler=1;
#else /*Not paranoid, so just assume reinstatement succeeded*/
signal(sig,sigint_handler);
#endif
}
--------

Before you enter your main loop, install the signal handler like this:
--------
/*Near the beginning of main is probably the best place to put this.
Don't forget to #include <signal.h>.
*/
void (*oldsigfunc)(int);
oldsigfunc=signal(SIGTERM,sigint_handler);
if(oldsigfunc == SIG_ERR)
{
fputs("Can't install signal handler - user interaction requests are unavailable\n",stderr);
}
else if(oldsigfunc == SIG_IGN)
{
fputs("SIGTERM was ignored (perhaps we're running in the background?), re-ignoring\n",stderr);
signal(SIGTERM,SIG_IGN);
}
--------

Now when your program fgets the SIGINT signal (usually as a result
of getting a ctrl-C at the keyboard), the signal handler will run and
set stop_and_get_input to indicate that this happened, so now you can
put something like this inside your main loop:
--------
/*This should go somewhere deep enough in the main loop to run within
a reasonable amount of time after the signal handler runs, but not
deep enough to slow down the program by running millions of times
a second or to run in the middle of something that you don't want
to be changing parameters in the middle of.
*/
if(stop_and_get_input)
{
do_user_input();
stop_and_get_input=0;
}
--------

The program won't run in the background while do_user_input() is running,
so you'll need to have a way for the user to tell it "OK, I'm done, go
back to crunching and I'll interrupt you again if I have more to say".
It would also be nice for it to have a way to exit the program without
running to completion, since the usual response to SIGINT is for the
program to do that (without stopping and bothering the user first).


One thing that may not work, and is a Bad Idea anyways, is to have the
signal handler call do_user_input directly. Since standard C doesn't
require that you be able to call library functions from a signal handler
(with a few exceptions, like reinstating the signal handler or installing
a new one for the same signal), you can't do this without invoking
undefined behavior; also, at least one rather common system (Windows)
will run the signal handler in its own thread while the main program
continues to run, forcing you to deal with concurrency issues if you
change anything that the program wants to be able to use.


dave

--
Dave Vandervies (e-mail address removed)
May I be excused for showing incomplete/incorrect knowledge of C++ knowledge
in a C newsgroup? --Michael Rubenstein and Ian Woods in comp.lang.c
 
R

Randy Howard

No. You probably want to use threads. Try an appropriate OS newsgroup that
discusses threads. It is quite easy with threads.

Yes. comp.programming.threads is a fine place to start.

If you are willing to expand the concept of portability to POSIX
standards instead of ISO, for example wanting to run on both Linux
and Win32, then pthreads will do it for you. Just be aware that
moving to 64-bit from 32-bit on Windows may or may not be ready w/
respect to pthreads when your time comes to do the port.
 
S

SeeBelow

Joona I Palaste wrote:
It took me some time to figure out what you want the program to do.
You say you want your program to be *both* processing its data *and*
looking for input from you at the same time? I don't think that it's
possible within the standard C I/O model.
Standard C input functions are blocking. If there is not enough data
available in the stream they are reading from, they block until there
is. If the stream is closed, they return immediately with an error
code.
Therefore your program would need to either wait every now and then
for you to give it input - or process a "batch" of input you've
given it in advance. All it wants is a stream of bytes. It doesn't
care where that stream is coming from.
If C had multi-threading support as standard, you could have one
thread processing the data and another doing blocking I/O, but as it
doesn't, you can't.
So, unfortunately, the answer is no: you can't do what you ask with
standard I/O. Your program must either block while accepting input
or process ready-written input without ex-tempore additions.

A C program can look for a file, and if it won't open, then it can
continue processing without blocking. Is there a way to do that using
the keyboard stream?

I could actually do this by using a file as a messenger. I would have
to have a seperate program running concurrently, which both Windows and
linux can do. This second program would use scanf() to get user input,
and then write a file. The primary program would be periodically trying
to open this file. When it succeeds it gets the data and then closes
the file. Otherwise it continues processing.

Is there some way to do the same thing by treating the keyboard stream
as a file?

Mitchell Timin

--
"Many are stubborn in pursuit of the path they have chosen, few in
pursuit of the goal." - Friedrich Nietzsche

http://annevolve.sourceforge.net is what I'm into nowadays.
Humans may write to me at this address: zenguy at telus dot net
 
S

SeeBelow

Dave Vandervies wrote:
Not directly, but if you have a reliable way of generating SIGINT
(ctrl-C should do this on both Unix and Windows), you can fake it.

You'll need a flag that the signal handler will set to indicate that
the user wants to talk to the program:
--------
#include <signal.h>
volatile sig_atomic_t stop_and_get_input;
--------

You'll need a signal handler that looks something like this:
--------
#include <signal.h>

void sigint_handler(int sig)
{
stop_and_get_input=1;

/*Reinstate the signal handler. May or may not be required
(N869 7.14.1.1#3), but causes no problems if done when not
required (N869 7.14.1.1#5).
*/
#ifdef PARANOID
/*Set failed_to_reinstate_handler (which should be a volatile
sig_atomic_t) to indicate that something went wrong and we
won't be able to request an interactive session again
*/
if(signal(sig,sigint_handler) == SIG_ERR)
failed_to_reinstate_handler=1;
#else /*Not paranoid, so just assume reinstatement succeeded*/
signal(sig,sigint_handler);
#endif
}
--------

Before you enter your main loop, install the signal handler like this:
--------
/*Near the beginning of main is probably the best place to put this.
Don't forget to #include <signal.h>.
*/
void (*oldsigfunc)(int);
oldsigfunc=signal(SIGTERM,sigint_handler);
if(oldsigfunc == SIG_ERR)
{
fputs("Can't install signal handler - user interaction requests are unavailable\n",stderr);
}
else if(oldsigfunc == SIG_IGN)
{
fputs("SIGTERM was ignored (perhaps we're running in the background?), re-ignoring\n",stderr);
signal(SIGTERM,SIG_IGN);
}
--------

Now when your program fgets the SIGINT signal (usually as a result
of getting a ctrl-C at the keyboard), the signal handler will run and
set stop_and_get_input to indicate that this happened, so now you can
put something like this inside your main loop:
--------
/*This should go somewhere deep enough in the main loop to run within
a reasonable amount of time after the signal handler runs, but not
deep enough to slow down the program by running millions of times
a second or to run in the middle of something that you don't want
to be changing parameters in the middle of.
*/
if(stop_and_get_input)
{
do_user_input();
stop_and_get_input=0;
}
--------

The program won't run in the background while do_user_input() is running,
so you'll need to have a way for the user to tell it "OK, I'm done, go
back to crunching and I'll interrupt you again if I have more to say".
It would also be nice for it to have a way to exit the program without
running to completion, since the usual response to SIGINT is for the
program to do that (without stopping and bothering the user first).

One thing that may not work, and is a Bad Idea anyways, is to have the
signal handler call do_user_input directly. Since standard C doesn't
require that you be able to call library functions from a signal handler
(with a few exceptions, like reinstating the signal handler or installing
a new one for the same signal), you can't do this without invoking
undefined behavior; also, at least one rather common system (Windows)
will run the signal handler in its own thread while the main program
continues to run, forcing you to deal with concurrency issues if you
change anything that the program wants to be able to use.

Wow! That's quite an answer. Perhaps that's exactly what I need. I
know nothing about SIGINT or the use of signals in C, but with the hints
you have given me perhaps I can learn it.

If there is no easier way I will try to implement your suggestion.

Thanks,

Mitchell Timin

--
"Many are stubborn in pursuit of the path they have chosen, few in
pursuit of the goal." - Friedrich Nietzsche

http://annevolve.sourceforge.net is what I'm into nowadays.
Humans may write to me at this address: zenguy at telus dot net
 
D

Dave Vandervies

A C program can look for a file, and if it won't open, then it can
continue processing without blocking. Is there a way to do that using
the keyboard stream?

No. The two operations ("open file and associate it with a stream"
and "read from a stream") are handled differently and have different
ways of indicating "nothing here"; with an input stream associated with
a keyboard, "nothing here" is handled by waiting for more, while with
a file "nothing here" is handled by indicating that the program can't
open that file (because it doesn't exist).

I could actually do this by using a file as a messenger. I would have
to have a seperate program running concurrently, which both Windows and
linux can do. This second program would use scanf() to get user input,
and then write a file. The primary program would be periodically trying
to open this file. When it succeeds it gets the data and then closes
the file. Otherwise it continues processing.

This will work. You'd need some way to recognize that the file has been
updated; one way of doing this is to have the primary program delete the
file (with remove()) when it's finished reading it, but in that case
you'd need the control program to wait for the primary to process and
remove the file before writing a new one if more commands are ready.

(scanf is also not a very good way to handle user input, even though
if you're careful it can be made to play nicely (unlike, say, gets).
Using fgets to read a line at a time and then breaking down the line of
input once you've read it is usually easier to get right.)


Not inappropriate in this case, it seems - the path of "non-blocking
stdio input" isn't all that close to a good way to acheive the goal of
"asynchronous user input to a running program". Have you had a chance
to digest my suggestion elsethread about using a signal handler to notify
the program that you'd like to tell it something?


dave
 
S

Sheldon Simms

Yes. comp.programming.threads is a fine place to start.


If you are willing to expand the concept of portability to POSIX
standards instead of ISO, for example wanting to run on both Linux
and Win32, then pthreads will do it for you. Just be aware that
moving to 64-bit from 32-bit on Windows may or may not be ready w/
respect to pthreads when your time comes to do the port.

Threads are totally unnecessary for this application. The
solution is outside the scope of standard C, but all the OP
really needs is a non-blocking read from stdio.

-Sheldon
 
J

Jack Klein

Threads are totally unnecessary for this application. The
solution is outside the scope of standard C, but all the OP
really needs is a non-blocking read from stdio.

-Sheldon

Actually, no, that is not what he needs. What he requested is
non-blocking input from a keyboard, which is something that doesn't
exist in C.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
 
G

Gordon Burditt

If C had multi-threading support as standard, you could have one
A C program can look for a file, and if it won't open, then it can
continue processing without blocking.

This is not guaranteed. It is quite possible that if you attempt
to open a modem device, it will block until the modem receives an
incoming call from another modem. (This is a common UNIX way of
handling serial ports with modem control lines enabled). Also,
even with a disk file, it is not necessarily possible to have the
open succeed or fail without waiting for the disk I/O to finish.
Is there a way to do that using
the keyboard stream?

Not portably.

Gordon L. Burditt
 
J

Joona I Palaste

(e-mail address removed) scribbled the following:
Joona I Palaste wrote:
A C program can look for a file, and if it won't open, then it can
continue processing without blocking. Is there a way to do that using
the keyboard stream?

No. A C program can't open the keyboard stream in the first place. A
console or terminal emulator has to do it for it.
I could actually do this by using a file as a messenger. I would have
to have a seperate program running concurrently, which both Windows and
linux can do. This second program would use scanf() to get user input,
and then write a file. The primary program would be periodically trying
to open this file. When it succeeds it gets the data and then closes
the file. Otherwise it continues processing.
Is there some way to do the same thing by treating the keyboard stream
as a file?

No. Not in standard C, that is.
 
F

Fred L. Kleinschmidt

Is there any way, in C, of interacting with a running program, but still
using code that is portable, at least between linux and Windows?

By "interacting" it could be something as simple as detecting a key
board hit so that it could invoke scanf(). So a portable key board data
available routine would satisfy my minimum requirements. But more
generally I want to know if one can write portable C code that allows a
user to change the course of execution of a running program.

Thanks,

Mitchell Timin

--
"Many are stubborn in pursuit of the path they have chosen, few in
pursuit of the goal." - Friedrich Nietzsche

http://annevolve.sourceforge.net is what I'm into nowadays.
Humans may write to me at this address: zenguy at telus dot net

Relatively easy to do if you have eXceed on the Windows platform. Just
write the program using X; I do it all the time, either using just X, or
with Xt and Motif. My C source code is identical for my Unix, Linux, and
Win32 platforms.
 
S

SeeBelow

Relatively easy to do if you have eXceed on the Windows platform. Just
write the program using X; I do it all the time, either using just X, or
with Xt and Motif. My C source code is identical for my Unix, Linux, and
Win32 platforms.

That's interesting. I never heard of eXceed. Is it a commercial
product, a free download, or something in between?

I also don't know how to program in X; I'm not even sure what that
means, although I know what X-Windows is.

Can you show a few lines of X code that would do something like what I
describe above?

Thanks,

Mitchell Timin

--
"Many are stubborn in pursuit of the path they have chosen, few in
pursuit of the goal." - Friedrich Nietzsche

http://annevolve.sourceforge.net is what I'm into nowadays.
Humans may write to me at this address: zenguy at telus dot net
 
S

Sheldon Simms

Actually, no, that is not what he needs. What he requested is
non-blocking input from a keyboard, which is something that doesn't
exist in C.

You are right, but threads don't exist in C either. For
practical purposes, an implementation extension that provides
a non-blocking read from stdio would solve the OP's problem.
 
C

Chris Torek

... if you have a reliable way of generating SIGINT
(ctrl-C should do this on both Unix and Windows), you can fake
[interactivity].

but then:
oldsigfunc=signal(SIGTERM,sigint_handler); [and]
fputs("SIGTERM was ignored (perhaps we're running in the background?), re-ignoring\n",stderr);
signal(SIGTERM,SIG_IGN);

Presumably these are all supposed to read SIGINT as well. :)

Not quite on topic for the group, but perhaps significant, there
is a pitfall in using an interrupt key on Unix-like systems (whether
it applies to MS-Windows is less clear -- I try to avoid Windows
as much as possible and in any case Windows systems are not commonly
used with remote displays half a world away over long-response-time
TCP connections...). In particular, interrupting a program may
flush queued but as-yet-undisplayed output, at the OS level. There
is nothing a portable C program can do about this.

One's best bet, in a case like this, is no doubt to separate out
the "interact while running" parts of the program. At the least,
you could have an "if (input_is_available()) get_input();" code
sequence, where "input_is_available()" is a function you rewrite
for each target system. I would also suggest that, if possible,
the "interaction" happen independently -- ideally, in a completely
separate program -- and then have the interactive program signal
(whether or not in the C sense) the computational program to pick
up the new data, once it is all prepared. This maximizes the
opportunities for parallelism. For instance, you can then run the
data crunching program on a remote supercomputer if you like.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top