[EMAIL PROTECTED] wrote: >>>I, being too lazy to look up a perl function, would use >> >>hostname command in >> >>>backticks like so: >>> >>>$HostID = `hostname`; >>> >> >>Right which is why the above is "too lazy". Anyone reading this please >>don't settle for the above, it is error prone, insecure, and >>insufficient. There is no error checking, there at least needs to be a >>full path, and it is potentially slower. > > > After the initial shock of having 1 simple assignment statement ripped to > shreds, I thought about it for a minute and it downed on me that I'm not > buying into your accusations. I would like you to please explain them. If > these are indeed realistic problems then everyone should know why. And > please don't use examples like, "it is insecure because someone could swap > out the hostname binary with something potentially damaging" because that > would require root access and for that matter a bang statement to the perl > binary would suffer from the same security flaws. >
Very well..... 1. Insecure: when using a shell command from a script you are at the mercy of the environment of the invoking user. If you do not have complete control of the environment you are at risk. This was the oldest trick in the book when I was in college, create a script called 'su', place it in a 'bin' directory in your user account, place '~/bin' at the front of the PATH environment variable. Then go to the sysadmins and say you had screwed up your account in some manner that would require them to become root. So logged in under your user they ran 'su' which was naturally setup to emulate the look of the real 'su' command. After about 10 seconds you now have root's password. Of course most people aren't this susceptible anymore, and most are using 'sudo' which has protections in place, but the point remains. Unless you use a full path to a script you have no idea of what malicious intent has been placed in the path to cause you problems. And even if you do use a full path there is nothing to say that the command you are calling hasn't been replaced. Not to mention any code receiving input from an external source should have taint checking on. (Despite your claim to the contrary this is still a real enough threat.) 2. Error Prone: your command is insufficent because you do not check whether or not the command was even runnable. Backticks provides a return result in $? that will tell you whether or not you were able to fork, and whether or not the command existed, you had the proper permissions, etc. Without checking all of this each time you call out to a system command you are not providing sufficient error checking. On top of that you were not checking the exit value of the command so you don't know if it ran successfully or not, you only know whether you got any output. You don't know if it dumped core, or what signal caused it to stop in the case that it failed. You also didn't include the STDERR capturing idiom in the command so you don't know if there was error output or warnings generated. 3. Portability: the command issued may have different switches, may not exist, or may be for a completely different purpose depending on what platform you are running. 'hostname' is actually the perfect example, because to my knowledge it doesn't even exist on Windows systems. Many commands have very different settings and interfaces across the many unix systems, and depending on the available /bin/sh (assuming it is the default system shell, which isn't necessarily true either) there may be different quoting patterns needed, or the shell may not support long option processing. Granted a lot of code is intended to run on a single platform, but unless that was specifically provided in the spec by the poster you don't know, so can't assume. Some systems may not even provide a proper fork clone, more on that below. 4. Speed/Forking: because backticks causes a fork, you are using system resources in a way you wouldn't necessarily need to if you were able to use a built-in function. When Perl forks, it forks an exact copy of the running process and then transitions to the new command (at least on *nix systems) which may cause use of memory resources, file descriptors (which include open sockets to databases or possible remote locations), and other system level attributes that you wouldn't otherwise need. And the memory footprint of the running process includes all loaded modules so could be quite large. When running a forked system command, the perl interpreter has to fork, then exec the shell, the shell then has to parse the command line (which unless you have seen the parsing map you wouldn't believe how long this takes), then it has to fork and exec again into the running process, that process may then have to do its own option parsing, etc. which all could have been avoided by using the internal method. So it is almost always slower to call a system command when an internal method is available. Finally each call to system/backticks is independent, meaning that depending on the command being run and the optimizations of the alternatives there is no potential to use caching, session management, etc. to improve efficiency. Although system/backticks are written correctly in Perl 5, if you are using your own fork/exec model and don't include sufficient 'wait' code then your system may also become swamped by zombies, eventually causing a locked system, assuming you don't hit the memory limit first. I leave it to you whether I have backed up my position, but shelling out should *always* be an absolute last resort, which at times does happen, but when it does it should be executed with care and diligence. And if a module exists that can provide an alternative it should definitely be used, if for no other reason than maybe it will have to shell out too, but in that case the module author has more likely thought of the above things and done his best to avoid the issue. Sys::Hostname is the perfect example, it will eventually shell out too if all the preferred methods fail, but it does the proper amount of error checking, taint checking, etc. Check out the source if you want to see what I mean by sufficient handling. http://search.cpan.org/src/NWCLARK/perl-5.8.7/ext/Sys/Hostname/Hostname.pm And those are just my reasons, the gurus may have more/better ones... > >>>Not sure if that will catch a newline character so I would >> >>also follow it >> >>>with this: >>> >>>$HostID =~ s/\n//; >> >>Right, in which case we can at least suggest 'chomp', > > > Matter of preference really. I like using regex. > Well again if your preference is error proneness and slower by all means, I can't prevent you from doing it. But you haven't considered what the new line character may be for the given system, whether or not the given shell/program provides one. And firing up the regex engine will always be slower than using a simple chomp, especially since you are making the assumption that there is only one new line (fairly safe granted with 'hostname') and haven't even provided the courtesy of anchoring it to the end of the string to at least get that efficiency improvement. It is still just sloppiness, and beginners don't need to be picking up bad habits. http://danconia.org [snip] -- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>
