5

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!

Semonit
  • 379
  • 3
  • 14
  • 1
    I'm not aware that embedded Perl uses a working directory different from the process where it is embedded. Isn't this working directory just the same as the current working directory for the whole process which can be queried with [getcwd](https://linux.die.net/man/3/getcwd) in C and changed with [chdir](http://man7.org/linux/man-pages/man2/chdir.2.html) within the C program? – Steffen Ullrich Sep 01 '17 at 12:57
  • No, it doesn't seems so. I tried this, but bizarrely that has no effect on the script's working directory. I was using Qt5 functionality to change the directroy by the way. But I cant't imagine any side-effects with Qt5. – Semonit Sep 01 '17 at 13:19
  • See my response where I simply use the `chdir` to change the working directory and it affects the Perl code running afterwards. I have no idea what you've exactly tried but it works for me as expected. – Steffen Ullrich Sep 01 '17 at 14:18
  • 1
    Needs more [mcve]. – melpomene Sep 01 '17 at 14:27
  • 1
    The CWD is a property of a process. Perl doesn't have any CWD to set. – ikegami Sep 01 '17 at 18:29
  • What directory are you trying to set, and what is the actual directory set (full paths)? – CristiFati Jan 23 '18 at 21:56

2 Answers2

4

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.

Borodin
  • 126,100
  • 9
  • 70
  • 144
Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • That's exactly what I've done in my code. Right before perl_run() I've set the working directory to what I wanted. But the perl script, still had the same directory as before. Note, the perl_run() including the chdir is executed in a separate thread. Maybe there's something to consider? – Semonit Sep 08 '17 at 08:47
  • @Karl: On most systems all threads share the same working directory, i.e. it is not per thread. See also https://stackoverflow.com/questions/9082804/precisely-what-owns-the-current-working-directory – Steffen Ullrich Sep 08 '17 at 09:22
1

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.

Zac B
  • 3,796
  • 3
  • 35
  • 52
  • hmmm, just tried to set the environments PWD to the path. didn't work. – Semonit Sep 01 '17 at 14:15
  • @Karl, Zac is saying you may need to set *both*. – ikegami Sep 01 '17 at 18:23
  • 2
    @Zac B, While it may that some programs that expect to be run from the shell use `$ENV{PWD}`, that's not a safe assumption to make. Perl programs using `$ENV{PWD}` are buggy. – ikegami Sep 01 '17 at 18:28
  • Agreed. I updated my answer to reflect that. I think it is still something good to check, given its ubiquity in many Perl programs (e.g. the `Cwd` module uses `PWD`). Thanks! – Zac B Sep 06 '17 at 18:33