Thursday, July 28, 2011

Validate program installation with C++ and system()

Currently I am writing an analysis script. This script outputs a graph generated by a third party program called gnuplot. In order to make the script more robust, I wanted to be able to abort at startup if gnuplot had not been installed. Hence, the post.

Requirements:
I need something that will quitely find out if the command exists and then kill the script.

Discussion:
I've been doing a lot of 'man 3' reading and scouring around the web looking for a quick and easy way to check if a program is installed. I tried to stay away from system() as other sources deemed it very dangerous and even *EVIL*. Thus, I thought I had to absolutely stay away from using system().

I tried using many of the std C exec* functions after calling a fork and writing my own function that buffered popen results. However, this seemed like too much code and must have been redundant to existing libraries. I hesitated using popen(), as it is basically system(), only buffered (both system and popen just fork and call a process with the shell). This lead me to hesitate the security of popen() as well. Turns out it, it didn't really matter.

Finally an answer:
The issue with system() is that it *can* be very dangerous. In system() the child process runs with the same user privileges as the parent. Thus, with admin rights, one can accidentally run system("rm -rf /"). Hence, problems occur when the programmer is imprudent with the system() argument. Under computer security pragma, this means system should never be used, as it could mess up. However, I finally concluded with my software developer sense that system() really is fine, especially with a static string as an argument. That being said, here are the lines:

if (256 == system("hash gnuplot 2>&-")) {
  cout << "Gnuplot must be installed to run script. Aborting.\n";
  exit(EXIT_SUCCESS);
}

Enjoy!

2 comments:

  1. System call with a static string in your situation is considered safe imo.

    ReplyDelete
  2. I've since found that (-X $filename) serves the same purpose in perl.

    ReplyDelete