tneduts
tneduts

Reputation: 115

C - finding full path of command

I am trying to find the full path of a command someone would type in the terminal or console window. I am trying to use

 getenv(PATH) 

to get the ':' delimited strings of different paths the command may live in, and then use

stat() 

to see if it exists in each one.

I am having trouble parsing through the returns of getenv() since I cannot use the string library.

getenv(path) returns: 
PATH = /Library/Frameworks/Python.framework/Versions/3.2/bin:/Library/Frameworks/Python.framework/Versions/3.2/bin:/Library/Frameworks/Python.framework/Versions/2.7/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

I am trying:

char* fullPath = getenv( "PATH" );
struct stat buffer;
int exists; 
char* fileOrDirectory = usersCommand    
exists = stat( file_or_dir, &buffer );  
if ( exists == 0 && ( S_IFDIR & buffer.st_mode ) ) {
    //dir exists
} else if ( exists == 0 && ( S_IFREG & buffer.st_mode ) ) {
    //file exists
} else {
    //neither exists
}

As of now I am not using my fullPath variable. As it is now is it just searching my local directory for the command?

An example command would be 'cd', or 'ls' , etc.

How can I parse through the ':' delimited string and then call stat on each one? I don't exactly understand the purpose of buffer besides having some info on the file or directory status but I feel like it should be taking another parameter so I can input what I am searching for as well as the fullPath.

Thanks

Upvotes: 1

Views: 1850

Answers (3)

cmidi
cmidi

Reputation: 2010

Because string standard library functions are not allowed you need to write a string tokenizer yourself you can do something on the lines of the following code below, You might would have to refine it a little more.

Basically what we are doing here

Get the PATH

find token ':'

memcpy substring upto token -1

update the PATH

repeat until '\0'.

#define MAX_DIR_PATH_SIZE 500
char *get_directory(char **u_path, int *done)
{
    int i;
    char *temp  = malloc(MAX_DIR_PATH_SIZE);
    //handle error here                                                                                                                                                                                                                           
    memset(temp,0,MAX_DIR_PATH_SIZE);
    if(!u_path || !(*u_path))
        return NULL;
    int index =0 ;

    for(i = 0;i <= MAX_DIR_PATH_SIZE ; i++)
    {
         if(index)
            break;
         switch((*u_path)[i]) // proximity of the brackets and * is important                                                                                                                                                                   
         {
            case '\0':
              *done  = 1;
              index = 1;
              memcpy(temp,*u_path,i+1);
              printf("Last substring %s\n",temp);
            break;
            //Search for token ': ascii = 58'                                                                                                                                                                                                  
            case 0x3A:
              index = 1;
              memcpy(temp,*u_path,i);
              *u_path = *u_path+i+1;
              printf("token found : %s\n",temp);
              break;
           default:
             break;
        }

    }
    //handle error for maximum size overlimit
    return temp;
 }


int main(int argc, char **argv)
{
    char *fullPath = getenv( "PATH" );
    char *u_path = fullPath;
    struct stat buffer;
    int exists;
    int done = 0;
    char* fileOrDirectory = NULL;
    while(!done)
    {
        fileOrDirectory = get_directory(&u_path,&done);
        printf("new path is : %s\n",u_path);
        if(fileOrDirectory)
        {
            exists = stat( fileOrDirectory, &buffer );
            if ( exists == 0 && ( S_IFDIR & buffer.st_mode ) ) {
                printf("directory size %lu\n",buffer.st_size);
            }
            else {
               //do something else                                                                                                                                                                                                                
            }
            free(fileOrDirectory);
        }
    }
    return 0;
}

Upvotes: 1

rghome
rghome

Reputation: 8819

The function strtok is the standard method of tokenizing a string. With that you can build the full path-name of the file.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>

main(int argc, char **argv)
{

    char* fullPath = getenv( "PATH" );
    struct stat buffer;
    int exists;
    char* fileOrDirectory = argv[0];
    char fullfilename[1024];

    char *token = strtok(fullPath, ":");

    /* walk through other tokens */
    while( token != NULL )
    {
        sprintf(fullfilename, "%s/%s", token, fileOrDirectory);
        exists = stat( fullfilename, &buffer );
        if ( exists == 0 && ( S_IFREG & buffer.st_mode ) ) {
            printf("found file %s\n", fullfilename);
        }

        token = strtok(NULL, ":"); /* next token */
    }
    exit(0);
}

Upvotes: 1

R Sahu
R Sahu

Reputation: 206577

Here's something to try:

// Variables needed during iteration.
char* start = fullPath;
char sep = ':';
char* iter;
char trialPath[BUFSIZ];

// Get the path
char* originalPath = getenv( "PATH" );

// Make a copy of the path since we are going to modify it
// while we are iterating on it.
char* fullPath = malloc(strlen(originalPath) + 1);
strcpy(fullPath, originalPath);

start = fullPath;

// Iterate over the path.
for ( char* iter = start; *iter != '\0'; ++iter )
{
   if ( *iter == sep )
   {
      *iter = '\0';
      // Now, start is a directory.
      // Check whether the user command is at this location.
      strcpy(trialPath, start);
      strcat(trialPath, "/");
      strcat(trialPath, usersCommand);

      // Now use stat to check whether the file exists and
      // it is an executable.
      // ....


      // If not, reset where start points to.
      start = iter + 1;
   }
}

// Deallocate memory allocated earliner.
free(fullPath);

Upvotes: 0

Related Questions