Is Perl slower when compiled with DDEBUGGING? - perl

According to this slide from Supercharging Perl - Daina Pettit,
It reads,
Avoid versions of perl compiled with threading or DDEBUGGING unless you know you need them.
I know most distros compile Perl with threading, but my Perl on Debian (as observed with perl -V_ is compiled with -DDEBUGGING=-g does this slow it down?

Perl with debugging enabled is slower.,
Note that a perl built with -DDEBUGGING will be much bigger and will run much, much more slowly than a standard perl.
However, -DDEBUGGING=-g does not enable debugging:
As a convenience, debugging code (-DDEBUGGING) and debugging symbols (-g) can be enabled jointly or separately using a Configure switch, also (somewhat confusingly) named -DDEBUGGING. For a more eye appealing call, -DEBUGGING is defined to be an alias for -DDEBUGGING. For both, the -U calls are also supported, in order to be able to overrule the hints or Policy.sh settings.
and also documented:
Configure -DEBUGGING=-g
Adds -g to optimize, but does not set -DDEBUGGING. (Note: Your system may actually require something like cc -g2. Check your man pages for cc(1) and also any hint file for your system.)
You can test status with: perl -D, if you see the following you do not have -DDEBUGGING,
Recompile perl with -DDEBUGGING to use -D switch (did you mean -d ?)

Related

Perl/Raku succinct webserver one-liner?

Are there any concise one-liners for quick serving of pages or directories if no index.html? Something like this:
python3 -m http.server
Couldn't find a Raku one-liner.
Compare Perl ones, taken from https://gist.github.com/willurd/5720255 and https://github.com/imgarylai/awesome-webservers :
plackup -MPlack::App::Directory -e 'Plack::App::Directory->new(root=>".");' -p 8000
perl -MHTTP::Server::Brick -e '$s=HTTP::Server::Brick->new(port=>8000); $s->mount("/"=>{path=>"."}); $s->start'
Install them prior to use (no additional installs with Python):
cpan Plack
cpan HTTP::Server::Brick
Plack pulls in a gajillion of dependencies so I didn't proceed with installation, and HTTP::Server::Brick doesn't install on my machine as its tests fail.
Both Perl and Raku are generally considered to be good in one-liners, and are meant to deliver DWIM:
"try to do the right thing, depending on the context",
"guess ... the result intended when bogus input was provided"
So I'd expect them - especially modern and rich Raku - to provide a webserver one-liner on par in simplicity with Python.
Or have I missed something?
If the feature lacks, is it planned?
If lacks and not-to-be-implemented, why?
I like http_this (https_this is also available).
There's an annoying shortcoming in that it doesn't currently support index.html - but I have a pull request pending to fix that.
On the other hand, these programs rely on Plack, so maybe you'd rather look elsewhere.
Raku Cro needs one line to install:
zef install --/test cro
And then one to setup and run:
cro stub http hello hello && cro run
From https://cro.services/docs/intro/getstarted
Let's say you want to serve all the files in a project subdirectory e.g. hello/httpd, then tweak the standard hello/lib/Routes.pm6 file to this:
1 use Cro::HTTP::Router;
2
3 sub routes() is export {
4 route {
5 get -> *#path {
6 static 'httpd', #path;
7 }
8 }
9 }
cro run looks for file changes and will auto restart the server
index.html works fine
I suggest a symbolic link ln -s if your dir is outside the project tree
Putting aside the webserver portion of your question, Python and Perl differ in their philosophies. Both of them are perfectly fine ways of doing things, and each appeals to a different sort of crowd.
Python is "batteries included", so it's a heavyweight distribution of many things in its standard library. There's more right out of the box, even if you never use most of it.
Perl tries to distribute just enough for you to install the modules that you decide that you need. That way, you can choose something that is fresher or newer than the thing that Perl chose to distribute.
Now, for the webserver, you may like Mojolicious. It's mostly self-contained (or relies on mostly core modules) so it's an easier install. The links you mentioned have Mojolicious::Lite examples.

Autoconf : How to get program output in a string and check if another string is present in that

I am developing a Qt application in Python. It uses a resource file, which needs to be compiled. I am using autotools to manage compilation and installation of my projects.
Now, in order for the resource file to be usable by the application, it needs to be compiled with a certain version of the compilation program (pyrcc). I can get the version by putting the output of pyrcc -version in a variable in configure.ac. But then, I don't know how to check whether the string pyrcc5 is present in the output. If it is not present, I want to tell the user that his PyRCC programm has the wrong version, and abort configure.
Additionally, I would like to avoid the need of an extra variable for the program output, but instead do it like this (Pseudo code):
if "pyrcc5" not in output of "pyrcc -version":
say "pyrcc has wrong version"
exit 1
How can I do this ?
When writing a configure.ac for Autoconf, always remember that you are basically writing a shell script. Autoconf provides a host of macros that afford you a lot of leverage, but you can usually at least get an idea about basic "How can I do X in Autoconf?" questions by asking instead "How would I do X in a portable shell script?"
In particular, for ...
I would like to avoid the need of an extra variable for the program
output, but instead do it like this (Pseudo code):
if "pyrcc5" not in output of "pyrcc -version":
say "pyrcc has wrong version"
exit 1
... the usual tool for a portable shell script to use for such a task is grep, and, happily, the easiest way to apply it to the task does not require an intermediate variable. For example, this implements exactly your pseudocode (without emitting any extraneous messaging to the console):
if ! pyrcc -version | grep pyrcc5 >/dev/null 2>/dev/null; then
echo "pyrcc has wrong version"
exit 1
fi
That pipes the output of pyrcc -version into grep, and relies on the fact that grep exits with a success status if and only if it finds any matches.
You could, in fact, put exactly that in your configure.ac, but it would be more idiomatic to
Use the usual Autoconf mechanisms to locate pyrcc and grep, and to use the versions discovered that way;
Use the Autoconf AS_IF macro to write the if construct, instead of writing it literally;
Use standard Autoconf mechanisms for emitting a "checking..." message and reporting on its result; and
Use the standard Autoconf mechanism for outputting a failure message and terminating.
Of course, all of that makes the above considerably more complex, but also more flexible and portable. It might look like this:
AC_ARG_VAR([PYRCC], [The name or full path of pyrcc. Version 5 is required.])
# ...
AC_PROG_GREP
AC_CHECK_PROGS([PYRCC], [pyrcc5 pyrcc], [])
AS_IF([test "x${PYRCC}" = x],
[AC_MSG_ERROR([Required program pyrcc was not found])])
# ...
AC_MSG_CHECKING([whether ${PYRCC} has an appropriate version])
AS_IF([! pyrcc -version | grep pyrcc5 >/dev/null 2>/dev/null], [
AC_MSG_RESULT([no])
AC_MSG_ERROR([pyrcc version 5 is required, but ${PYRCC} is a different version])
], [
AC_MSG_RESULT([yes])
])
In addition to portability and conventional Autoconf progress messaging, that also gets the builder a way to specify a particular pyrcc executable to configure (by setting variable PYRCC in its environment), documents that in configure's help text, and exports PYRCC as a make variable.
Oh, and I snuck in a check for pyrcc under the name pyrcc5, too, though I don't know whether that's useful in practice.
The final result no longer looks much like the shell script fragment I offered first, I grant. But again, the pure shell script fragment could be used as is, and also, the fully Autoconfiscated version is derived directly from the pure script.

Install Perl with TAINT as the default for an app's private Perl

I recently converted an application to use its own version of Perl using Perlbrew, rather than the system Perl, and I am never going back to using the system Perl again!
I'm about to start a clean slate application in which all of the scripts will run with TAINT turned on. Like my previous app, the libraries of the new app will refuse to run without TAINT turned on.
My question is, can I install or modify my own private Perl so that it always runs in TAINT mode by default?
EDIT: Sorry -- I should have also mentioned that I would like to use the #!/usr/bin/env perl shebang idiom in my scripts, so defining a shell alias would not be a solution.
While it looks reasonably straightforward to modify perl to always run with tainting turned on (untested: add TAINTING_set(TRUE); just after the command-line-switch-handling for/case in perl.c), there is no supported way to do it. Setting the PERL5OPT environment variable is as close as its gets. Note that "-T" must come first in the variable's value, and any other switches you try to set there will be ignored.
All this seems overly paranoid, though. Is it not enough to put "-T" on the #!-line for the scripts that may get outside input?

Can I setuid a perl script?

I made a perl script to change owner of a file owned by some other user. Script is complete. My administrator save that in /sbin directory and set uid for it using chmod u+s name_of_script. But when I run this script it gives me error that chown operation is not permitted. I made a C program and it works by following same steps. So my question is if setuid is working for perl then I should not get that error because C code did not give me any error. So can i setuid for perl script or I should go with c code.
Don't tell me to ask administrator to change owner each time. Actually in server I have user name staging and I am hosting a joomla site in it. Now when I install some plugin then files related to that plugin are owned by www-data. So that's why I do not want to go to admin each time. Or you can give me some other solution also regarding my problem.
Many unix systems (probably most modern ones) ignore the suid bit on interpreter scripts, as it opens up too many security holes.
However, if you are using perl < 5.12.0, you can run perl scripts with setuid set, and they will run as root. How it works is that when the normal perl interpreter runs, and detects that the file you are trying to execute has the setuid bit set, and it then executes a program called suidperl. Suidperl takes care of elevating the user's privileges, and starting up the perl interpreter in a super-secure mode. suidperl is itself running with setuid root.
One of the consequences of this is that taint mode is turned on automatically. Other additional checks are also performed. You will probably see messages like:
Insecure $ENV{PATH} while running setuid at ./foobar.pl line 3.
perlsec provides some good information about securing such scripts.
suidperl is often not installed by default. You may have to install it via a separate package. If it is not installed then you get this message:
Can't do setuid (cannot exec sperl)
Having said all of that - you would be much better off using sudo to execute actions with elevated privileges. It is much more secure as you can specify exactly what is allowed to be executed via the sudoers file.
As of perl 5.12.0, suidperl was dropped. As a result, if you want to run a perl script on perl >= 5.12.0 with setuid set, you would have to write your own C wrapper. Again I recommend sudo as a better alternative.
No, you cannot use setuid aka chmod +s on scripts. The script's interpreter would be the thing that would actually need to be setuid, but doing that is a really bad idea. REALLY bad.
If you absolutely must have something written in Perl as setuid, the typical thing to do would be to make a small C wrapper that is setuid and executes the Perl script after starting. This gives you the best of both worlds in having a small and limited setuid script but still have a scripting language available to do the work.
If you have a sudo configuration that allows it (as most desktop linux distributions do for normal users), you can start your perl script with this line:
#!/usr/bin/env -S -i MYVAR=foo sudo --preserve-env perl -w -T
Then in your script before you use system() or backticks explicitly set your $ENV{PATH} (to de-taint it):
$ENV{PATH} = '/usr/bin';
Other environment variable that your script explicitly mentions or that get implicitly used by perl itself will have to be similarly de-tainted (see man perlsec).
This will probably (again depending on your exact sudo configuration) get you to the point where you only have to type in your root password once (per terminal) to run the script.
To avoid having to type your password at all you can add a line like this to the bottom of /etc/sudoers:
myusername ALL=(ALL) NOPASSWD:ALL
Of course you'd want to be careful with this on a multi-user system.
The -S options to env splits the string into separate arguments (making it possible to use options and combinations of programs like sudo/perl with the shebang mechanism). You can use -vS instead to see what it's doing.
The -i option to env clears the environment entirely.
MYVAR=foo introduces an environment variable definition.
The --preserve-env option to sudo will preserve MYVAR and others.
sudo sets up a minimal environment for you when it finds e.g. PATH to be missing.
The -i option to env and --preserve-env option to sudo may both be omitted and you'll probably end up with a slightly more extensive list of variables from your original environment including some X-related ones (presumably the ones the sudo configuration considers safe). --preserve-env without -i will end up passing along your entire unsanitized environment.
The -w and -T options to perl are generally advisable for scripts running as root.

Using Perl modules vs. using system() calls

Quite recently, I wrote a few scripts in Perl for a cPanel plugin in which, though most of the code was in Perl, there was quite a lot of system() commands as well which I used to execute shell commands directly.
I am pretty sure that there are Perl modules that I could have used instead. Keeping in mind the time crunch, I thought using the system command was easier (to complete the project in time). In retrospective, I think that was a bad programming practice.
My question is, is there any tradeoff, memory-wise or otherwise when using Perl's modules and using system() commands. For example, what would be the difference in using:
my $directory = "temp";
mkdir $directory;
and
system ("mkdir temp");
Also, if I am to use Perl modules, wouldn't that involve installing a whole lot of modules in the beginning?
The most obvious economy is that, in the first case, your Perl process is creating the directory, while in the second, Perl is starting a new process that runs a command shell which parses the command line and runs the shell mkdir command to create the directory, and then the child process is deleted. You would be creating and deleting a process and running the shell for every call to system: there is no caching of processes or similar economy.
The second thing that comes to mind is that, if your original mkdir fails, it is simple to handle the error in Perl, whereas shelling out to run a mkdir command puts your program at a distance from the error, and it is far more awkward to handle the many different problems that may arise.
There is also the question of maintainability and portability, which will affect you even if you aren't expecting to run your program on more than one machine. Once you abandon control to a system command you have no control over what happens. I could have written a mkdir that will delete your home directory or, less disastrously, your program may find itself on a system where mkdir doesn't exist, or does something slightly different.
In the particular case of mkdir, this is a built-in Perl operator and is part of every Perl installation. There are also many core libraries that require you to put use Module in your program, but are already installed and need no further action.
I am sure others will come up with more reasons to prefer a Perl operator or module over a shell command. In general you should prefer to keep everything you can within the language. There are only a few cases where you have to run a third-party program, and they usually involve custom software that allows you act on proprietary data formats.