rudrak@saphir.cl.bull.fr (Rudrakshala Purushotham) (11/19/90)
I want to provide shell escape feature from a C program. But I am having
some problems with the following code:
shell_escape (command);
char *command;
{
...
char *args [MAX_ARGS];
args [0] = "/bin/sh";
args [1] = "-c";
for (i = 2; i < MAX_ARGS && (s = strtok (command, " \t")); i++)
args [i] = strsave (s);
args [i] = NULL;
if (fork () > 0) {
execv ("/bin/sh", args);
perror ("execv");
_exit (1);
}
wait (&status);
...
I am using C shell and System V. I tried `/bin/ls -l -R' as input to
shell_escape (), my .login file gets executed here and /bin/ls is executed
(without -l -R) options.
Can some body help me with this problem?
Thanks
-- Purushotham
--
R. Purushotham Email: rudrak@saphir.cl.bull.fr
F7 1 D5 BULL SA Tel Off: 34627000 ext 3928
78340 Les Clayes sous Bois FRANCE Tel Res: 34604752
=======================================================================
cs@cci632.UUCP (Craig Schmackpfeffer) (11/20/90)
In article <349@clbull.cl.bull.fr> rudrak@saphir.cl.bull.fr (Rudrakshala Purushotham) writes: >I want to provide shell escape feature from a C program. But I am having >some problems with the following code: > shell_escape (command); ^ | > char *command; > { > char *args [MAX_ARGS]; > > args [0] = "/bin/sh"; > args [1] = "-c"; > > for (i = 2; i < MAX_ARGS && (s = strtok (command, " \t")); i++) > args [i] = strsave (s); > > args [i] = NULL; > > if (fork () > 0) { ^^^ ||| > execv ("/bin/sh", args); > perror ("execv"); > _exit (1); > } > > wait (&status); > >I am using C shell and System V. I tried `/bin/ls -l -R' as input to >shell_escape (), my .login file gets executed here and /bin/ls is executed >(without -l -R) options. >-- Purushotham My first question would be "why re-invent the wheel?". You could use the system() call and not worry about any of the parsing and fork/exec'ing. In fact, it your function cannot work properly because you are having the parent process do the exec instead of the child. You only get the output of ls (with no -l -R) because the shell wants to parse the command itself. Here's how the function could look: shell_escape (command) char *command; { char *args [MAX_ARGS]; args [0] = "/bin/sh"; args [1] = "-c"; args [2] = command; args [3] = NULL; switch (fork()) { case 0: /* child */ execv("/bin/sh", args); case -1: /* fork error or exec fallthrough */ perror("fork/exec"); _exit(1); default: /* parent */ wait(&status); } } -- or better yet -- system(command); Craig = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = Me: Craig Schmackpfeffer (another damn yankee) Disclaimer: Disclaim'er? I don't even know her! Address: ccird1!cs@cci632.UUCP Go Bills! = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
weimer@ssd.kodak.com (Gary Weimer) (11/20/90)
In article <349@clbull.cl.bull.fr> rudrak@saphir.cl.bull.fr (Rudrakshala Purushotham) writes: >I want to provide shell escape feature from a C program. But I am having >some problems with the following code: > > for (i = 2; i < MAX_ARGS && (s = strtok (command, " \t")); i++) > args [i] = strsave (s); > >I am using C shell and System V. I tried `/bin/ls -l -R' as input to >shell_escape (), my .login file gets executed here and /bin/ls is executed >(without -l -R) options. > >Can some body help me with this problem? From the man page for strtok: strtok() considers the string s1 to consist of a sequence of zero or more text tokens separated by spans of one or more characters from the separator string s2. The first call (with pointer s1 specified) returns a pointer to the first character of the first token, and will have written a null character into s1 immediately following the returned token. The function keeps track of its position in the string between separate calls, so that subsequent calls (which must ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ be made with the first argument a NULL pointer) will work ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ through the string s1 immediately following that token. In this way subsequent calls will work through the string s1 until no tokens remain. The separator string s2 may be dif- ferent from call to call. When no token remains in s1, a NULL pointer is returned.
norm@oglvee.UUCP (Norman Joseph) (11/21/90)
In <349@clbull.cl.bull.fr> rudrak@saphir.cl.bull.fr (Rudrakshala Purushotham) writes: >I want to provide shell escape feature from a C program. But I am having >some problems with the following code: You are doing more work than you have to. Your "shell_escape( command )" has already been written for you. It is called "system()". Look for it in your manual. As for your code: > char *args [MAX_ARGS]; > args [0] = "/bin/sh"; > args [1] = "-c"; > for (i = 2; i < MAX_ARGS && (s = strtok (command, " \t")); i++) > args [i] = strsave (s); > args [i] = NULL; To properly use strtok() you only pass it the string you want to parse once. To return successive tokens from the string, the first argument should be a null pointer in all successive calls. The idiom goes something like this: s = strtok( command, " \t" ); args[2] = strsave( s ); for ( i = 3; i < MAX_ARGS && ( s = strtok( NULL, " \t" )); i++ ) args[i] = strsave( s ); args[i] = NULL; -- Norm Joseph - (amanue!oglvee!norm) cgh!amanue!oglvee!norm@dsi.com, or Oglevee Computer Systems, Inc. ditka!oglvee!norm@daver.bungi.com ---<*>--- "Shucking Usenet oysters in pursuit of a pearl." -- Bill Kennedy
md@sco.COM (Michael Davidson) (11/22/90)
In article <349@clbull.cl.bull.fr> rudrak@saphir.cl.bull.fr (Rudrakshala Purushotham) writes: >I want to provide shell escape feature from a C program. But I am having >some problems with the following code: > > shell_escape (command); > char *command; > { > ... > char *args [MAX_ARGS]; > > args [0] = "/bin/sh"; > args [1] = "-c"; > > for (i = 2; i < MAX_ARGS && (s = strtok (command, " \t")); i++) > args [i] = strsave (s); > > args [i] = NULL; > > if (fork () > 0) { > execv ("/bin/sh", args); > perror ("execv"); > _exit (1); > } > > wait (&status); > ... Well, I don't know exactly what is going wrong, but I have a few comments ... First, why not just use "system()"? There *are* sometimes good reasons for NOT using system(), but I don't see any evidence in your code that you are trying to do anything clever that wouldn't work just fine with system(). One comment on the code itself - do you *really* intend that the parent process should be the one that exec's the shell? Something like this would be more appropriate: if ((pid = fork()) == 0) { /* child */ execv("/bin/sh", args); perror("execv"); _exit(1); } else if (pid > 0) { /* parent */ int (*sigint)(); int r; sigint = signal(SIGINT, SIG_IGN); while ((r = wait(&status)) != -1) if (r == pid) break; signal(SIGINT, sigint); } else perror("fork");
mday@iconsys.icon.com (Matt Day) (11/22/90)
Why don't you use the system() routine rather than reinventing the wheel with a routine that essentially does the same thing? system() is more portable to non-UNIX systems and it makes your source code smaller and clearer. -- - Matt Day, Sanyo/Icon, mday@iconsys.icon.com || uunet!iconsys!mday
guy@auspex.auspex.com (Guy Harris) (11/24/90)
>>Can some body help me with this problem? > >From the man page for strtok: That's certainly *A* problem with his code, but far from the most fundamental one, and not the one that's screwing him up. The problem that's screwing him up, as others have noted, is that the "-c" flag to the shell takes *one* argument, which is a character string containing the command to be executed, in its entirety; his use of "strtok()" to try to carve the command up into tokens, and pass each token as an individual argument to the shell, is incorrect - and would still be incorrect even if he were correctly calling "strtok()" with a NULL pointer as the first argument in all but the first call.