ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
I'm trying to write a very simple shell in C that
Prompts the user for a command,
Parses the command line,
Execute the command while passing to it the arguments passed on the command
line.
say the desired command is in variable cmd
how can i get the full path of this specific cmd?
anything like path = getenv("PATH"); ??
If you need a program to find the full path to itself, here's an example.
(If the program is executed through a symbolic link, it will print the full path to the actual file, not the link.)
Code:
/* getexepath2.c */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#define MAXPATHLEN 200 /* make this larger if you need to. */
int main ()
{
int length;
char fullpath[MAXPATHLEN];
/* /proc/self is a symbolic link to the process-ID subdir
* of /proc, e.g. /proc/4323 when the pid of the process
* of this program is 4323.
*
* Inside /proc/<pid> there is a symbolic link to the
* executable that is running as this <pid>. This symbolic
* link is called "exe".
*
* So if we read the path where the symlink /proc/self/exe
* points to we have the full path of the executable.
*/
length = readlink("/proc/self/exe", fullpath, sizeof(fullpath));
/* Catch some errors: */
if (length < 0) {
fprintf(stderr, "Error resolving symlink /proc/self/exe.\n");
exit(EXIT_FAILURE);
}
if (length >= MAXPATHLEN) {
fprintf(stderr, "Path too long. Truncated.\n");
exit(EXIT_FAILURE);
}
/* I don't know why, but the string this readlink() function
* returns is appended with a '@'.
*/
fullpath[length] = '\0'; /* Strip '@' off the end. */
printf("Full path is: %s\n", fullpath);
return 0;
}
Originally posted by Hady but I need something that returns the path not of itself,
but of any command that the user types,
for example, if the user of the program types ls,
it returns (/usr/bin) [supposing ls is in that directory]
I have looked for it in the man an info pages, but there seems not to be a standard library call for this. This amazes really. There will be a day, when I will need it as well, so I made one. Hope this helps you out.
Code:
/* searchpath.c
*
* Find named executable in the PATH environment variabele.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <libgen.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
/* int checkifexecutable(const char *filename)
*
* Return non-zero if the name is an executable file, and
* zero if it is not executable, or if it does not exist.
*/
int checkifexecutable(const char *filename)
{
int result;
struct stat statinfo;
result = stat(filename, &statinfo);
if (result < 0) return 0;
if (!S_ISREG(statinfo.st_mode)) return 0;
if (statinfo.st_uid == geteuid()) return statinfo.st_mode & S_IXUSR;
if (statinfo.st_gid == getegid()) return statinfo.st_mode & S_IXGRP;
return statinfo.st_mode & S_IXOTH;
}
/* int findpathof(char *pth, const char *exe)
*
* Find executable by searching the PATH environment variable.
*
* const char *exe - executable name to search for.
* char *pth - the path found is stored here, space
* needs to be available.
*
* If a path is found, returns non-zero, and the path is stored
* in pth. If exe is not found returns 0, with pth undefined.
*/
int findpathof(char *pth, const char *exe)
{
char *searchpath;
char *beg, *end;
int stop, found;
int len;
if (strchr(exe, '/') != NULL) {
if (realpath(exe, pth) == NULL) return 0;
return checkifexecutable(pth);
}
searchpath = getenv("PATH");
if (searchpath == NULL) return 0;
if (strlen(searchpath) <= 0) return 0;
beg = searchpath;
stop = 0; found = 0;
do {
end = strchr(beg, ':');
if (end == NULL) {
stop = 1;
strncpy(pth, beg, PATH_MAX);
len = strlen(pth);
} else {
strncpy(pth, beg, end - beg);
pth[end - beg] = '\0';
len = end - beg;
}
if (pth[len - 1] != '/') strncat(pth, "/", 1);
strncat(pth, exe, PATH_MAX - len);
found = checkifexecutable(pth);
if (!stop) beg = end + 1;
} while (!stop && !found);
return found;
}
int main(int argc, char **argv)
{
char path[PATH_MAX+1];
char *progpath = strdup(argv[0]);
char *prog = basename(progpath);
char *exe;
if (argc != 2) {
fprintf(stderr, "Usage: %s <executable file>\n", prog);
return 1;
}
exe = argv[1];
if (!findpathof(path, exe)) {
fprintf(stderr, "No executable \"%s\" found\n", exe);
return 1;
}
puts(path);
free(progpath);
return 0;
}
If you need only the directory, not the file (or symbolic link) itself, you can use dirname() (see "man 3 dirname") to strip it of.
On my system (Debian testing) "/usr/bin/gcc" is a symbolic link to /usr/bin/gcc-3.3.
When I try my program:
Code:
bash$ searchpath gcc
/usr/bin/gcc
# which is correct, though it is a symbolic link actually.
# But when I do the following, the $PATH is not used, and then
# the symbolic link gets resolved by the realpath() function:
bash$ searchpath /usr/bin/gcc
/usr/bin/gcc-3.3
So two different answers for the same thing, though both correct, it's not consistent.
More or less a "cosmetic" bug.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.