System() question

Discussion in 'C Programming' started by Bob, Dec 6, 2007.

  1. Bob

    Bob Guest

    Howdy,

    Why does a call to system() work by passing the command line string
    supplied to sh -c? This is causing problems when running in a chroot
    environment where no sh is available. Wouldn't it be better for C to
    replace the system() call by a fork()-exec() pair? Is there some
    compiler option that can change the behavior of system()?

    Thanks in advance.
    Bob, Dec 6, 2007
    #1
    1. Advertising

  2. Bob

    santosh Guest

    Bob wrote:

    > Howdy,
    >
    > Why does a call to system() work by passing the command line string
    > supplied to sh -c? This is causing problems when running in a chroot
    > environment where no sh is available. Wouldn't it be better for C to
    > replace the system() call by a fork()-exec() pair? Is there some
    > compiler option that can change the behavior of system()?
    >
    > Thanks in advance.


    Fork() and exec() are not present on many systems where C is
    implemented. Also they are not as generic as system(). As far as the C
    Standard is concerned, everthing about the argument to system() is
    implementation specific.

    You can always find out if a shell is available by doing:

    int rc = system(NULL);
    if (rc) { /* shell present */ }
    else { /* no shell */ }
    santosh, Dec 6, 2007
    #2
    1. Advertising

  3. Bob

    Flash Gordon Guest

    santosh wrote, On 06/12/07 22:20:
    > Bob wrote:
    >
    >> Howdy,
    >>
    >> Why does a call to system() work by passing the command line string
    >> supplied to sh -c? This is causing problems when running in a chroot
    >> environment where no sh is available. Wouldn't it be better for C to
    >> replace the system() call by a fork()-exec() pair? Is there some
    >> compiler option that can change the behavior of system()?
    >>
    >> Thanks in advance.

    >
    > Fork() and exec() are not present on many systems where C is
    > implemented. Also they are not as generic as system(). As far as the C
    > Standard is concerned, everthing about the argument to system() is
    > implementation specific.
    >
    > You can always find out if a shell is available by doing:
    >
    > int rc = system(NULL);
    > if (rc) { /* shell present */ }
    > else { /* no shell */ }


    Not quite everything is system specific, and the answer to why system()
    is having a problem if no shell is available is *not* system specific.

    The standard *requires* that the system call pass the parameter to the
    command processor (AKA shell), so if there is no shell available then it
    is required to fail. Whether some other behaviour would be better is
    another matter.

    If you want the behaviour of fork/exec and your implementation provides
    them (or some equivalent) then I recommend using these system specific
    functions. Note that another standard (POSIX) might give the guarantees
    required, if so then for information on using them see
    comp.unix.programmer or some other group appropriate to the system(s) of
    interest.
    --
    Flash Gordon
    Flash Gordon, Dec 6, 2007
    #3
  4. In article <>,
    Bob <> wrote:

    >Why does a call to system() work by passing the command line string
    >supplied to sh -c? This is causing problems when running in a chroot
    >environment where no sh is available. Wouldn't it be better for C to
    >replace the system() call by a fork()-exec() pair? Is there some
    >compiler option that can change the behavior of system()?


    As far as the C standard is concerned, it could work either way.

    But in practice it's much more useful if commands passed to system()
    are treated the same way as commands typed to the shell. For example,
    I expect system("rm *") to remove all the files in the directory,
    which wouldn't happen if you just executed the "rm" program with with
    argv[1] set to "*".

    If you're writing code to work in a chroot()ed environment you quite
    likely want to take special care with any commands you execute: I
    suggest writing your own system()-like function that uses fork()
    and exec() (and probably wait()) directly.

    -- Richard
    --
    :wq
    Richard Tobin, Dec 6, 2007
    #4
  5. In article <-gordon.me.uk>,
    Flash Gordon <> wrote:

    >The standard *requires* that the system call pass the parameter to the
    >command processor (AKA shell), so if there is no shell available then it
    >is required to fail. Whether some other behaviour would be better is
    >another matter.


    Unix has several shells available, and no doubt so do many other
    operating systems. The standard doesn't specify which one to use - it
    just refers to "a command processor". If you wrote some code to
    execute commands using fork() and exec(), that would be another
    (trivial) command processor, and using it would satisfy the C
    standard. For most purposes it would be less useful than using
    /bin/sh or $SHELL.

    -- Richard
    --
    :wq
    Richard Tobin, Dec 7, 2007
    #5
  6. Bob

    Flash Gordon Guest

    Richard Tobin wrote, On 07/12/07 00:03:
    > In article <-gordon.me.uk>,
    > Flash Gordon <> wrote:
    >
    >> The standard *requires* that the system call pass the parameter to the
    >> command processor (AKA shell), so if there is no shell available then it
    >> is required to fail. Whether some other behaviour would be better is
    >> another matter.

    >
    > Unix has several shells available, and no doubt so do many other
    > operating systems. The standard doesn't specify which one to use - it
    > just refers to "a command processor". If you wrote some code to
    > execute commands using fork() and exec(), that would be another
    > (trivial) command processor, and using it would satisfy the C
    > standard. For most purposes it would be less useful than using
    > /bin/sh or $SHELL.


    Yes, that is all true. However the OP was specifically talking about
    running the program in an environment without a command processor.
    --
    Flash Gordon
    Flash Gordon, Dec 7, 2007
    #6
  7. >>> The standard *requires* that the system call pass the parameter to the
    >>> command processor (AKA shell), so if there is no shell available then it
    >>> is required to fail. Whether some other behaviour would be better is
    >>> another matter.

    >>
    >> Unix has several shells available, and no doubt so do many other
    >> operating systems. The standard doesn't specify which one to use - it
    >> just refers to "a command processor". If you wrote some code to
    >> execute commands using fork() and exec(), that would be another
    >> (trivial) command processor, and using it would satisfy the C
    >> standard. For most purposes it would be less useful than using
    >> /bin/sh or $SHELL.

    >
    >Yes, that is all true. However the OP was specifically talking about
    >running the program in an environment without a command processor.


    The minimum needed under UNIX to run a command line is to parse the
    command line (possibly just splitting at every white-space character,
    with no quoting conventions whatever, and no i/o redirection), form
    argv[], and call fork() and some form of exec*(). That arguably
    *IS* a command processor (for that matter, you can argue that exec()
    alone is a command processor), even if it isn't a separate program.
    It might even take less code than the existing system() function
    does in the C library.
    Gordon Burditt, Dec 7, 2007
    #7
  8. Bob

    James Kuyper Guest

    Gordon Burditt wrote:
    ....
    > The minimum needed under UNIX to run a command line is to parse the
    > command line (possibly just splitting at every white-space character,
    > with no quoting conventions whatever, and no i/o redirection), form
    > argv[], and call fork() and some form of exec*(). That arguably
    > *IS* a command processor


    It could be a command processor. I don't think it is one; because it
    hasn't been written, yet. You could write it pretty easily though.
    James Kuyper, Dec 7, 2007
    #8
  9. >> The minimum needed under UNIX to run a command line is to parse the
    >> command line (possibly just splitting at every white-space character,
    >> with no quoting conventions whatever, and no i/o redirection), form
    >> argv[], and call fork() and some form of exec*(). That arguably
    >> *IS* a command processor

    >
    >It could be a command processor. I don't think it is one; because it
    >hasn't been written, yet. You could write it pretty easily though.


    I think something like this, although a little more sophisticated
    (like knowing how to strip quotes off of quoted strings), was written
    as an optimization. If the command doesn't contain any of certain
    shell metacharacters (pipe, I/O redirection, $, *, {}, (), ?, \, and
    ~ at least would force use of a shell), it would use this instead.
    I believe at least alphanumerics, white space, - and / were safe.
    Otherwise it would use a shell.

    I can't recall what used it, though: I'm thinking it was one of
    sendmail, exim, certain versions of make, or perl. I learned about
    it because the optimization had some side effect related to environment
    variables that was tripping me up somehow.


    exec() itself could be considered as a command procesor which accepts
    the name of the program to run as the command (no arguments allowed).
    Very, very crude, but the standard doesn't require much.
    Gordon Burditt, Dec 7, 2007
    #9
  10. Bob <> writes:
    > Why does a call to system() work by passing the command line string
    > supplied to sh -c? This is causing problems when running in a chroot
    > environment where no sh is available. Wouldn't it be better for C to
    > replace the system() call by a fork()-exec() pair? Is there some
    > compiler option that can change the behavior of system()?


    The C standard doesn't specify sh -c; it merely requires the string to
    be passed to a "command processor". (Also standard C doesn't specify
    fork or exec.)

    POSIX specifies "sh -c". You might try asking in
    comp.unix.programmer. (Note that the job of splitting the command's
    arguments on whitespace, handling wildcards, etc. is passed off to the
    shell; a function that uses fork/exec directly would have to reproduce
    that functionality.)

    --
    Keith Thompson (The_Other_Keith) <>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Dec 7, 2007
    #10
  11. Bob

    Bob Guest

    On 7 Dec 2007 at 7:45, Keith Thompson wrote:
    > Bob <> writes:
    >> Why does a call to system() work by passing the command line string
    >> supplied to sh -c? This is causing problems when running in a chroot
    >> environment where no sh is available. Wouldn't it be better for C to
    >> replace the system() call by a fork()-exec() pair? Is there some
    >> compiler option that can change the behavior of system()?

    >
    > The C standard doesn't specify sh -c; it merely requires the string to
    > be passed to a "command processor". (Also standard C doesn't specify
    > fork or exec.)
    >
    > POSIX specifies "sh -c". You might try asking in
    > comp.unix.programmer. (Note that the job of splitting the command's
    > arguments on whitespace, handling wildcards, etc. is passed off to the
    > shell; a function that uses fork/exec directly would have to reproduce
    > that functionality.)


    But wouldn't it be better to first try "sh -c" and then if no shell is
    available fall back to fork-exec, rather than failing the system() call?
    Bob, Dec 7, 2007
    #11
  12. In article <>,
    Bob <> wrote:
    >But wouldn't it be better to first try "sh -c" and then if no shell is
    >available fall back to fork-exec, rather than failing the system() call?


    Only if the fork()/exec() version does exactly the same thing;
    executing the wrong command could be disastrous.

    And if it does do exactly the same thing, why not use it in the first
    place?

    -- Richard
    --
    :wq
    Richard Tobin, Dec 7, 2007
    #12
  13. >> POSIX specifies "sh -c". You might try asking in
    >> comp.unix.programmer. (Note that the job of splitting the command's
    >> arguments on whitespace, handling wildcards, etc. is passed off to the
    >> shell; a function that uses fork/exec directly would have to reproduce
    >> that functionality.)

    >
    >But wouldn't it be better to first try "sh -c" and then if no shell is
    >available fall back to fork-exec, rather than failing the system() call?


    No, unless you've got a *complete* shell emulation in the library, and if
    that's the case, why bother loading another program when it's already
    loaded? Use the emulation all the time.

    fork-exec is missing a critical piece: turning a command string
    into a program name and an argv[] array of command arguments. Along
    with that go a bunch of other (POSIX) features invoked by the
    parsing: I/O redirection, sequential command execution, pipelines,
    wildcard expansion, shell variables, argument quoting, etc.

    You can do a simple-minded implementation, for example, if the
    command consists entirely of alphanumeric characters, white space,
    hyphen, and slash, you can get pretty close with a parser that just
    breaks arguments at white space, then does fork()/execvp().
    This can go horribly wrong if the command intended to use some
    of the features not implemented.

    Example:
    rm -f foo.o ; cc -c foo.c ; cc -o foo foo.o -lbar ; ./foo
    when run by the simple-minded parser runs "rm" with lots of arguments
    and will end up deleting foo.c, along with complaining about some
    probably-nonexistent files.
    Gordon Burditt, Dec 7, 2007
    #13
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. sfunds sfunds
    Replies:
    9
    Views:
    8,686
  2. Charles A. Lackman

    Streaming with System.IO and System.Net

    Charles A. Lackman, Dec 8, 2004, in forum: ASP .Net
    Replies:
    4
    Views:
    539
    Richard Grimes [MVP]
    Jan 15, 2005
  3. Mark Miller
    Replies:
    1
    Views:
    1,065
    Mark Miller
    Jul 18, 2003
  4. Matt
    Replies:
    2
    Views:
    827
    Matt Getting
    Jul 24, 2003
  5. Rhino
    Replies:
    0
    Views:
    1,632
    Rhino
    Nov 13, 2004
Loading...

Share This Page