system shell command

S

Siemel Naran

Hi. I'm writing a command shell that reads commands from standard input.
At this point I have the command in a std::string. Now I want to execute
this command in the shell. From the Borland newsgroups I learned that there
is a function in stdlib.h called system.

int system(const char *command);

First question, is the system command ANSI compliant. Because I include
<cstdlib> and write std::system(command.c_str()); it looks like an ANSI C++
function. But the documentation says it's in POSIX and Win32 only, not in
ANSI C and ANSI C++.

Second, and more important, the system command does not appear to respond to
the cd command. The call std::system("cd ..") runs without error, but does
not change the working directory, as can be evidenced by calling getcwd of
dir.h before and after the call to system. The reason is that the system
command runs within a new child process, and within that the process that
directory does probably change. After all, if one runs system("exit"), one
wants the child process to exit, not the parent process.

So how can I get the system command to change the directory of the parent
process? Do I have to parse the command, and look for "cd xyz" and change
the directory to "xyz" using chdir of dir.h? Or is there some way to create
a system object as a local variable, so that it can know it's state (ie.
it's directory, environment variables, etc)? If this is the wrong
newsgroup, can someone please let me know the right newsgroup?

Thanks.
 
D

Derk Gwen

# Hi. I'm writing a command shell that reads commands from standard input.
# At this point I have the command in a std::string. Now I want to execute
# this command in the shell. From the Borland newsgroups I learned that there
# is a function in stdlib.h called system.
#
# int system(const char *command);
#
# First question, is the system command ANSI compliant. Because I include
# <cstdlib> and write std::system(command.c_str()); it looks like an ANSI C++
# function. But the documentation says it's in POSIX and Win32 only, not in
# ANSI C and ANSI C++.

system(...) is ANSI C, but its evaluation is system specific. So check your
system documentation. On unices, the system function calls a shell to
evaluate the command; using that on a unix is sort of like cheating (or
leads in to endless recursion if it tries to use your shell to evaluate the
string).

# Second, and more important, the system command does not appear to respond to
# the cd command. The call std::system("cd ..") runs without error, but does
# not change the working directory, as can be evidenced by calling getcwd of
# dir.h before and after the call to system. The reason is that the system

On unices, the cd only changes the directory of the current process; the shell
that interprets the "cd ..." string is a separate process and changes in its
directory do not affect the directory of the process evaluating the
system(...) function. Unix shells recognise and interpret the cd command
directly in the shell itself.

if (strcmp(command,"cd")==0) {
change current directory(rest(command));
}else {
system(command);
}
 
M

Martin Ambuhl

Siemel said:
Hi. I'm writing a command shell that reads commands from standard input.
At this point I have the command in a std::string.

At this point, your post has become off-topic in comp.lang.c. std::string
is part of C++ and not C. It is good that you posted to comp.lang.c++, but
your crossposting to a newsgroup where your question cannot be topical
suggests that you have neither followed the newsgroups nor checked the FAQs
before posting. This is a sin.
Now I want to execute
this command in the shell. From the Borland newsgroups I learned that there
is a function in stdlib.h called system.

int system(const char *command);

Since you are using C++, you want to use the C++ header <cstdlib> and not
the C header said:
First question, is the system command ANSI compliant.

It is part of ISO (&ANSI) C and C++. The _argument_ has no meaning apart
from the implementation, OS, in which you use it, however. Its use is,
even though standard, not portable.
 
T

Ted Davis

Hi. I'm writing a command shell that reads commands from standard input.
At this point I have the command in a std::string. Now I want to execute
this command in the shell. From the Borland newsgroups I learned that there
is a function in stdlib.h called system.

int system(const char *command);

First question, is the system command ANSI compliant. Because I include
<cstdlib> and write std::system(command.c_str()); it looks like an ANSI C++
function. But the documentation says it's in POSIX and Win32 only, not in
ANSI C and ANSI C++.

Second, and more important, the system command does not appear to respond to
the cd command. The call std::system("cd ..") runs without error, but does
not change the working directory, as can be evidenced by calling getcwd of
dir.h before and after the call to system. The reason is that the system
command runs within a new child process, and within that the process that
directory does probably change. After all, if one runs system("exit"), one
wants the child process to exit, not the parent process.

So how can I get the system command to change the directory of the parent
process? Do I have to parse the command, and look for "cd xyz" and change
the directory to "xyz" using chdir of dir.h? Or is there some way to create
a system object as a local variable, so that it can know it's state (ie.
it's directory, environment variables, etc)? If this is the wrong
newsgroup, can someone please let me know the right newsgroup?


No, the first - and most important - question in this MSDOS group is
"how does system() execute commands in DOS and DOS emulators?". The
answer is that it invokes the default command processor (shell) and
passes it the command. If your program is to be the shell, then it
has to process all the internal command processor commands that you
support as well as loading and launching any external executables - if
you wnat to use CD, then your program must intrepret it and invoke the
necessary interrupt functons to accomplish the underlying tasks. If
%COMSPEC% points to your program, which it would have to if it were
the shell, then system() reinvokes your program recursively.


T.E.D. ([email protected])
SPAM filter: Messages to this address *must* contain "T.E.D."
somewhere in the body or they will be automatically rejected.
 
K

Karl Heinz Buchegger

Siemel said:
Hi. I'm writing a command shell that reads commands from standard input.
At this point I have the command in a std::string. Now I want to execute
this command in the shell. From the Borland newsgroups I learned that there
is a function in stdlib.h called system.

int system(const char *command);

If your program is using system(), then you are not writing a command shell.
system() starts the command shell and gives it the command to execute. So
it is your program that could be called by system() and not the other way
round.
 
S

Siemel Naran

Derk Gwen said:
"Siemel Naran" <[email protected]> wrote:

Thanks to all who replied. My apologies for making the code run in C++
only. I'll try in C now.
# Second, and more important, the system command does not appear to respond to
# the cd command. The call std::system("cd ..") runs without error, but does
# not change the working directory, as can be evidenced by calling getcwd of
# dir.h before and after the call to system. The reason is that the system

On unices, the cd only changes the directory of the current process; the shell
that interprets the "cd ..." string is a separate process and changes in its
directory do not affect the directory of the process evaluating the
system(...) function. Unix shells recognise and interpret the cd command
directly in the shell itself.

if (strcmp(command,"cd")==0) {
change current directory(rest(command));
}else {
system(command);
}

So is the above the only way to do it?

What I was hoping for is maybe there's a way to open a shell, kind of like
fopen, and get a handle to this shell. Can anyone please let me know if
something like the following exists?

char command[1024];
strcpy(command, "dir");
SHELL * shell = shellopen();
system(shell, command);
char dir[1024];
getdir(shell, dir);
printf("%s", dir);
shellclose(shell);


The problem with
if (strcmp(command,"cd")==0) {
change current directory(rest(command));
}else {
system(command);
}

is that I have to interpret the command to look for the occurrence of "cd".
First problem, some shells let you type many commands on one line seperated
by semicolons like "cd x ; cd y" and now I have to interpret this. And
second, my program will hardcode the string "cd" but different shells may
use a different token to denote change directory (though DOS, BASH, TCSH,
and all the others I've tried do in fact use "cd").

In my program so far, with the exception of the call to system(...), the
whole program is ANSI compliant. As soon as I add the parsing capability
above, my program hardcodes that the change directory command is "cd", and
that there could be many commands seperated by ";".

Basically I wrote a streambuf that does reverse incremental history search,
tab completion, color coding, etc. This streambuf is a replacement for
stdin or std::cin. Now I want to write a program that behaves like a shell
(but it's not really a shell because it does not interpret commands itself).
It will read commands from my special editor, and then run the command in a
shell. The standard MSDOS shell does not do reverse incremental history
search, tab completion, color coding (but BASH has all these cool features).

The structure of my program is

while true {
char command[1024];
mystreambuf(command); // read a command from standard input with reverse
incremental history, etc.
system(command); // oops: if command is "cd .." then the directory of the
shell in which the system command ran does change, but the directory of this
program does not change -- but I want it to change
}

Thanks.
 
D

Derk Gwen

# > if (strcmp(command,"cd")==0) {
# > change current directory(rest(command));
# > }else {
# > system(command);
# > }
#
# So is the above the only way to do it?

On unix and other systems that treat the current directory this way
(and even have a current directory notion), it all comes down to either
this or have each program report back its final environment to its invoker.

If you aren't trying to write a real shell, but this is simply a functional
layer function between a real shell for other clients, then one solution is
to edit the command to reestablish the environment you want, execute the
command, and then extract the environment out again.

For example on unix, you might want to save the environmental variables
and current directory. For bourne shell you can edit the command so
instead of
system("command")
you do something like
system("cd directory; var=value var=value ... "
"command; "
"echo STATUS $? ... ENV $(env) PWD $(pwd) >env.report");
and then open and parse env.report. (Or use popen and have the report piped
back to you.)

Be warned that interpretation of command string to system() is implementation
dependent, and that on unices, it is also shell dependent.
 
D

Dietmar Schindler

Siemel said:
What I was hoping for is maybe there's a way to open a shell, kind of like
fopen, and get a handle to this shell. Can anyone please let me know if
something like the following exists?

char command[1024];
strcpy(command, "dir");
SHELL * shell = shellopen();
system(shell, command);
char dir[1024];
getdir(shell, dir);
printf("%s", dir);
shellclose(shell);

The structure of my program is

while true {
char command[1024];
mystreambuf(command); // read a command from standard input with reverse
incremental history, etc.
system(command); // oops: if command is "cd .." then the directory of the
shell in which the system command ran does change, but the directory of this
program does not change -- but I want it to change
}

Try something like

FILE *shell = popen("sh", "w"); // replace "sh" by the shell you have
fputs(command, shell); // don't forget the \n at the end of command
 
M

mcalhoun

....[snip]....
On unix and other systems that treat the current directory this way
(and even have a current directory notion), it all comes down to
....[snip]....

I discovered that same "new shell" problem when I was trying to invoke
SYSTEM from FORTRAN, noticed a FEROCIOUS amount of disk activity for
each invocation, and finally realized that DOS was ALSO loading a new
copy of COMMAND.COM for each invocation! Talk about slowdown!

So, instead of using SYSTEM, I wrote (using direct INTerrupt calls)
FORTRAN versions of MKDIR, RMDIR, CHDIR, GET/CLR/SET/XFR attributes,
CopyFile, DeleteFile, CompareFiles, etc.), the problem disappeared,
and, although the learning curve seemed steep at the time, I've been
very happy I went to the effort.

--Myron.
 
S

Siemel Naran

I discovered that same "new shell" problem when I was trying to invoke
SYSTEM from FORTRAN, noticed a FEROCIOUS amount of disk activity for
each invocation, and finally realized that DOS was ALSO loading a new
copy of COMMAND.COM for each invocation! Talk about slowdown!

So, instead of using SYSTEM, I wrote (using direct INTerrupt calls)
FORTRAN versions of MKDIR, RMDIR, CHDIR, GET/CLR/SET/XFR attributes,
CopyFile, DeleteFile, CompareFiles, etc.), the problem disappeared,
and, although the learning curve seemed steep at the time, I've been
very happy I went to the effort.

Why don't they have a way to create a shell like fopen.

FILE * file = fopen("abc.txt");
fwrite(file, ...);
fclose(file);
 
J

Joona I Palaste

mcalhoun <[email protected]> scribbled the following
I discovered that same "new shell" problem when I was trying to invoke
SYSTEM from FORTRAN, noticed a FEROCIOUS amount of disk activity for
each invocation, and finally realized that DOS was ALSO loading a new
copy of COMMAND.COM for each invocation! Talk about slowdown!
So, instead of using SYSTEM, I wrote (using direct INTerrupt calls)
FORTRAN versions of MKDIR, RMDIR, CHDIR, GET/CLR/SET/XFR attributes,
CopyFile, DeleteFile, CompareFiles, etc.), the problem disappeared,
and, although the learning curve seemed steep at the time, I've been
very happy I went to the effort.

Yikes. Are you sure you're not a chair? (comp.lang.c in-joke)

--
/-- Joona Palaste ([email protected]) ------------- Finland --------\
\-- http://www.helsinki.fi/~palaste --------------------- rules! --------/
"I am not very happy acting pleased whenever prominent scientists overmagnify
intellectual enlightenment."
- Anon
 

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top