1

I am new in UNIX and new in Programming on it using C language.

What I want to do is the simple implementation for telnet.

I made all required connection on both sides(Server & Client).

On the server: any request I receive, I fork a new process to handle it

void createProcess() {
    int pid = fork();
    if( pid == CHILD ) {
        transferHandling(s);
        close(s);
        _exit(0);
    }
}

This method for handling commands that come from the client side:

int transferHandling(int socket) {
    char buf[20];
    char command[1024];
    int n, pid, fd[2];
    char *shell, *ps1;
    if( checkLogin(socket) == 0 ) { // Used to check user account
        send(socket, "Login Succeeded\n", 16, 0);
        if( setupENV(info->name) == 0 ) {  // setuid and setgid for the user
            if( pipe(fd) == ERROR ) {
                send(socket, "Server Busy\n", 12, 0);
                return 1;
            }
                    // Here I make a process to run the default shell for the user
                    // and make pipe between them
            if((pid = fork()) > 0) {
                dup2(fd[0], STDOUT_FILENO);
                close(fd[1]);

                //read commands from socket
                while(1) {
                    n = recv(socket, command, 1024, 0);
                                    // send the commands received to the child which contains the default shell
                    write(fd[0], command, n);
                }
            } else {
                dup2(fd[1], STDIN_FILENO);
                dup2(socket, STDOUT_FILENO);
                dup2(socket, STDERR_FILENO);
                close(fd[0]);

                //run default shell
                shell = getpwnam(info->name)->pw_shell;
                execlp(shell, shell, NULL);
            }
        } else {
            return 1; // setup ENV error
        }
    } else {
        send(socket, "Login Failed\n", 13, 0);
    }
}

This program runs successfully with any command, but when the client write any command like: wc, cd, bash (to run any other shell). The program is hanged.

This is the client side after the connection is setup.

if(login(soc)) { // send the user information for the server
        char cmd[2024], cc[1024];
        int n;
        while(1) {
            printf("Reading\n");
            write(1, "username@hostname> ", 19);
            n = read(0, cmd, 2024);  // read the command from the STDIN, and send it to server
            send(soc, cmd, n, 0);

            printf("Receiving Now\n");
            n = recv(soc, cmd, 2024, 0); // getting back the command output
            write(1, cmd, n);
        }
    }
Mahmoud Emam
  • 1,499
  • 4
  • 20
  • 37

1 Answers1

0

You've got your pipe file descriptors wrong. You should:

write(fd[1], ...);

and:

dup2(fd[0], STDIN_FILENO);

BTW, there is no need for the intermediate process to read commands from the socket and send them through the pipe to the shell. You can directly redirect the shell's input from the socket. Moreover, there is no need for dup2() if writing directly to the pipe. Finally, the infinite loop to do this seems to be a very bad idea, as it will spin when the shell dies.

jop
  • 2,226
  • 15
  • 16
  • Do you mean, that I should remove the `fork()` and make `dup2(socket, STDIN_FILENO)` and the same for the output, then `exec` the default shell for a user – Mahmoud Emam Mar 15 '13 at 09:21
  • Yes. Call `fork()` once in `createProcess()` and that's it. – jop Mar 15 '13 at 09:25
  • dosent' work, dup2(socket, STDIN_FILENO); dup2(socket, STDOUT_FILENO); dup2(socket, STDERR_FILENO); //close(fd[0]); //run default shell shell = getpwnam(info->name)->pw_shell; execlp(shell, shell, NULL); – Mahmoud Emam Mar 15 '13 at 09:30
  • The redirection should be ok. Are you sure it isn't the login procedure? Try commenting it out and use `nc` as client. Moreover, the shell should not prompt for commands when `stdin` has been redirected, yet, still work. – jop Mar 15 '13 at 09:38