0

The code is a copy of shell. It needs to make commands like

ls -a > test.txt | sort < test.txt

When I compiled the program, it didn't work as intended. So I thought of trying gdb. When I used gdb I got the right answer with the right output. How is it possible?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{

    int ind=0; // Indicator that shows if the app is still working
    
    // Some details to make it look like shell

    /*char *user;
    user=getlogin();*/

    /*uid_t user;
    user=getuid();
    struct passwd *nick;
    nick=getpwuid(user);
    char *login;
    login=(nick->pw_name);*/

    // For some reason after using anything related to the user, the program messes up. 

    printf("\n");
    printf("\033[0;32muser\033[0m");
    putchar(':');
    printf("\033[0;34m~\033[0m");
    printf("$ ");

    while(ind==0)
    {

        // Reading the input and organizing it.

        // 1) Reading from stdin and putting it in an array.

        int max_size=16;
        char *chars=malloc(max_size*sizeof(char));
        int cur_size=max_size;
        int cur_len=0;
        int max_len=0;
        int word_amount=2;
        int com_amount=1;
        if(chars==NULL)
        {
            fprintf(stderr, "Something was wrong with the memory. Error code: %d: %s\n", errno, strerror(errno));
            return 1;
        }
        int c;
        int i=0;
        c=getchar();
        if(c==EOF || c=='\n')
        {
            ind=1;
            continue;
        }
        while(c!='\n')
        {
            if(c=='|')
            {
                com_amount++;
            }
            if(c==' ')
            {
                word_amount++;
                if(cur_len>max_len)
                {
                    max_len=cur_len;
                }
                cur_len=0;
            }
            else
            {
                cur_len++;
            }
            chars[i]=(char)c;
            i++;
            if(i==cur_size)
            {
                cur_size+=max_size;
                chars=realloc(chars, cur_size);
                if(chars==NULL)
                {
                    fprintf(stderr, "Something was wrong with the memory. Error code: %d: %s\n", errno, strerror(errno));
                    return 1;
                }
            }
            c=getchar();
        }
        if(word_amount==2)
        {
            max_len=cur_len;
        }
        chars[i]='\0';
        max_len+=2;

        //Testing

        /*i=0;
        while(chars[i]!='\0')
        {
            printf("%d :%c\n", i, chars[i]);
            i++;
        }*/

        // 2) Making it from a char array to string array using the counter.
        // max_len is the size of the longest word + 2 (Just in case)
        // word_amount is the amount of the words + 1 (Just in case)

        int ind[com_amount];
        char *argv[word_amount];
        char file_name[com_amount][word_amount];
        for(i=0; i<word_amount; i++)
        {
            argv[i]=malloc(max_len);
            if(argv[i]==NULL)
            {
                fprintf(stderr, "Something was wrong with the memory. Error code: %d: %s\n", errno, strerror(errno));
                return 1;
            }
        }
        int j=0;
        int w=0;
        int s=0;
        int y=0;

        for(i=0; i<word_amount; i++)
        {
            ind[i]=0;
        }

        /*for(i=0; i<com_amount; i++)
        {
            file_name[i]=NULL;
        }*/

        i=0;

        while(chars[i]!='\0')
        {
            if(chars[i]=='>')
            {
                ind[s]=1;
                while(chars[i]!='|' && chars[i]!='\0')
                {
                    i++;
                    if(chars[i]==' ')
                    {
                        while(chars[i]==' ')
                        {
                            i++;
                        }
                    }
                    file_name[s][y]=chars[i];
                    y++;
                }
                file_name[s][y-1]='\0';
                y=0;
            }
            else if(chars[i]=='<')
            {
                ind[s]=2;
                while(chars[i]!='|' && chars[i]!='\0')
                {
                    i++;
                    if(chars[i]==' ')
                    {
                        while(chars[i]==' ')
                        {
                            i++;
                        }
                    }
                    file_name[s][y]=chars[i];
                    y++;
                }
                file_name[s][y]='\0';
                y=0;
            }
            if(chars[i]=='|')
            {
                s++;
            }
            if(chars[i]!=' ')
            {
                argv[j][w]=chars[i];
                w++;
                i++;
            }
            else if(chars[i]==' ')
            {
                while(chars[i]==' ' && chars[i]!='\0')
                {
                    i++;
                }
                if(chars[i]=='\0')
                {
                    break;
                }
                argv[j][w]='\0';
                j++;
                w=0;
            }
        }
        if(j==0)
        {
            argv[j][w]='\0';
            argv[j+1]=NULL;
        }
        else
        {
            if(ind[s]==0)
            {
                argv[j+1]=NULL;
            }
            else
            {
                argv[j]=NULL;
            }
        }

        //Testing

        /*for(i=0; argv[i]!=NULL; i++)
        {
            printf("%d: %s\n", i, argv[i]);
        }*/

        /*for(i=0; i<com_amount; i++)
        {
            printf("%d: %s\n", i, file_name[i]);
        }*/

        // 3) Finally, making an array of pointers, that will be pointing at those words without '|'

        j=0;
        char **args[com_amount];
        args[0]=argv;
        for(i=1; (i<(word_amount-2)) && (j<(com_amount-1)); i++)
        {
            if(((argv[i][0]=='|') && (argv[i][1]=='\0')) || (argv[i][0]=='\n'))
            {
                argv[i]=NULL;
                j++;
                args[j]=argv+i+1;
            }
        }

        //Testing

        /*for(i=0; i<com_amount; i++)
        {
            for(j=0; args[i][j]!=NULL; j++)
            {
                printf("%d: %s\n", i, args[i][j]);
            }
        }*/

        //Preparation done, we have an array of commands. Now to the pipes and forks.

        printf("\033[0;32muser\033[0m");
        putchar(':');
        printf("\033[0;34m~\033[0m");
        printf("$ ");

        pid_t son[com_amount];
        int *fds=NULL;
        fds=(int *)malloc((com_amount-1)*2*sizeof(int));

        for(i=0; i<(com_amount-1); i++)
        {
            if(pipe(fds+2*i)==-1)
            {
                fprintf(stderr, "Something went wrong while making a pipe. Error code: %d: %s\n", errno, strerror(errno));
                return 1;
            }
        }
        
        i=0;

        if(ind[i]==1)
        {
            int fd;
            fd=open(file_name[i], O_WRONLY | O_CREAT | O_TRUNC, 0600);
            if(fd==-1)
            {
                fprintf(stderr, "Something went wrong while creating a file. Error code: %d: %s\n", errno, strerror(errno));
                return 1;
            }
            son[i]=fork();
            if(son[i]==-1)
            {
                fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                return 1;
            }
            if(son[i]==0)
            {
                dup2(fd, 1);
                for(j=0; j<2*(com_amount-1); j++)
                {
                    close(fds[j]);
                }
                close(fd);
                execvp(args[i][0], args[i]);
                return 2;
            }
            close(fd);
        }
        else if(ind[i]==2)
        {
            int fd;
            fd=open(file_name[i], O_RDONLY, 0600);
            if(fd==-1)
            {
                fprintf(stderr, "Something went wrong while creating a file. Error code: %d: %s\n", errno, strerror(errno));
                return 1;
            }
            son[i]=fork();
            if(son[i]==-1)
            {
                fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                return 1;
            }
            if(son[i]==0)
            {
                dup2(fd, 0);
                if(com_amount>1)
                {
                    dup2(fds[2*i+1], 1);
                }
                for(j=0; j<2*(com_amount-1); j++)
                {
                    close(fds[j]);
                }
                close(fd);
                execvp(args[i][0], args[i]);
                return 2;
            }
            close(fd);
        }
        else
        {
            son[i]=fork();
            if(son[i]==-1)
            {
                fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                return 1;
            }
            if(son[i]==0)
            {
                if(com_amount>1)
                {
                    dup2(fds[2*i+1], 1);
                }
                for(j=0; j<2*(com_amount-1); j++)
                {
                    close(fds[j]);
                }
                execvp(args[i][0], args[i]);
                return 2;
            }
        }

        for(int i=1; i<(com_amount-1); i++)
        {
            if(ind[i-1]==1)
            {
                if(ind[i]==1)
                {
                    int fd;
                    fd=open(file_name[i], O_WRONLY | O_CREAT | O_TRUNC, 0600);
                    if(fd==-1)
                    {
                        fprintf(stderr, "Something went wrong while creating a file. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    son[i]=fork();
                    if(son[i]==-1)
                    {
                        fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    if(son[i]==0)
                    {
                        dup2(fd, 1);
                        for(j=0; j<2*(com_amount-1); j++)
                        {
                            close(fds[j]);
                        }
                        close(fd);
                        execvp(args[i][0], args[i]);
                        return 2;
                    }
                    close(fd);
                }
                else if(ind[i]==2)
                {
                    int fd;
                    fd=open(file_name[i], O_RDONLY, 0600);
                    if(fd==-1)
                    {
                        fprintf(stderr, "Something went wrong while creating a file. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    son[i]=fork();
                    if(son[i]==-1)
                    {
                        fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    if(son[i]==0)
                    {
                        dup2(fd, 0);
                        dup2(fds[2*i+1], 1);
                        for(j=0; j<2*(com_amount-1); j++)
                        {
                            close(fds[j]);
                        }
                        close(fd);
                        execvp(args[i][0], args[i]);
                        return 2;
                    }
                    close(fd);
                }
                else
                {
                    son[i]=fork();
                    if(son[i]==-1)
                    {
                        fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    if(son[i]==0)
                    {
                        dup2(fds[2*(i-1)], 0);
                        dup2(fds[2*i+1], 1);
                        for(j=0; j<2*(com_amount-1); j++)
                        {
                            close(fds[j]);
                        }
                        execvp(args[i][0], args[i]);
                        return 2;
                    }
                }
            }
            else
            {
                if(ind[i]==1)
                {
                    int fd;
                    fd=open(file_name[i], O_WRONLY | O_CREAT | O_TRUNC, 0600);
                    if(fd==-1)
                    {
                        fprintf(stderr, "Something went wrong while creating a file. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    son[i]=fork();
                    if(son[i]==-1)
                    {
                        fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    if(son[i]==0)
                    {
                        dup2(fds[2*(i-1)], 0);
                        dup2(fd, 1);
                        for(j=0; j<2*(com_amount-1); j++)
                        {
                            close(fds[j]);
                        }
                        close(fd);
                        execvp(args[i][0], args[i]);
                        return 2;
                    }
                    close(fd);
                }
                else if(ind[i]==2)
                {
                    int fd;
                    fd=open(file_name[i], O_RDONLY, 0600);
                    if(fd==-1)
                    {
                        fprintf(stderr, "Something went wrong while creating a file. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    son[i]=fork();
                    if(son[i]==-1)
                    {
                        fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    if(son[i]==0)
                    {
                        dup2(fd, 0);
                        dup2(fds[2*i+1], 1);
                        for(j=0; j<2*(com_amount-1); j++)
                        {
                            close(fds[j]);
                        }
                        close(fd);
                        execvp(args[i][0], args[i]);
                        return 2;
                    }
                    close(fd);
                }
                else
                {
                    son[i]=fork();
                    if(son[i]==-1)
                    {
                        fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    if(son[i]==0)
                    {
                        dup2(fds[2*(i-1)], 0);
                        dup2(fds[2*i+1], 1);
                        for(j=0; j<2*(com_amount-1); j++)
                        {
                            close(fds[j]);
                        }
                        execvp(args[i][0], args[i]);
                        return 2;
                    }
                }
            }
        }

        if(com_amount>1)
        {
            i=com_amount-1;

            if(ind[i-1]==1)
            {
                if(ind[i]==1)
                {
                    int fd;
                    fd=open(file_name[i], O_WRONLY | O_CREAT | O_TRUNC, 0600);
                    if(fd==-1)
                    {
                        fprintf(stderr, "Something went wrong while creating a file. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    son[i]=fork();
                    if(son[i]==-1)
                    {
                        fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    if(son[i]==0)
                    {
                        dup2(fd, 1);
                        for(j=0; j<2*(com_amount-1); j++)
                        {
                            close(fds[j]);
                        }
                        close(fd);
                        execvp(args[i][0], args[i]);
                        return 2;
                    }
                    close(fd);
                }
                else if(ind[i]==2)
                {
                    int fd;
                    fd=open(file_name[i], O_RDONLY, 0600);
                    if(fd==-1)
                    {
                        fprintf(stderr, "Something went wrong while creating a file. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    son[i]=fork();
                    if(son[i]==-1)
                    {
                        fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    if(son[i]==0)
                    {
                        dup2(fd, 0);
                        for(j=0; j<2*(com_amount-1); j++)
                        {
                            close(fds[j]);
                        }
                        close(fd);
                        execvp(args[i][0], args[i]);
                        return 2;
                    }
                    close(fd);
                }
                else
                {
                    son[i]=fork();
                    if(son[i]==-1)
                    {
                        fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    if(son[i]==0)
                    {
                        dup2(fds[2*(i-1)], 0);
                        for(j=0; j<2*(com_amount-1); j++)
                        {
                            close(fds[j]);
                        }
                        execvp(args[i][0], args[i]);
                        return 2;
                    }
                }
            }
            else
            {
                if(ind[i]==1)
                {
                    int fd;
                    fd=open(file_name[i], O_WRONLY | O_CREAT | O_TRUNC, 0600);
                    if(fd==-1)
                    {
                        fprintf(stderr, "Something went wrong while creating a file. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    son[i]=fork();
                    if(son[i]==-1)
                    {
                        fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    if(son[i]==0)
                    {
                        dup2(fds[2*(i-1)], 0);
                        dup2(fd, 1);
                        for(j=0; j<2*(com_amount-1); j++)
                        {
                            close(fds[j]);
                        }
                        close(fd);
                        execvp(args[i][0], args[i]);
                        return 2;
                    }
                    close(fd);
                }
                else if(ind[i]==2)
                {
                    int fd;
                    fd=open(file_name[i], O_RDONLY, 0600);
                    if(fd==-1)
                    {
                        fprintf(stderr, "Something went wrong while creating a file. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    son[i]=fork();
                    if(son[i]==-1)
                    {
                        fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    if(son[i]==0)
                    {
                        dup2(fd, 0);
                        for(j=0; j<2*(com_amount-1); j++)
                        {
                            close(fds[j]);
                        }
                        close(fd);
                        execvp(args[i][0], args[i]);
                        return 2;
                    }
                    close(fd);
                }
                else
                {
                    son[i]=fork();
                    if(son[i]==-1)
                    {
                        fprintf(stderr, "Something went wrong while making a process. Error code: %d: %s\n", errno, strerror(errno));
                        return 1;
                    }
                    if(son[i]==0)
                    {
                        dup2(fds[2*(i-1)], 0);
                        for(j=0; j<2*(com_amount-1); j++)
                        {
                            close(fds[j]);
                        }
                        execvp(args[i][0], args[i]);
                        return 2;
                    }
                }
            }
        }

        for(j=0; j<2*(com_amount-1); j++)
        {
            close(fds[j]);
        }

        while(wait(NULL) != -1);
        
    }

    printf("Back to main shell\n\n");
    return 0;
}

When compiling it and just running it the answer is nothing, in gdb it outputs the sorted list of files in stdout.

Delev1n
  • 51
  • 3
  • 3
    You probably have undefined behavior somewhere, so running it in different ways produces different results. Try using valgrind to check for invalid memory accesses. – Barmar Dec 15 '21 at 20:50
  • 6
    There's way too much code here for anyone to try to search for your bugs. You need to narrow down to a [mre]. – Barmar Dec 15 '21 at 20:51
  • *For some reason after using anything related to the user, the program messes up* You should check to see that `getuid()` and `getpwuid()` didn't return NULL. – Steve Summit Dec 15 '21 at 21:00
  • 1
    Your code is more complicated than it needs to be with too much special casing. I'd also use a `struct` to save info related to each command inside the pipe. And, closing the correct pipe ends in _both_ parent and the children is a bit tricky. For a working example, see my answer: https://stackoverflow.com/questions/52823093/fd-leak-custom-shell/52825582 – Craig Estey Dec 15 '21 at 21:12
  • Is sort supposed to get its input from the pipe or the file that is redirected in? – Jerry Jeremiah Dec 15 '21 at 21:15
  • @SteveSummit Small correction: [`getuid`](https://man7.org/linux/man-pages/man2/getuid.2.html) can not fail. [`getlogin`](https://man7.org/linux/man-pages/man3/getlogin.3.html) and [`getpwuid`](https://man7.org/linux/man-pages/man3/getpwnam.3.html) can. – Oka Dec 15 '21 at 21:17
  • You declare `int ind[com_amount];` and then later `for(i=0; i – Jerry Jeremiah Dec 15 '21 at 21:29
  • I think the main reason you are having trouble is you fork the ls and it writes the results to the file but you don't wait for it to do that - you just charge ahead and tell sort to read the not yet filled in file. It works in the debugger because when you step through it you do that slow enough that ls can finish before you open the file for sort to read. You need to wait for the forked process to finish before continuing. – Jerry Jeremiah Dec 15 '21 at 21:52
  • @SteveSummit they are not returning NULL, and they return the right ID, but they mess up the whole program afterwards – Delev1n Dec 16 '21 at 05:04
  • @JerryJeremiah thanks for pointing out, I changed that, but the bug still remains – Delev1n Dec 16 '21 at 05:06
  • @JerryJeremiah if I use while(wait(NULL)!=-1) before forking, will it help? I tried putting it before calling fork with '<' but still the same result – Delev1n Dec 16 '21 at 05:18
  • You need to wait for the child in the parent code after each fork and before you continue with the next step. – Jerry Jeremiah Dec 16 '21 at 20:40

0 Answers0