Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

embedded perl in C - set working directory

Tags:

c

perl

How to tell the embedded perl in C what's it's working directory?

It seems that it's set to the directory of the executable in which embedded perl is used. Setting the directory from outside before invoking the embedded perl stuff doesn't change it's behaviour.

A possible workaround would be popping in "chdir " before the actual script is started but I don't like that.

My code technically looks like this:

PERL_SYS_INIT3(NULL, NULL, NULL);
my_perl = perl_alloc();
PERL_SET_CONTEXT(my_perl);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
PERL_SET_CONTEXT(my_perl);
PL_perl_destruct_level = 1;
perl_construct(my_perl);

int argc = 2;
char** argv = new char*[argc];
argv[0] = new char[4096];
argv[0][0] = '\0';
argv[1] = scriptFileName;

PERL_SET_CONTEXT(my_perl);
perl_parse(my_perl, xs_init, argc, argv, (char **)NULL);
perl_run(my_perl)

PL_perl_destruct_level = 1;
PERL_SET_CONTEXT(my_perl);
perl_destruct(my_perl);
perl_free(my_perl);
my_perl = NULL;

The above outlined code is running in separate threads. Maybe there's something to consider?

Thanks for any hint!

like image 854
Semonit Avatar asked Sep 01 '17 12:09

Semonit


2 Answers

There is no separate working directory for Perl. It just takes the one currently active in the process which can be changed with chdir from inside the C program.


To prove this I've tried a small example program by using the code from Adding a Perl interpreter to your C program in the official documentation. I've only added a single chdir call before executing perl_run:

#include <EXTERN.h>               /* from the Perl distribution     */
#include <perl.h>                 /* from the Perl distribution     */

static PerlInterpreter *my_perl;  /***    The Perl interpreter    ***/

int main(int argc, char **argv, char **env)
{
       PERL_SYS_INIT3(&argc, &argv, &env);
       my_perl = perl_alloc();
       perl_construct(my_perl);
       PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
       perl_parse(my_perl, NULL, argc, argv, (char **) NULL);

       /***** HERE IT CHANGES THE WORKING DIRECTORY ******/
       chdir("/"); 

       perl_run(my_perl);
       perl_destruct(my_perl);
       perl_free(my_perl);
       PERL_SYS_TERM();
}

When starting the following small Perl program to check the working directory it shows exactly the working directory which I've set in my C code:

use Cwd 'getcwd';  
print getcwd(), "\n";

So there is no separate working directory for Perl: it just takes the one currently set in the process.

like image 73
Steffen Ullrich Avatar answered Nov 07 '22 01:11

Steffen Ullrich


Doing chidir in the surrounding C may not be enough, unless you also ensure that the PWD field in the environment of the surrounding code is also updated. Otherwise, that variable may be inherited as $ENV{PWD} by your perl, since you're passing NULL as the final argument to perl_parse. Not 100% sure of this though.

Non-shell code should not be relying on the PWD environment variable, as @ikegami pointed out. However, some poorly written code may depend on it, so it's worth checking.

like image 1
Zac B Avatar answered Nov 07 '22 00:11

Zac B