0

I am required to develop a stripped down version of online IDE. It will follow a client-server architecture. Client side will have three commands.

  1. CREATE
  2. RUN
  3. QUIT

When the client chooses 'create' , the command would be sent to a server. The server will open windows. The first window will be a text editor in which the user will be able to write the code. The second window will act like an automatic parser which will parse the program that the users have written in the first window. The server side will read the user program at an interval of 1 second and parse the program using Lex and yacc. Any error found in the program should be reported in window 2. If there are no errors, the window will simply state "No error".

I have done till parsing part. But i could not understand, how to open a terminal from program and print error to that terminal. I am posting my code here.

SERVER SIDE:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>     // This is for string related call.
    #include<errno.h>      // This is for error handling.
    #include<limits.h>     // this is for different type limit checking.
    #include<ctype.h>      // This is for different type checking.
    #include<fcntl.h>      // This is for unblocking socket.
    #include<unistd.h>     // this is for different type typical system call.
    #include<sys/socket.h> // This header file defines miscellaneous socket related constant, types, and function.
    #include<sys/types.h>  // This header file defines miscellaneous types 
    #include<sys/sem.h>    // This header file defines semaphores related types, function.
    #include<sys/wait.h>   // This header file defines blocking and wait related types and function.
    #include<sys/ipc.h>    // This header file defines mainly interprocess communication related structures.
    #include<netinet/in.h> // This header file defines system parameter related to address.
    #include<arpa/inet.h>  // This header file defines different types macros .
    #include<time.h>       // This header file is included for getting times.
    #include<signal.h>     
    #include<netdb.h>
    #include<sys/shm.h>    // This header file is included for shared memory .

    #define PORT "5000"   // This is the port server will be listening on
    #define MAX 4096 
    #define NAZMUL
    extern void parse(FILE*,FILE*);


    int listener;         // Server will be listening on this socket id.


    /*.....................This function convert the IP address................................*/
    void *convert(struct sockaddr *sa)
    {
        if(sa->sa_family == AF_INET)
            return &(((struct sockaddr_in *)sa)->sin_addr);
        return &(((struct sockaddr_in6 *)sa)->sin6_addr);
    }
    /*.........................................................................................*/



    /*...............We are handling SIGINT SIGNAL here..........................................*/
    void sigint_handler(int sig)
    {
        int nbytes;
        char buffer[MAX];
        strcpy(buffer, "quit");
        #if hi
        if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) < 0)
        {
            if(nbytes == 0)
            {
                printf("SERVER: client is closed\n");
                close(new_fd);
                close(listener);
                exit(EXIT_SUCCESS);
            }
            else
            {
                perror("SERVER:");
                close(new_fd);
                close(listener);
                exit(EXIT_FAILURE);
            }
        }
        close(listener);
        close(new_fd);
        #endif
        exit(EXIT_SUCCESS);
    }
    /*............................................................................................*/



    /*.......................We are handling SIGCHLD signal here..................................*/
    void sigchild_handler(int sig)
    {
        // waitpid() might overwrite errno, so we save and restore it:
        int saved_errno = errno;

        while(waitpid(-1, NULL, WNOHANG) > 0);

        errno = saved_errno;
    }
    /*..............................................................................................*/



    /*...........................We are generating random number here...............................*/





    int main()
    {
        int yes = 1;              // this for setsockopt()
        int status;           // this is for holding return value of getaddrinfo()
        int proces_id_gedit;        // this will hold return value of fork()
        int flags;             // this for fcntl() call
        char file_name[128];        // This is for saving filename.
        char command[128],filenameout[128];
        FILE *fp, *output_fp;
        int create_flag = 0;  // To check whether create command came or not

        char *line = NULL;
        size_t length = 0;
        ssize_t nread;


        struct sigaction for_sigint, for_sigchild; // these struct, we have to pass to sigaction()

        char buffer[MAX];    // this will be used in send(), recv()
        int nbytes;          // This will hold return value of send(), recv()
        int new_fd;           // newly accept()ed socket descriptor.

        struct sockaddr_storage client_addr; //it will hold client socket address.
        char client_IP[INET6_ADDRSTRLEN];       // It will hold the ip address of client ip address.
        socklen_t addr_len;                   // It will hold length of client ip address.



        /*................GET us an successful socket and bind it...........................................*/
        struct addrinfo hints, *ref, *p;
        memset(&hints, 0, sizeof hints);
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_flags = AI_PASSIVE;

        if((status = getaddrinfo(NULL, PORT, &hints, &ref)) != 0)
        {
            fprintf(stderr, "SERVER: getaddrinfo:%s\n",gai_strerror(status) );
            exit(EXIT_FAILURE);
        }

        for(p = ref; p != NULL; p = p->ai_next)
        {
            if((listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
            {
                continue;
            }

            if(setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
            {
                perror("SERVER:");
                exit(EXIT_FAILURE);
            }
             /*....Setting the socket in non-blocking mode...*/
            if ((flags = fcntl(listener, F_GETFL, 0)) < 0) 
            { 
                perror("SERVER(flags = fcntl):");
                continue;
            } 

            if (fcntl(listener, F_SETFL, flags | O_NONBLOCK) < 0) 
            { 
                perror("SERVER( fcntl):");
                continue;
            } 
            /*..............................................*/

            if(bind(listener, p->ai_addr, p->ai_addrlen) == -1)
            {
                continue;
            }

            break; // we get successfull socket and bind, so we do not need to traverse anymore.
        }


        if(p == NULL) //checking whether we get a successful binding socket or not
        {
            fprintf(stderr, "we did not get successful binding socket\n");
            exit(EXIT_FAILURE);
        }

        freeaddrinfo(ref);

        /*..................we are handling here SIGINT SIGNAL....................................*/
        for_sigint.sa_handler = sigint_handler;
        for_sigint.sa_flags = 0;
        sigemptyset(&for_sigint.sa_mask);
        if(sigaction(SIGINT, &for_sigint, NULL) < 0)
        {
            perror("SERVER(sigint):");
            exit(EXIT_FAILURE);
        }
        /*............................................................................................*/


        /*.......................We are handling SIGCHLD signal here.................................*/
        for_sigchild.sa_handler = sigchild_handler;
        for_sigchild.sa_flags = SA_RESTART;
        sigemptyset(&for_sigchild.sa_mask);
        if(sigaction(SIGCHLD, &for_sigchild, NULL) < 0)
        {
            perror("SERVER(SIGCHLD):");
            exit(EXIT_FAILURE);
        }
        /*.............................................................................................*/



        listen(listener, 5);  // we are listening here.
        printf("SERVER:We are waiting for connection......................................\n");



        for(;;)
        {   
            addr_len = sizeof(client_addr);
            if((new_fd = accept(listener, (struct sockaddr *)&client_addr, &addr_len)) < 0)  // we are accepting new connection here.
            {

            }   
            else
            {
                /*....Setting the socket in non-blocking mode...*/
                if ((flags = fcntl(new_fd, F_GETFL, 0)) < 0) 
                { 
                    perror("SERVER(flags = fcntl):");
                    continue;
                } 

                if (fcntl(new_fd, F_SETFL, flags | O_NONBLOCK) < 0) 
                { 
                    perror("SERVER( fcntl):");
                    continue;
                } 
                /*..............................................*/


                inet_ntop(client_addr.ss_family, convert((struct sockaddr *)&client_addr), client_IP, sizeof client_IP);
                printf("SERVER: We got connection from %s\n",client_IP );

                if( fork() == 0)
                {   
                    close(listener); // child process does not need this.
                    for(;;)
                    {

                        memset(buffer, 0, 4096);
                        if((nbytes = recv(new_fd, buffer, MAX, 0)) == 0)
                        {
                            printf("SERVER: client is closed\n");
                            close(new_fd);
                            close(listener);
                            exit(EXIT_SUCCESS);

                        }
                        else
                        {


                            if(strcmp(buffer, "quit") == 0)
                            {
                                memset(buffer, 0, 4096);
                                strcpy(buffer, "quit");
                                if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) < 0)
                                {
                                    if(nbytes == 0)
                                    {
                                        printf("SERVER: client is closed\n");
                                        close(new_fd);
                                        close(listener);
                                        exit(EXIT_SUCCESS);
                                    }
                                    else
                                    {

                                    }
                                }
                                else
                                {
                                    if(create_flag == 1)
                                    {
                                        remove(file_name);
                                        remove(filenameout);
                                        create_flag = 0;
                                    }
                                    printf("SERVER: Connection with client %d is closed\n",new_fd );
                                    close(new_fd);
                                    close(listener);
                                    exit(EXIT_SUCCESS);
                                }

                            }
                            else if(strcmp(buffer, "create") == 0)
                            {
                                printf("create command came\n");
                                memset(buffer, 0, 4096);
                                strcpy(buffer, "we got create command");
                                if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) == 0)
                                {

                                    printf("SERVER: client is closed\n");
                                    close(new_fd);
                                    close(listener);
                                    exit(EXIT_SUCCESS);


                                }

                                sprintf(file_name, "%d.txt",getpid() );
                                sprintf(filenameout,"%dout.txt",getpid());
                                sprintf(command,"gedit %s",file_name);
                                signal(SIGCHLD, SIG_IGN);
                                if((proces_id_gedit= fork())== 0)
                                {close(new_fd);
                                    system(command);
                                }
                                else
                                    create_flag = 1;



                            }
                            else if(strcmp(buffer, "run") == 0)
                            {
                                printf("run command came\n");
                                memset(buffer, 0, 4096);
                                output_fp = fopen(filenameout, "r");
                                while((nread = getline(&line, &length, output_fp)) != -1)
                                {
                                    strcat(buffer, line);
                                }
                                free(line);
                                fclose(output_fp);
                                //printf("%s\n",buffer );
                                if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) == 0)
                                {
                                    if(nbytes == 0)
                                    {
                                        printf("SERVER: client is closed\n");
                                        close(new_fd);
                                        close(listener);
                                        exit(EXIT_SUCCESS);
                                    }
                                    else
                                    {

                                    }
                                }
                                char temp[128];
                                sprintf(temp, "kill -9 %d",proces_id_gedit);
                                //printf("%s\n",temp );
                                system(temp);
                                remove(filenameout);
                                remove(file_name);
                                create_flag = 0;
                            }
                            else
                            {
                                #if nazmul
                                memset(buffer, 0, 4096);
                                strcpy(buffer, "you entered invalid command");
                                if((nbytes = send(new_fd, buffer, strlen(buffer) + 1, 0)) < 0)
                                {
                                    if(nbytes == 0)
                                    {
                                        printf("SERVER: client is closed\n");
                                        close(new_fd);
                                        close(listener);
                                        exit(EXIT_SUCCESS);
                                    }
                                    else
                                    {}

                                }
                                #endif
                            }

                            if(create_flag == 1)
                            {
                                sleep(1);
                                fp = fopen(file_name, "r");
                                output_fp=fopen(filenameout, "w");
                                if ( fp != NULL)
                                {
                                    //printf("we are calling parse\n");
                                    parse(fp, output_fp);
                                    fclose(fp);
                                }

                                fclose(output_fp);

                            }
                        } 

                    }/*..........................................END OF FOR LOOP OF EACH CLIENT HANDLING PROCESS................*/

                }/*..............................................END OF FORK IF BLOCK...........................................*/
                else
                {
                    close(new_fd);  // parent does not need this
                    continue;
                }

            }/*..................................................END OF ACCEPT ELSE BLOCK....................................*/

        }/*......................................................END OF OF MAIN FOR LOOP.......................................*/

    }/*..........................................................END OF MAIN BLOCK.........................................................*/   

I am just posting server side here. This might be big code to go through. You can answer just without reading the code. I assumed that I run both client and server on my machine.

  • 2
    Hello! Please see [ask] and how to create a [mcve]. – grooveplex Feb 10 '19 at 14:24
  • @grooveplex, that is why I told, you might answer without seeing the code. because, my code do not have problem. I just need something to add. I just post the code , if someone want to go through this. – NAZMUL HUSSAIN Feb 10 '19 at 14:27
  • Well, but if your code doesn't have a problem, you shouldn't include your in the question, in my opinion. I would just ask "how to open a terminal window from a program written in C" and be done with it. I don't think the server-side, client-side and the parsing code will make the answer any different. – grooveplex Feb 10 '19 at 14:31
  • Basically, the server should not open a window. The server might be located on a different machine, and the user@client cannot even see the "window" – wildplasser Feb 10 '19 at 14:32
  • What I'm saying is, someone will come here, say "oh, you need to use this function from that package and then you can do it", and then it's up to you to adapt it to your code. – grooveplex Feb 10 '19 at 14:32
  • @wildplasser, yea you are right. I assume that i only run both server and client on my machine. I just want some remedy on this situation. – NAZMUL HUSSAIN Feb 10 '19 at 14:41
  • @grooveplex, "how to open a terminal from a c program written in c " has many answer, but the problem is , how I print something one that terminal is difficult to me – NAZMUL HUSSAIN Feb 10 '19 at 14:43
  • Look into the sourcecode for Rstudio or anaconda. (both are web-based,I think) `man openpty` for inspiration – wildplasser Feb 10 '19 at 14:45
  • Well, then [edit] your question to *remove* all of the irrelevant code, and then *add* what you have tried so far. – grooveplex Feb 10 '19 at 14:45
  • You don't need so many comments – lost_in_the_source Feb 10 '19 at 15:18
  • You don't need a terminal in order to display a message; you just need some window which displays text. The window doesn't need to accept input. What you are asking is how to create a GUI, which is a very broad question. To get an answer, you'll need to be a lot more specific. You should also edit your tags; practically none of them are appropriate. Your question really has nothing to do with yacc, lex or even networking. – rici Feb 10 '19 at 15:21
  • @rici, I am very new to programming. can you guide me please, how can I do that. And which tags should I mention? or You might edit this question. – NAZMUL HUSSAIN Feb 10 '19 at 15:33
  • I guess you need to stream the messages to the WebUI and have a simple text box there to print the messages. No real terminal involved... – eckes Feb 10 '19 at 15:59
  • 1
    in windows, exec*() the `cmd.com` in linux exec*() xterm – user3629249 Feb 10 '19 at 20:29

0 Answers0