using system?

M

mlt

I would like to do something like this:

system("cd test/test2/")
system("wgnuplot test.p")

But wgnuplot is not executed form the dir that I use system to cd to, is
that not possible?
 
J

James Kanze

I would like to do something like this:
system("cd test/test2/")
system("wgnuplot test.p")
But wgnuplot is not executed form the dir that I use system to
cd to, is that not possible?

The semantics of the string passed to system is implementation
defined, but in most (or almost most) cases, it will generate a
subprocess, and in many systems (Unix, at least, and I think
also under Windows), changes in the environment only affect the
process in which the change occurs, and subprocesses of that
process which are spawned after the change.

Under Unix (and I think under Windows as well), you can do
something like:

system( "cd test/test2/" ; wgnuplot test.p" ) ;

(I'm actually not sure that this works under Windows. Can
anyone confirm?)
 
T

Thomas J. Gritzan

James said:
The semantics of the string passed to system is implementation
defined, but in most (or almost most) cases, it will generate a
subprocess, and in many systems (Unix, at least, and I think
also under Windows), changes in the environment only affect the
process in which the change occurs, and subprocesses of that
process which are spawned after the change.

Under Unix (and I think under Windows as well), you can do
something like:

system( "cd test/test2/" ; wgnuplot test.p" ) ;

Syntax error. Your " are not paired.
(I'm actually not sure that this works under Windows. Can
anyone confirm?)

NACK.

In Windows Vista, "cd / ; dir" won't work, but "cd / && dir" prints the
root directory.
 
J

James Kanze

Syntax error. Your " are not paired.

Yup. The one in the middle is the one I didn't want.
In Windows Vista, "cd / ; dir" won't work, but "cd / && dir"
prints the root directory.

Interesting.

I'd already encountered problems with system under Windows, due
to the fact that it didn't invoke a command interpreter, but I'd
forgotten about them. A quick check on my Windows machine
(which wasn't handy when I responded earlier), however, shows
the first printing the current directory. (That's Windows XP
Professional, with SP 3, and the VC++ from Visual Studio 8,
version 14.00.50727.762.) Without invoking a command
interpreter, I don't see how the dir command would ever be
executed. I'm also wondering: under Unix (and presumably under
Windows as well), cd is a built-in command of the command
interpreter, and not a separate program. What does system do
about this?

Note that as far as I know, Windows doesn't specify anything
here, so it's entirely up to the compiler. Posix requires the
string to be interpreted by a Posix compatible shell (but
Solaris doesn't seem to be Posix compliant here).

In the end, it's very difficult to use system in any portable
manner. (I gave up with it, and ended up writing my own spawn,
once for Windows and once for Unix, just so that I know what I'm
getting.)
 
C

Christof Donat

Hi,
I would like to do something like this:

system("cd test/test2/")
system("wgnuplot test.p")

But wgnuplot is not executed form the dir that I use system to cd to, is
that not possible?

1. Is there a good reason why you use system("cd ...") instead of
chdir("...")?

2. why not call wgnuplot with the complete path?

string wgpath = "/asdf/jkl/";
chdir("test/test2/");
system( (wgpath+"wgnuplot test.p").c_str() );

Christof
 
P

Pascal J. Bourguignon

Christof Donat said:
Hi,


1. Is there a good reason why you use system("cd ...") instead of
chdir("...")?

system("cd xyz") is a NOP.
system forks a shell. The shell will call chdir, then exit. The
parent process will be unaffected.

2. why not call wgnuplot with the complete path?

string wgpath = "/asdf/jkl/";
chdir("test/test2/");
system( (wgpath+"wgnuplot test.p").c_str() );

system should be avoided.

if(fork()==0){
chdir(path);
char* argv[3];
argv[0]=(wgpath+"wgnuplot").c_str();
argv[1]="test.p";
argv[2]=0;
execv(argv[0],argv);
// should not reach here.
exit(1);
}
 
J

James Kanze

1. Is there a good reason why you use system("cd ...") instead
of chdir("...")?

Well, neither is very portable. (Under Windows, that would be
SetCurrentDirectory, for example.) But more importantly, the
semantics aren't the same; chdir/SetCurrentDirectory changes the
current directory of the running process, system( "cd ..." )
doesn't.
2. why not call wgnuplot with the complete path?
string wgpath = "/asdf/jkl/";
chdir("test/test2/");
system( (wgpath+"wgnuplot test.p").c_str() );

That won't affect the current directory when wgnuplot runs.
That may or may not be an issue, of course.
 
J

James Kanze

Christof Donat <[email protected]> writes:

[...]
system should be avoided.
if(fork()==0){
chdir(path);
char* argv[3];
argv[0]=(wgpath+"wgnuplot").c_str();
argv[1]="test.p";
argv[2]=0;
execv(argv[0],argv);
// should not reach here.
exit(1);
}

And what is the advantage of doing this, unless you're paid by
the line?

Not that this has undefined behavior: you've assigned a pointer
to the internals of a temporary object to argv[0]. And why
should you have to know the full path of wgnuplot anyway; one of
the real advantages of system under Posix is that it uses a full
shell path lookup.

If the only reason for changing directories is for wgnuplot to
find test.p, then:

system( "wgnuplot test/test2/test.p" ) ;

would solve the problem. It's also likely to be more portable;
it will work under both Unix and Windows, for example.

The function system has its problems; I myself have a
replacement in my libraries, which results in a version with
known semantics. (IIRC, the problems I was having involved
quoting arguments which contained special characters.) But for
something this simple, it works fine. And if your not concerned
with portability beyond Posix, there's very little reason to use
anything else. (Posix requires that the function execute the
equivalent of "sh -c 'command string'", where sh is a Posix
conformant shell.)
 
C

Christof Donat

Hi,
Well, neither is very portable. (Under Windows, that would be
SetCurrentDirectory, for example.)

I don't work with Windows, but as much as I know including dir.h should be
enough to have chdir() available.
But more importantly, the
semantics aren't the same; chdir/SetCurrentDirectory changes the
current directory of the running process, system( "cd ..." )
doesn't.

Well, I do think that the intention of the OP was to use chdir() instead of
just heating the room by executing totally useless instructions.
That won't affect the current directory when wgnuplot runs.
That may or may not be an issue, of course.

As much as I understood the OP had the problem, that his Programm wgnuplot
was not in the path. Using the full path should fix that. My example code
includes the call to chdir(). The Program /asdf/jkl/wgnuplot will be
executed in test/test2/ with the input file test/test2/test.p - it will open
test.p in its current directory which we have changed to test/test2.

I don't have a Problem if that is not what the OP needs. I'm just trying to
be helpful.

Christof
 
P

Pascal J. Bourguignon

James Kanze said:
[...]
2. why not call wgnuplot with the complete path?
string wgpath = "/asdf/jkl/";
chdir("test/test2/");
system( (wgpath+"wgnuplot test.p").c_str() );
system should be avoided.
if(fork()==0){
chdir(path);
char* argv[3];
argv[0]=(wgpath+"wgnuplot").c_str();
argv[1]="test.p";
argv[2]=0;
execv(argv[0],argv);
// should not reach here.
exit(1);
}

And what is the advantage of doing this, unless you're paid by
the line?

Not that this has undefined behavior: you've assigned a pointer
to the internals of a temporary object to argv[0]. And why
should you have to know the full path of wgnuplot anyway; one of
the real advantages of system under Posix is that it uses a full
shell path lookup.

You can use execvp if you want to go thru PATH.

The downsides of system are:

* As mentioned, system() ignores SIGINT and SIGQUIT. This may
make programs that call it from a loop uninterrupt- ible,
unless they take care themselves to check the exit status of
the child.
-- man system

* since we go thru sh, that leaves to malware a lot of
opportunities for injection.

* if you go thru the PATH, the caller of your program may inject a
different program than the one you expect.


Of course, you can close all the holes, checks your arguments, empty
the environment, setup your own PATH, etc to keep using safely
system(2), but this is more work than yousing your own restricted
run_program function as above.

If the only reason for changing directories is for wgnuplot to
find test.p, then:

system( "wgnuplot test/test2/test.p" ) ;

would solve the problem. It's also likely to be more portable;
it will work under both Unix and Windows, for example.

The function system has its problems; I myself have a
replacement in my libraries, which results in a version with
known semantics.

So why do you ask?

(IIRC, the problems I was having involved
quoting arguments which contained special characters.) But for
something this simple, it works fine. And if your not concerned
with portability beyond Posix, there's very little reason to use
anything else. (Posix requires that the function execute the
equivalent of "sh -c 'command string'", where sh is a Posix
conformant shell.)

Not exactly. It specifies:

execl(<shell path>, "sh", "-c", command, (char *)0);

Otherwise you would have an unending stream of quoting problems...
 

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

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top