2

What is the most efficient method for running programs from the /usr/bin directory in a C program? I am tasking with getting user input, and if the user input matches up with a program in bin, running the respective program.

I had the idea of throwing the names of all the bin's programs in a text file, and using a loop to iterate through each word in the file while comparing the word to the input. However, I figured that might be reinventing the wheel a bit. Are there any streamlined ways to do this?

Z4-tier
  • 7,287
  • 3
  • 26
  • 42
  • 2
    The simplest technique is simply to create the full path from what the user enters and try running it. – Jonathan Leffler May 05 '19 at 05:02
  • You can add a few logical checks to ensure the name your user enters actually exists before attempting to run it. Look at [man 3 system](http://man7.org/linux/man-pages/man3/system.3.html) and the [man 3 exec family](http://man7.org/linux/man-pages/man3/exec.3.html) – David C. Rankin May 05 '19 at 05:07
  • Possible duplicate of [Please explain the exec() function and its family](https://stackoverflow.com/q/4204915/608639), [What is the difference between the functions of the exec family of system calls like exec and execve?](https://stackoverflow.com/q/20823371/608639), [How to use exec() family to implement the shell commands cp and rm?](https://stackoverflow.com/q/17866495/608639), etc. – jww May 05 '19 at 05:17

2 Answers2

3

The "classical" way of invoking a program from an existing process on any of the UNIX-like OS'es is to use one of the exec() functions. When you read about exec() most tutorials will start by explaining another function: fork(). These functions are very commonly used together, but don't get too caught up on that, because they are both useful in their own right.

To answer your question, a fairly efficient way of doing what you're after:

  1. Take the user generated input from whatever your source happens to be
  2. (Optionally, call fork())
  3. Call the execvp() function
  4. What you do here will depend on whether you called fork() in step (2), and what you intend to do (if anything) after performing the task you described.

execvp() will do the legwork for you, by automatically searching on your environment PATH for a filename matching the first argument. If the current environment does not have a PATH set, it will default to /bin:/usr/bin. Since the only way that a call to exec() can yield a return value is when that call failed, you might want to check the value of errno as part of step (4). In the event that the user input didn't match any executable in the environment PATH, errno will be set to ENOENT. Exactly how you do this and what additional steps might be worth taking will depend on whether or not you forked, along with any additional requirements for your program.

Z4-tier
  • 7,287
  • 3
  • 26
  • 42
  • Excellent, thanks a bunch for this info! I was already toying with `exec` related functions, but I didn't know that it automatically searches on my PATH. – poppinMartinellis May 05 '19 at 22:42
-1

I would suggest looking if the name you get from the user matches a file in the /usr/bin directory and if it does use the system function to run this program.

https://linux.die.net/man/3/system

#include <stdlib.h>
int system(const char *command);

i.e

FILE *file;
if (file = fopen(userinput, "r")){
    fclose(file);
    system(userinput);
}
mstruebing
  • 1,674
  • 1
  • 16
  • 29