Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does one pass includes to execvp that's running a perl script?

Tags:

c

perl

RHEL6

In C, how does one pass includes to execvp which in turn runs a perl executable ? (this is a means to replace missing translation of PERL5LIB to @INC when taint mode is on)

This question is looking for a working implementation of an answer provided by mob to... Why does @INC change when setgid-bit of C wrapper around perl script change?.

I'm wrapping a perl script execution in a C program that uses execvp to call the perl. Because taint mode is enabled, @INC will not be loaded with the content of $PERL5LIB, so I have pass the paths to the perl executable using "-I". perlsec says this is possible (ref the answer provided by mob in the note sited above).

My attempts to do this have failed. My C program attempted to run the perl executable as the first arg to execvp and then the perl script as part of the argument list. The includes were made part of the perl script executable statement. Here's the example...

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
  char **args;  /*args will be passed to execvp.  prepend perl executable*/

  args=malloc(3*sizeof(char*));

  args[0]=malloc(sizeof("/tools/bin/perl -I/proj/perlmods")+1);
  strcpy(args[0],"/tools/bin/perl -I/proj/perlmods");

  args[1]=malloc(sizeof("/home/me/the.pl")+1);
  strcpy(args[1],"/home/me/the.pl");

  args[2]=NULL;

  execvp("/tools/bin/perl",args);

}

The perl script is simply...

use html_mail;
print "In my.pl\n";
exit;

/proj/perlmods has html_mail.pm

A straight out perl execution at the linux prompt using -I works...

% /tools/bin/perl -I /proj/perlmods /home/me/my.pl
In my.pl

But running the C binary does not. It complains that the perl module can't be found. If, however, /proj/perlmods is put in PERL5LIB, then it does work. So I think args is good as far as the perl script being in args[1].

I believe the include statement I threw into args is being ignored. If I stick it as a suffix to the perl executable call in the execvp...

  execvp("/tools/bin/perl -I /proj/perlmods",args);

...the C program fails, so I don't think it belongs there. If I put the include as part of the perl script call....

  strcpy(args[1],"/home/me/the.pl -I /proj/perlmods");

... it fails. If I add it as a new element of args (args[3]), it just gets passed as an arg to the perl script and has no affect.

I looked at execvpe, but that just looks like a means to set env vars.

Question is, how does one actually pass the include information to the execvp ?

like image 890
daveg Avatar asked Jan 02 '23 14:01

daveg


2 Answers

You need each argument to be a separate entry in args. Try this:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int
main(int argc, char *argv[])
{
    char *args[4];       /* args will be passed to execvp.  prepend perl executable */

    args[0] = "/tools/bin/perl";
    args[1] = "-I/proj/perlmods";
    args[2] = "/home/me/the.pl";
    args[3] = NULL;

    execvp(args[0], args);

}
like image 184
Craig Estey Avatar answered Jan 05 '23 17:01

Craig Estey


You're doing something wrong if you're using -I. The script's executer shouldn't have to care about where the script's libraries are located.

  • If /proj/perlmods is used by multiple applications, you should add the following to your login script:

    export PERL5LIB=/proj/perlmods
    
  • If /proj/perlmods is only used by that one Perl program, add the following to the Perl program:

    use lib qw( /proj/perlmods );
    

Then, the C program becomes

char *args[2];                  # Or char **args = malloc(2 * sizeof(char*));
args[0] = "/home/me/the.pl";    # No need to duplicate the string; just copy the ptr.
args[1] = NULL;

execvp(args[0], args);

instead of

char *args[4];                  # Or char **args = malloc(4 * sizeof(char*));
args[0] = "/tools/bin/perl";
args[1] = "-I/proj/perlmods";
args[2] = "/home/me/the.pl";
args[3] = NULL;

execvp(args[0], args);
like image 22
ikegami Avatar answered Jan 05 '23 17:01

ikegami