Need some help with this...

I am trying to implement some kind of a which program. I could get the PATH environment variable and was able to tokenize it. I have a list of paths in tokens[]. Now, I have the name of the shell command. How would I search the tokens[] and display where the command was found?

try access(X_OK)

Thank You. One problem I'm facing is that it is giving me a segmentation fault.

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

char* program_name;

int allpaths;			/* -a */
int readalias;			/* -r */
const char *name = "PATH";
char *value;
int result;
char *filename;
char *pathsep = "/";
int i;

/*PASTED ONLY THE REQUIRED PART*/
int processIt(const char* command,  char* paths[])
{
  /* check your arguments! */
  /* At this point, the command line options have been taken care of assuming that only one option was there.
  Now, we need to take this "command" that was sent to us from the main function and then search for this command in the paths.*/
  
  /*paths contains the current path to be searched*/
  for(i=0;i<MAX_PATHS;i++) {
  strcat(paths,pathsep);
  strcat(paths,command);
  printf("%s",paths);
  /*result = access(paths, F_OK);*/
  printf("%d",result); }
  return 0;
} /* processIt! */

processIt is the function I'm using to find the file. Any advice please?

for (i=0;i<number_of_paths;i++) 
{
  char tmp[1024];
  strcpy(tmp,paths);
  strcat(tmp,pathsep);
  strcat(tmp,command);
  printf("%s",tmp);
  result = access(tmp, X_OK);
  printf("%d",result); 
}
  1. you need a better way to indicate the valid number of paths in the paths[] variable.

  2. you need to use a temporary string to build the complete path for access().

Thank You. I did as you instructed but I keep getting this Segmentation Fault:

  int processIt(const char* command,  char* paths[])
  {
           
        /*paths contains the current path to be searched*/
        for(i=0;i<MAX_PATHS;i++) {
            strcat(temp,paths);  
            strcat(temp,pathsep);
            strcat(temp,command);
            result = access(temp, F_OK);
            if(result == 0)
            {
              printf("%s\t",temp);
              printf("%d\n",result);
            }
            for(j=0;j<MAX_PATHS;j++)
              temp[j] = '\0';
        }
        return 0;
  } /* processIt! */

Any advice please?

Here's the output if that would help:

gma@server1 [~/public_html/os/skeleton]# ./uwhich -a curl

i is 0
        Errno: 2        /usr/local/jdk/bin/curl
i is 1
        Errno: 2        /usr/kerberos/bin/curl
i is 2
        Errno: 2        /usr/lib/courier-imap/bin/curl
i is 3
        Errno: 2        /usr/local/bin/curl
i is 4
        Errno: 2        /bin/curl
i is 5
/usr/bin/curl   0
/usr/bin/curl
i is 6
        Errno: 2        /usr/X11R6/bin/curl
i is 7
        Errno: 2        /usr/local/bin/curl
i is 8
        Errno: 2        /usr/X11R6/bin/curl
i is 9
Segmentation fault (core dumped)
gma@server1 [~/public_html/os/skeleton]# echo $PATH
/usr/local/jdk/bin:/usr/kerberos/bin:/usr/lib/courier-imap/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/usr/X11R6/bin:/home/enigma/bin
gma@server1 [~/public_html/os/skeleton]#

The program is working fine till the last directory and after that its giving a Segmentation Fault... I don't know why that is happening...

One weird thing is that when I try to print out the elements in the paths array, it says there are atleast 9 but when I use sizeof(paths) I get 4... What could be the reason for this?

You are getting the size of the pointer, not the number of elements in the array.

int processIt(const char* command,  char* paths[], int numberOfPaths)
{
        /*paths contains the current path to be searched*/
        for(i=0; i<numberOfPaths; i++) {
            char temp[1024];  
            strcpy(temp,paths);  
            strcat(temp,pathsep);
            strcat(temp,command);
            result = access(temp, X_OK);
            if(result != -1)
            {
              printf("%s\t",temp);
              printf("%d\n",result);
            }
        }
        return 0;
  } /* processIt! */

The function has no idea of the number of valid elements in the paths array.
Use strcpy for the first, then strcat to append.
access returns -1 for error, non -1 for success.
X_OK as you want to know the file is executable.

Thank you so much... I followed your advice... And if I want to implement alias support for my command... do I have to add some extra lines to the code or do I just have to utilise the alias command?

Seeing as my manpage for alias does not say where the alias mappings are stored, I think that using popen("alias","r") is your best bet.

Well I don't quite get the sentence itself... What does it mean to implement alias support for my command?

Hm, sounds like the teacher wants you to ......

http://www.unix.com/unix-for-dummies-questions-and-answers/2971-simple-rules-of-the-unix-com-forums.html rule (6)

Not exactly... But my book wants me and its not homework... :stuck_out_tongue: And yeah, don't tell me the solution or anything. I want to implement it myself... I just want to know the meaning of that... thats it..

Basically you would be converting the following into C.

#!/bin/sh

first()
{
        echo $1
}

for n in $@
do
        /usr/bin/alias | while read STR
        do
                NAME=`echo $STR | sed y/=/\ /`
                FIRST=`first $NAME`
                if test "$FIRST" = "$n"
                then
                        echo $STR | sed s/$n=//
                fi
        done

        if test -f $n
        then
                echo $n
        fi

        for d in `echo $PATH | sed y/:/\ /`
        do
                if test -f $d/$n
                then
                        echo $d/$n
                fi
        done
done

I'm not sure if I still know what I need to do.. I'll just go through that code for now...

which is supposed to tell you what actual command will be executed if you type it in.

So if the name is listed by alias then there is an alias mapping which is run instead of looking for the command in the $PATH. Presumeably you are supposed to print out that mapping?

:slight_smile: I think I got you now... I'll try writing for that... Thank You... Will get back when I'm done with it...

I tried out a short example:

 fp = popen("alias","r");
            if(fp == NULL)
            {
                  printf("Handle Error");
            }
            printf("You asked for an alias");
            while(fgets(alia,20,fp) != NULL)
            printf("%s",alia);
            pclose(fp);

It goes upto "You asked for an alias" and quits... alia is a "char alia[1024];" definition and fp is a file pointer... Am I doing something wrong?

Edit: It outputs the data if I use something else other than alias. For example, something like netstat. I'm getting some error when I try to directly put something like alias ls. It says:

sh: line 1: alias: ls: not found

Chicken and egg.

Perhaps your system does not support alias...?

try

which alias

similarly

bash -c alias
ksh -c alias
zsh -c alias
sh -c alias
csh -c alias