[comp.unix.wizards] What is a good way to do general execs?

friedl@mtndew.UUCP (Stephen J. Friedl) (06/08/90)

Hi folks,

    We have an application where a background daemon sometimes
has to run a user-supplied program with my arguments, and I am trying
to find a good way to do it.  I don't want to use system(3) because
I want to have control over the fork/exec chain (I catch SIGCLD)
and I just don't like using system anyway.

     Execv works great if I'm running a binary, but it doesn't
like to run shell scripts directly (this is Sys V).  To get around
this I try the following:

	i = 0;
	argv[i++] = "/bin/sh";
	argv[i++] = userprog;
	argv[i++] = myarg_1;
	argv[i++] = myarg_2;
	argv[i++] = you_get_the_idea;
	argv[i++] = NULL;

	execv(argv[1], argv+1);
	execv(argv[0], argv+0);
	error("cannot run userprog %s (errno = %d)", userprog, errno);

     Here I try to run the user's program directly, and if it
doesn't work then I try running with with a shell.  The problem
is that this looks too easy.

     I have thought about this from a handful of directions and
it seems to be workable.  Because the first argument is a
filename, I don't have to worry about the string containing scam
characters such a ! or ; or others.  I provide the other args and
presumably I trust myself :-).

     Does anybody see anything wrong with this? 

     Steve

-- 
Stephen J. Friedl, KA8CMY / Software Consultant / Tustin, CA / 3B2-kind-of-guy
+1 714 544 6561  / friedl@mtndew.Tustin.CA.US  / {uunet,attmail}!mtndew!friedl

"I will defend to your death my right to my opinion" - me

limes@ouroborous.Sun.COM (Greg Limes) (06/09/90)

In article <438@mtndew.UUCP> friedl@mtndew.UUCP (Stephen J. Friedl) writes:
>	i = 0;
>	argv[i++] = "/bin/sh";
>	argv[i++] = userprog;
>
>	execv(argv[1], argv+1);
>	execv(argv[0], argv+0);
>	error("cannot run userprog %s (errno = %d)", userprog, errno);

what if "userprog" is a CSH script, or a PERL script, or an AWK
script, or ... [you get the idea]

Of course, if your system does not support scripts for anything
other than /bin/sh this should work OK.

You might also want to adjust this a bit, so the user's .profile
is not read into the shell [speeds up startup]:

	i = 0;
	argv[i++] = "/bin/sh";
	argv[i++] = "-";
	argv[i++] = userprog;

	execv(argv[2], argv+2);
	execv(argv[0], argv+0);
	error("cannot run userprog %s (errno = %d)", userprog, errno);

DISCLAIMER: I rarely work under System V, so my point of view may
be a little off base; SunOS 4.1 may be "the bridge to SysVr4", but
it still gives me all the goodies that I am all to accustomed to :-)
without warning me when something ain't SysV'ish.
--
Greg Limes   limes@sun.com   ...!sun!limes   73327,2473   CGDB02A [choose one]
		A Fool and his Money are soon Partying ...

martin@mwtech.UUCP (Martin Weitzel) (06/09/90)

In article <438@mtndew.UUCP> friedl@mtndew.UUCP (Stephen J. Friedl) writes:
[needs to exec a user supplied program, but has to avoid "system"]
>     Execv works great if I'm running a binary, but it doesn't
>like to run shell scripts directly (this is Sys V).  To get around
>this I try the following:

Use "execvp". The "p" stands not only for pathname search, but also
will invoke a shell if the supplied program is in reality a script.
Eventually you may want to set PATH with `putenv' to make execvp
search the desired directories (only).

Small flame concerning choice of groups: How about a *first* try
with comp.unix.questions - you can have allways a second try with
c.u.w, but experience shows you may well receive the attention
of a wizard in c.u.q. At most make a crosspost but leave followups
to c.u.q. I felt tempted to redirect followups, but as I don't
appreciate to have threads pop up "out of nothing" I left it here.
-- 
Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83

guy@auspex.auspex.com (Guy Harris) (06/12/90)

>You might also want to adjust this a bit, so the user's .profile
>is not read into the shell [speeds up startup]:

Nope.  You must be assuming that a lot of "#! /bin/sh" headers have
"#! /bin/sh -" because the author didn't want ".profile" sourced,
presumably along lines similar to "#! /bin/csh -f".

That's not what the "-" does; it just makes sure that, if the name of
the script begins with "-" (e.g., because somebody's trying to break
your set-UID shell script - yes, there are other problems with set-UID
shell scripts, but...), the shell does *not* treat it as a flag
argument.  In that regard, it's similar to the "-b" flag in the C shell. 

The Bourne shell sources ".profile" *only* for login shells (just as the
C shell sources ".login" only for login shells - the "-f" in
"#! /bin/csh -bf" is there to prevent it from sourcing your ".cshrc").

leo@ehviea.ine.philips.nl (Leo de Wit) (06/12/90)

In article <3449@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:
|>You might also want to adjust this a bit, so the user's .profile
|>is not read into the shell [speeds up startup]:
|
|Nope.  You must be assuming that a lot of "#! /bin/sh" headers have
|"#! /bin/sh -" because the author didn't want ".profile" sourced,
|presumably along lines similar to "#! /bin/csh -f".
|
|That's not what the "-" does; it just makes sure that, if the name of
|the script begins with "-" (e.g., because somebody's trying to break
|your set-UID shell script - yes, there are other problems with set-UID
|shell scripts, but...), the shell does *not* treat it as a flag
|argument.  In that regard, it's similar to the "-b" flag in the C shell. 
|
|The Bourne shell sources ".profile" *only* for login shells (just as the
|C shell sources ".login" only for login shells - the "-f" in
|"#! /bin/csh -bf" is there to prevent it from sourcing your ".cshrc").

Nope. For the man page for 'sh': 
 
     Invocation. 
     If the first character of argument zero is -, commands are 
     read from $HOME/.profile, if such a file exists.   
 
In fact this documentation is not right either, since .profile is read
(in the current directory instead of $HOME). Login shells are started
with - prepended to the basename of their name as argv[0], so they will
read $HOME/.profile.

From the csh man page:

     Argument list processing

     If argument 0 to the shell is `-' then this is a login
     shell. 

What it should say: if argv[0] of the shell starts with a '-', it is
treated as a login shell: $HOME/.login is sourced (cause that is what
happens).

    Leo.

guy@auspex.auspex.com (Guy Harris) (06/14/90)

 >|The Bourne shell sources ".profile" *only* for login shells (just as the
 >|C shell sources ".login" only for login shells - the "-f" in
 >|"#! /bin/csh -bf" is there to prevent it from sourcing your ".cshrc").
 >
 >Nope. For the man page for 'sh': 
 > 
 >     Invocation. 
 >     If the first character of argument zero is -, commands are 
 >     read from $HOME/.profile, if such a file exists.   

I consider "login shell" basically short for "shell with the first
character of argument zero a '-'" (which means that any shell fired up
by "login" is a login shell, but so are shells fired up by e.g.  "su"
when run with the appropriate flag).  I considered the more detailed
explanation unnecessary and extraneous in this case.... 

meissner@osf.org (Michael Meissner) (06/14/90)

In article <3459@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris)
writes:

|  >|The Bourne shell sources ".profile" *only* for login shells (just as the
|  >|C shell sources ".login" only for login shells - the "-f" in
|  >|"#! /bin/csh -bf" is there to prevent it from sourcing your ".cshrc").
|  >
|  >Nope. For the man page for 'sh': 
|  > 
|  >     Invocation. 
|  >     If the first character of argument zero is -, commands are 
|  >     read from $HOME/.profile, if such a file exists.   
| 
| I consider "login shell" basically short for "shell with the first
| character of argument zero a '-'" (which means that any shell fired up
| by "login" is a login shell, but so are shells fired up by e.g.  "su"
| when run with the appropriate flag).  I considered the more detailed
| explanation unnecessary and extraneous in this case.... 

On the same thread, I sometimes want to create a login shell when I'm
not logging in, and not all shell's have a -login switch like bash
does.  You can get around this by symlinking the appropriate shell to
-<shell> in your executable directory, ie:

lrwxrwxr-x  1 meissner       19 Jun  2 14:11 -ksh -> /usr/bin/ksh
lrwxrwxr-x  1 meissner        7 May 16 15:13 -sh -> /bin/sh
lrwxrwxr-x  1 meissner        8 May 16 15:13 -sh5 -> /bin/sh5
--
Michael Meissner	email: meissner@osf.org		phone: 617-621-8861
Open Software Foundation, 11 Cambridge Center, Cambridge, MA

Catproof is an oxymoron, Childproof is nearly so

dik@cwi.nl (Dik T. Winter) (06/15/90)

In article <3459@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:
 >  >     Invocation. 
 >  >     If the first character of argument zero is -, commands are 
 >  >     read from $HOME/.profile, if such a file exists.   
 > 
 > I consider "login shell" basically short for "shell with the first
 > character of argument zero a '-'" (which means that any shell fired up
 > by "login" is a login shell, but so are shells fired up by e.g.  "su"
 > when run with the appropriate flag).  I considered the more detailed
 > explanation unnecessary and extraneous in this case.... 

It is indeed extraneous in the context; but I think your position is flawed.
Try:
	PATH=$PATH:.
	ln -s /bin/sh -sh
	-sh
Now, when you consider this to be a login shell, it becomes another matter,
but I think that it is non-intuitive naming.
--
dik t. winter, cwi, amsterdam, nederland
dik@cwi.nl

guy@auspex.auspex.com (Guy Harris) (06/16/90)

 >It is indeed extraneous in the context; but I think your position is flawed.
 >Try:
 >	PATH=$PATH:.
 >	ln -s /bin/sh -sh
 >	-sh
 >Now, when you consider this to be a login shell, it becomes another matter,
 >but I think that it is non-intuitive naming.

If somebody really wants to do that, they presumably know what they're
doing.  The majority of shells invoked with "-" at the front of argv[0]
are almost certainly shells fired up from logins, and the second most
common set of such shells are fired up from "su"s with the appropriate
arguments; I considered the exceptions to be rare enough that confusion
from saying "login shell" rather than "shell fired up with '-' in front
of its first argument" to be unlikely enough that it wasn't worth using
the longer phrase and then explaining that "login" fires shells up with
"-" in front of the first argument....