Thread: How can I print a linked list that contains the path directory (environment variable)

  1. #1
    Registered User
    Join Date
    Dec 2021
    Posts
    5

    Unhappy How can I print a linked list that contains the path directory (environment variable)

    I have been trying to print the linked list the program below creates, to see how the path information is actually organized inside of it, having no success in the process.

    Code:
    [COLOR=var(--highlight-keyword)]#[/COLOR][COLOR=var(--highlight-keyword)]define[/COLOR][COLOR=var(--highlight-keyword)] TRUE 1[/COLOR]
    [COLOR=var(--highlight-keyword)]#[COLOR=var(--highlight-keyword)]define[/COLOR] FALSE 0[/COLOR]
    
    [COLOR=var(--highlight-keyword)]extern[/COLOR] [COLOR=var(--highlight-namespace)]char[/COLOR] **environ;
     
    [COLOR=var(--highlight-comment)]/*
     * struct Node - singly linked list
     * @str: string - (malloc'ed string)
     * @next: points to the next node
     * Description: singly linked list node structure
     */[/COLOR]
    [COLOR=var(--highlight-keyword)]typedef[/COLOR] [COLOR=var(--highlight-keyword)]struct[/COLOR] [COLOR=var(--highlight-literal)]Node[/COLOR]
    {
     [COLOR=var(--highlight-namespace)]char[/COLOR] *str;
     [COLOR=var(--highlight-keyword)]struct[/COLOR] [COLOR=var(--highlight-literal)]Node[/COLOR] *[COLOR=var(--highlight-literal)]next[/COLOR];
    }
    
     [COLOR=var(--highlight-comment)]/**
     * _getenv - searches for the environment string
     * pointed to by name 
     * @name:  This is the C string containing the name
     * of the requested variable
     * Return: the associated value to the string.
     */[/COLOR]
    [COLOR=var(--highlight-namespace)]char[/COLOR] *_getenv([COLOR=var(--highlight-keyword)]const[/COLOR] [COLOR=var(--highlight-namespace)]char[/COLOR] *name)
    {
        [COLOR=var(--highlight-namespace)]int[/COLOR] i, j; [COLOR=var(--highlight-comment)]/* Counters */[/COLOR]
        [COLOR=var(--highlight-namespace)]int[/COLOR] status; [COLOR=var(--highlight-comment)]/* boolean variable */[/COLOR]
    
    
        [COLOR=var(--highlight-keyword)]for[/COLOR] (i = [COLOR=var(--highlight-namespace)]0[/COLOR]; environ[i] != [COLOR=var(--highlight-literal)]NULL[/COLOR]; i++) [COLOR=var(--highlight-comment)]/* loop over the array of pointers to strings called "environment" until it finds a string value called NULL (the last one) */[/COLOR]
        {
            status = [COLOR=var(--highlight-namespace)]1[/COLOR]; [COLOR=var(--highlight-comment)]/* initialize the status variable as TRUE (1) */[/COLOR]
            [COLOR=var(--highlight-keyword)]for[/COLOR] (j = [COLOR=var(--highlight-namespace)]0[/COLOR]; environ[i][j] != [COLOR=var(--highlight-variable)]'='[/COLOR]; j++)  [COLOR=var(--highlight-comment)]/* loop over the the current string value until the symbol '=' is found */[/COLOR]
            {
                [COLOR=var(--highlight-keyword)]if[/COLOR] (name[j] != environ[i][j]) [COLOR=var(--highlight-comment)]/* Check if each byte of the current string value is exactly the same as name */[/COLOR]
                {
                    status = [COLOR=var(--highlight-namespace)]0[/COLOR]; [COLOR=var(--highlight-comment)]/* if they are not, we notify (set the status variable as FALSE (0)) and break */[/COLOR]
                    [COLOR=var(--highlight-keyword)]break[/COLOR];
                }
            }
    
            [COLOR=var(--highlight-keyword)]if[/COLOR] (status) [COLOR=var(--highlight-comment)]/* IF and ONLY IF we have found that each byte of the current string value is exactly the same as name  */[/COLOR]
            {
                [COLOR=var(--highlight-keyword)]return[/COLOR] (&environ[i][j + [COLOR=var(--highlight-namespace)]1[/COLOR]]); [COLOR=var(--highlight-comment)]/* return the address of the current string value excluding the "=" sign */[/COLOR]
            }
        }
        [COLOR=var(--highlight-keyword)]return[/COLOR] ([COLOR=var(--highlight-literal)]NULL[/COLOR]); [COLOR=var(--highlight-comment)]/* This function returns NULL if the environment variable requested does not exist */[/COLOR]
    }              [COLOR=var(--highlight-comment)]/* if the previous return was successfully executed, this return is not executed */[/COLOR]
    
    [COLOR=var(--highlight-comment)]/**
     * _getpathdir - creates a linked list for
     * any environment string
     * @path: the selected environment string
     * @pathCopy: a duplicate of @path
     * Return: a linked list of @path
     */[/COLOR]
    Node *_getpathdir([COLOR=var(--highlight-namespace)]char[/COLOR] *path, [COLOR=var(--highlight-namespace)]char[/COLOR] **pathCopy)
    {
        [COLOR=var(--highlight-namespace)]char[/COLOR] *token = [COLOR=var(--highlight-literal)]NULL[/COLOR];
        Node *head;
        Node *pathNode;
    
    
        [COLOR=var(--highlight-keyword)]if[/COLOR] (path == [COLOR=var(--highlight-literal)]NULL[/COLOR]) [COLOR=var(--highlight-comment)]/* If path passed is NULL, return NULL */[/COLOR]
            [COLOR=var(--highlight-keyword)]return[/COLOR] ([COLOR=var(--highlight-literal)]NULL[/COLOR]);
    
        *pathCopy = strdup(path); [COLOR=var(--highlight-comment)]/* Make a duplicate of path parameter */[/COLOR]
    
        head = [COLOR=var(--highlight-literal)]NULL[/COLOR]; [COLOR=var(--highlight-comment)]/* Initialize the very first token of the linked list to NULL */[/COLOR]
        pathNode = [COLOR=var(--highlight-literal)]malloc[/COLOR]([COLOR=var(--highlight-keyword)]sizeof[/COLOR](Node)); [COLOR=var(--highlight-comment)]/* This allocates pathNode for its use in the very first head */[/COLOR]
        [COLOR=var(--highlight-keyword)]if[/COLOR] (pathNode == [COLOR=var(--highlight-literal)]NULL[/COLOR]) [COLOR=var(--highlight-comment)]/* If there's not enough memory to allocate pathNode, return NULL */[/COLOR]
            [COLOR=var(--highlight-keyword)]return[/COLOR] ([COLOR=var(--highlight-literal)]NULL[/COLOR]);
    
        token = strtok(*pathCopy,  [COLOR=var(--highlight-variable)]":"[/COLOR]); [COLOR=var(--highlight-comment)]/* Break the pathCopy string into tokens, separator used is ':' */[/COLOR]
        pathNode->str = token; [COLOR=var(--highlight-comment)]/* The first element to add to the linked list is token */[/COLOR]
        pathNode->next = head; [COLOR=var(--highlight-comment)]/* The "next" element to add to the linked list will be the new head */[/COLOR]
        head = pathNode;  [COLOR=var(--highlight-comment)]/* Assign pathNode to the head */[/COLOR]
        [COLOR=var(--highlight-keyword)]while[/COLOR] (token != [COLOR=var(--highlight-literal)]NULL[/COLOR]) [COLOR=var(--highlight-comment)]/* Fill the linked list with the rest of the string */[/COLOR]
        {
            token = strtok([COLOR=var(--highlight-literal)]NULL[/COLOR], [COLOR=var(--highlight-variable)]":"[/COLOR]); [COLOR=var(--highlight-comment)]/* By passing NULL as the first parameter to strtok(), we make sure that strtok() keeps working with */[/COLOR]
                                       [COLOR=var(--highlight-comment)]/* the previous parameter (pathCopy) */[/COLOR]
            [COLOR=var(--highlight-keyword)]if[/COLOR] (token == [COLOR=var(--highlight-literal)]NULL[/COLOR]) [COLOR=var(--highlight-comment)]/* Don't save token NULL in list */[/COLOR]
                [COLOR=var(--highlight-keyword)]break[/COLOR];
            pathNode = [COLOR=var(--highlight-literal)]malloc[/COLOR]([COLOR=var(--highlight-keyword)]sizeof[/COLOR](Node)); [COLOR=var(--highlight-comment)]/* This allocates pathNode for its use in the rest of the heads */[/COLOR]
            [COLOR=var(--highlight-keyword)]if[/COLOR] (pathNode == [COLOR=var(--highlight-literal)]NULL[/COLOR]) [COLOR=var(--highlight-comment)]/* If there are no more tokens left to add to the linked list, return NULL */[/COLOR]
                [COLOR=var(--highlight-keyword)]return[/COLOR] ([COLOR=var(--highlight-literal)]NULL[/COLOR]);
            pathNode->str = token; [COLOR=var(--highlight-comment)]/* Add to the linked list the current token */[/COLOR]
            pathNode->next = head; [COLOR=var(--highlight-comment)]/* The "next" element to add to the linked list will be the new head */[/COLOR]
            head = pathNode; [COLOR=var(--highlight-comment)]/* Assign pathNode to the head */[/COLOR]
        }
        [COLOR=var(--highlight-keyword)]return[/COLOR] (head);
    
    }
    
    
    [COLOR=var(--highlight-comment)]/**
     * listpath - Calls the functions _getenv and _getpathdir
     * @pathCopy: A variable that will store a duplication
     * of the "PATH" parameter
     * Return: A linked list of PATH directories
     */[/COLOR]
    Node *[COLOR=var(--highlight-literal)]listpath[/COLOR]([COLOR=var(--highlight-namespace)]char[/COLOR] **pathCopy)
    {
        [COLOR=var(--highlight-namespace)]char[/COLOR] *getEnv;
        Node *pathDirs;
    
        getEnv = _getenv([COLOR=var(--highlight-variable)]"PATH"[/COLOR]);
        pathDirs = _getpathdir(getEnv, pathCopy); [COLOR=var(--highlight-comment)]/* Here pathCopy is passed as the address of itself pointing to NULL, i.e. `char *pathCopy = NULL` */[/COLOR]
    
        [COLOR=var(--highlight-keyword)]return[/COLOR] (pathDirs); [COLOR=var(--highlight-color)]}[/COLOR]


    I tried to use the following loop to print to the sdtout, it compiles, but doesn't print anything actually , so, I would like to know what I'm doing wrong here, or if there's another way in which _getpathdir function could print its linked list to the stdout before returning head

    Code:
    [COLOR=var(--highlight-namespace)]int[/COLOR] [COLOR=var(--highlight-literal)]main[/COLOR]()
    {
      Node *head = [COLOR=var(--highlight-literal)]NULL[/COLOR];
      Node *current_node = head;
      [COLOR=var(--highlight-namespace)]char[/COLOR] *pathCopy = [COLOR=var(--highlight-literal)]NULL[/COLOR];
      listpath(&pathCopy);
      [COLOR=var(--highlight-keyword)]while[/COLOR] ( current_node != [COLOR=var(--highlight-literal)]NULL[/COLOR])
      {
        [COLOR=var(--highlight-literal)]printf[/COLOR]([COLOR=var(--highlight-variable)]"\n %s\n"[/COLOR], current_node->str);
        current_node = current_node->next;
      }
      [COLOR=var(--highlight-keyword)]return[/COLOR] ([COLOR=var(--highlight-namespace)]0[/COLOR]);
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,898
    Your markup is unacceptable.
    It's an unreadable mess.

    Edit your post (or just reply and I'll fix it), and this time use "copy as text" in your IDE and/or "paste as text" in your browser.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Dec 2021
    Posts
    5
    Quote Originally Posted by Salem View Post
    Your markup is unacceptable.
    It's an unreadable mess.

    Edit your post (or just reply and I'll fix it), and this time use "copy as text" in your IDE and/or "paste as text" in your browser.
    OMG, I'm very sorry, I didn't expect this for real , can you fix it just this time please?

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,898
    No, paste the original code properly.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Dec 2021
    Posts
    5
    Quote Originally Posted by Salem View Post
    No, paste the original code properly.
    I have been trying to print the linked list the program below creates, to see how the path information is actually organized inside of it, having no success in the process.

    Code:
    #define TRUE 1
        #define FALSE 0
        
        extern char **environ;
         
        /*
         * struct Node - singly linked list
         * @str: string - (malloc'ed string)
         * @next: points to the next node
         * Description: singly linked list node structure
         */
        typedef struct Node
        {
         char *str;
         struct Node *next;
        }
    
    
         /**
         * _getenv - searches for the environment string
         * pointed to by name 
         * @name:  This is the C string containing the name
         * of the requested variable
         * Return: the associated value to the string.
         */
        char *_getenv(const char *name)
        {
            int i, j; /* Counters */
            int status; /* boolean variable */
        
        
            for (i = 0; environ[i] != NULL; i++) /* loop over the array of pointers to strings called "environment" until it finds a string value called NULL (the last one) */
            {
                status = 1; /* initialize the status variable as TRUE (1) */
                for (j = 0; environ[i][j] != '='; j++)  /* loop over the the current string value until the symbol '=' is found */
                {
                    if (name[j] != environ[i][j]) /* Check if each byte of the current string value is exactly the same as name */
                    {
                        status = 0; /* if they are not, we notify (set the status variable as FALSE (0)) and break */
                        break;
                    }
                }
        
                if (status) /* IF and ONLY IF we have found that each byte of the current string value is exactly the same as name  */
                {
                    return (&environ[i][j + 1]); /* return the address of the current string value excluding the "=" sign */
                }
            }
            return (NULL); /* This function returns NULL if the environment variable requested does not exist */
        }               /* if the previous return was successfully executed, this return is not executed */
        
        /**
         * _getpathdir - creates a linked list for
         * any environment string
         * @path: the selected environment string
         * @pathCopy: a duplicate of @path
         * Return: a linked list of @path
         */
        Node *_getpathdir(char *path, char **pathCopy)
        {
            char *token = NULL;
            Node *head;
            Node *pathNode;
        
        
            if (path == NULL) /* If path passed is NULL, return NULL */
                return (NULL);
        
            *pathCopy = strdup(path); /* Make a duplicate of path parameter */
        
            head = NULL; /* Initialize the very first token of the linked list to NULL */
            pathNode = malloc(sizeof(Node)); /* This allocates pathNode for its use in the very first head */
            if (pathNode == NULL) /* If there's not enough memory to allocate pathNode, return NULL */
                return (NULL);
        
            token = strtok(*pathCopy,  ":"); /* Break the pathCopy string into tokens, separator used is ':' */
            pathNode->str = token; /* The first element to add to the linked list is token */
            pathNode->next = head; /* The "next" element to add to the linked list will be the new head */
            head = pathNode;  /* Assign pathNode to the head */
            while (token != NULL) /* Fill the linked list with the rest of the string */
            {
                token = strtok(NULL, ":"); /* By passing NULL as the first parameter to strtok(), we make sure that strtok() keeps working with */
                                           /* the previous parameter (pathCopy) */
                if (token == NULL) /* Don't save token NULL in list */
                    break;
                pathNode = malloc(sizeof(Node)); /* This allocates pathNode for its use in the rest of the heads */
                if (pathNode == NULL) /* If there are no more tokens left to add to the linked list, return NULL */
                    return (NULL);
                pathNode->str = token; /* Add to the linked list the current token */
                pathNode->next = head; /* The "next" element to add to the linked list will be the new head */
                head = pathNode; /* Assign pathNode to the head */
            }
            return (head);
        
        }
        
        
        /**
         * listpath - Calls the functions _getenv and _getpathdir
         * @pathCopy: A variable that will store a duplication
         * of the "PATH" parameter
         * Return: A linked list of PATH directories
         */
        Node *listpath(char **pathCopy)
        {
            char *getEnv;
            Node *pathDirs;
        
            getEnv = _getenv("PATH");
            pathDirs = _getpathdir(getEnv, pathCopy); /* Here pathCopy is passed as the address of itself pointing to NULL, i.e. `char *pathCopy = NULL` */
        
            return (pathDirs);
        }
    I tried to use the following loop to print to the sdtout, it compiles, but doesn't print anything actually, so, I would like to know what I'm doing wrong here, or if there's another way in which _getpathdir function could print the final linked list to the stdout before returning head

    Code:
    int main()
        {
          Node *head = NULL;
          Node *current_node = head;
          char *pathCopy = NULL;
          listpath(&pathCopy);
          while ( current_node != NULL)
          {
            printf("\n %s\n", current_node->str);
            current_node = current_node->next;
          }
          return (0);
        }

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,898
    > listpath(&pathCopy);
    You're ignoring the return result.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Dec 2021
    Posts
    5

    Unhappy

    Quote Originally Posted by Salem View Post
    > listpath(&pathCopy);
    You're ignoring the return result.
    I know the function listhpath returns a Node (i.e. pathDirs variable), but I don't get it, should I change then current_nod variable to pathDirs​ in the while loop to make it work? I mean:

    Code:
    int main()
        {
          Node *head = NULL;
          Node *pathDirs = head;
          char *pathCopy = NULL;
          listpath(&pathCopy);
          while (pathDirs != NULL)
          {
            printf("\n %s\n", pathDirs->str);
            current_node = pathDirs->next;
          }
          return (0);
        }

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,898
    > I know the function listhpath returns a Node
    You could have fooled me.

    Here.
    pathDirs = listpath(&pathCopy);
    Is this better?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Registered User
    Join Date
    Dec 2021
    Posts
    5

    Cool Bravo, problem is no more!

    Quote Originally Posted by Salem View Post
    > I know the function listhpath returns a Node
    You could have fooled me.

    Here.
    pathDirs = listpath(&pathCopy);
    Is this better?

    OMG! YOU ARE THE BEST THANK YOU!

    To whom it may concern:

    I just changed a little bit the main.c code, here's the final version of it:

    Code:
    int main()
    {
      Node *head = NULL;
      Node *pathDirs = head;
      char *pathCopy = NULL;
      pathDirs = listpath(&pathCopy);
      while (pathDirs != NULL)
      {
        printf("\n %s\n", pathDirs->str);
        pathDirs = pathDirs->next;
      }
      return (0);
    }

    Then I typed the following compiling command:
    Code:
    gcc -Wall -Werror -Wextra -pedantic -std=gnu99 *.c -o printf_path
    And here's the final output after executing the printf_path program :

    Code:
    root@691c473c3479:/printf_path# ./printf_path
    
    
     /bin
    
    
     /sbin
    
    
     /usr/bin
    
    
     /usr/sbin
    
    
     /usr/local/bin
    
    
     /usr/local/sbin
    Once more, thanks for the assistance. This thread can be closed now.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 05-23-2012, 10:07 AM
  2. c program to print list of files in a directory
    By leo_1024 in forum Linux Programming
    Replies: 3
    Last Post: 01-24-2009, 05:54 AM
  3. Retrieving PATH Environment Variable
    By mercury529 in forum Windows Programming
    Replies: 9
    Last Post: 01-09-2007, 08:02 PM
  4. Adding directory/file names to a linked list
    By thoseion in forum C Programming
    Replies: 13
    Last Post: 12-08-2006, 01:13 PM
  5. Setting path environment variable
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 09-01-2006, 03:03 PM

Tags for this Thread