how exactly does pclose work in C?

If i have the pointer to the pipe, which is given to pclose, what exactly does pclose do with it?

this is what pclose does

/*
* pclose --
*    Pclose returns -1 if stream is not associated with a `popened' command,
*    if already `pclosed', or waitpid returns an error.
*/
int
pclose(iop)
FILE *iop;
{
    register struct pid *cur, *last;
    int pstat;
    pid_t pid;

    (void)fclose(iop);

    /* Find the appropriate file pointer. */
    for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
    if (cur->fp == iop)
    break;
    if (cur == NULL)
    return (-1);

    do {
        pid = waitpid(cur->pid, &pstat, 0);
    } while (pid == -1 && errno == EINTR);

    /* Remove the entry from the linked list. */
    if (last == NULL)
    pidlist = cur->next;
    else
    last->next = cur->next;
    free(cur);
    
    return (pid == -1 ? -1 : pstat);
}

But I don't understand what its doing, its somehow using structs as linked lists...
Can someone show me what each line does?

How can a for loop be like
for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
and where is its start and ending brackets?

It is easy, if no brackets are present, it means it only executes one instruction (or block) just after that line. That means:

for a hundred of times
{
     cout << "foo";
     cout << "bar" << endl;
}

You will see 100 times foobar

for a hundred of times
      cout << "foo";
cout << "bar" << endl;

You'll see 100 times foo and once bar at the end.

and:

for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)

Means:

At start, we define last to be NULL and cur to be pidlist.
The for loop will continue while cur is != 0, that is, while (bool)cur is true.

At end of EACH LOOP, it defines last to be cur, and cur to be the next member of cur.

This is an usual way to loop through an structure of nodes. A node is an structure that knows who structure is next and who is last.

So the loop starts on cur, goes ->next, goes ->next, and ->next... until cur = cur->next is NULL. That is, there is no next after this.

I hope that is a bit helpful for you.

That may not be what pclose on your system does. It's an internal implementation detail. This is also why I can't tell you what each line does -- it's using structure members defined somewhere else. Another implementation-specific detail.

That looks like very, very, very old code by the way, to still use the old K&R function definition syntax.

Broadly, what it does is

int
pclose(iop)
FILE *iop;
{
    register struct pid *cur, *last;
    int pstat;
    pid_t pid;
    // Close the file.
    (void)fclose(iop);
    // pidlist must be a global variable of type 'struct pid', whatever that is.
    // It must contain the PID to wait for, and the matching FILE *, since it
    // wasn't contained in the FILE pointer itself.
    /* Find the appropriate file pointer. */
    // Whenever there's no brackets, it acts like it only encloses the next
    // statement, like this:
    for (last = NULL, cur = pidlist; cur; last = cur, cur = cur->next)
    {
        if (cur->fp == iop)
        {
            break;
        }
    }

    if (cur == NULL)
    {
        return (-1);
    }

    // Wait for the process.  Keep trying until it either succeeds or fails.
    do {
        pid = waitpid(cur->pid, &pstat, 0);
    } while (pid == -1 && errno == EINTR);

    /* Remove the entry from the linked list. */
    if (last == NULL)
    pidlist = cur->next;
    else
    last->next = cur->next;
    free(cur);
    
    return (pid == -1 ? -1 : pstat);
}

You can make a linked list with structures by having a structure that contains a pointer to another structure of the same type.

struct node
{
        struct node *next;
        struct node *prev;
        int value;
};


int main(void)
{
    struct node a,b, *z;
    a.prev=NULL;
    a.next=&b;
    a.value=3;

    b.prev=&a;
    b.next=NULL;
    b.value=5;

    z=&a;
    while(z != NULL)
    {
        printf("node %p=%d\n", z, z->value);
        z=z->next;
    }
}
$ ./a.out
node 0x7fff3f48bce0=3
node 0x7fff3f48bcc0=5
$

here its supposed to return the exit code of the command, in this case is the exit code equal to pstat? and why didnt it use WEXITSTATUS?

still i dont understand how something can be removed from the chain..
can u make an example where there is like 5 structs in the chain, then u remove the 1st or 3rd or last so i can see the easy way to remove structs from the chain

Sorry, could you rephrase that?

Because the code is very, very old.

All you do is alter the pointers so nothing's pointing to the node you want to remove any more. Then you're free to delete it or free() it or whatever.

Can you use the word "you"? Can you tell me you've actually compiled any of the code I've written for you?

Sorry, could you rephrase that?

Ok
the return of pclose() is supposed to be the exit code of the command given to the given pointer to a file descriptor, so here in the code i put in the very top it returns the variable 'pstat', is this equal to the exit number of the given command?

pid == -1 ? -1 : pstat

is equivalent to

if(pid == -1) { return(-1); } 
else { return(pstat); }

sorta unrelated question:
if u have an array that not all elements have been put in, and u do a for loop for it, will it crash if it tries to access one of the elements that doesnt have anything in it? If not, is the value equal to NULL ?

Please don't use netspeak. We really discourage it here; and if you know what "you" means, you also know how to spell it!

What do you mean by 'put in'? And what kind of array, anyway?

Depends what it is and what you're doing with it. An array of integers may have unpredictable values if you never put anything in it before you used it, but won't crash in of itself. (Of course, the things you do with unexpected numbers may cause it to crash, but that's neither here nor there.) An array of pointers may be full of garbage pointers aimed at nowhere in particular which will crash if you dereference them. Or, worse, they may be pointers to VALID if unintended memory, which will do bizzare unpredictable things instead of crashing.

But in any of these cases it's not the array that's crashing -- it's what you do with the values you find in it.