Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Invoking vi editor from a telnet-like server 2

Status
Not open for further replies.

apatterno

Programmer
Nov 26, 2002
368
US
I am writing a server that uses the telnet protocol to communicate with clients.

One of the commands I would like to implement will allow the client to edit their user-info with vi. Two concerns:

1. How do I invoke vi, such that the input from the socket goes into vi, and vi's output goes back to the client?

2. How do I start vi in such a way that prohibits the user from opening any files other than the one specified on the command line?

I realize this might be a dumb question, however I am coming from a Microsoft background and am just beginning to learn about Unix programming.

But thanks in advance, for all your help.
Will
 
> 1. How do I invoke vi, such that the input from the socket goes into vi, and vi's output goes back to the client?
Try this, which just uses stdin and stdout.
I think all you need to is replace these with the two socket file descriptors between you and the client
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>

#define PIPE_R      0
#define PIPE_W      1

#define MAX(a,b)    ((a>b)?(a):(b))

/* map the appropriate ends of the pipes to stdin and stdout */
/* then start the 'vi' process to edit a file */
void server ( int cli2ser[2], int ser2cli[2] ) {
    int     res;
    char    *cmd[] = { &quot;/bin/vi&quot;, &quot;tmp&quot;, NULL };
    int     to_client   = ser2cli[PIPE_W];
    int     from_client = cli2ser[PIPE_R];

    close( cli2ser[PIPE_W] );
    close( ser2cli[PIPE_R] );

    close( STDIN_FILENO );
    res = dup( from_client );   /* stdin reopened as one end of a pipe */
    if ( res == -1 ) {
        perror( &quot;dup 1&quot; );
    } else {
        fprintf( stderr, &quot;Duped %d\n&quot;, res );
    }

    close( STDOUT_FILENO );
    res = dup( to_client );     /* stdout reopened as one end of a pipe */
    if ( res == -1 ) {
        perror( &quot;dup 2&quot; );
    } else {
        fprintf( stderr, &quot;Duped %d\n&quot;, res );
    }

    res = execv( cmd[0], cmd );
    perror( &quot;exec failed&quot; );
}

/* in_fd and out_fd are the connections to the outside world */
/* cli2ser and ser2cli are the pipes to the server */
/* this function loops, copying data between the server and the outside world */
void client ( int in_fd, int out_fd, int cli2ser[2], int ser2cli[2], pid_t server_pid ) {
    char    buff[BUFSIZ];
    int     to_server   = cli2ser[PIPE_W];
    int     from_server = ser2cli[PIPE_R];
    fd_set  master_read_fds;
    fd_set  read_fds;
    int     max_fd;
    
    close( cli2ser[PIPE_R] );
    close( ser2cli[PIPE_W] );

    /* select needs the maximum fd + 1 */
    printf( &quot;FD's=%d,%d,%d,%d\n&quot;, in_fd, out_fd, to_server, from_server );
    max_fd = in_fd;
    max_fd = MAX(max_fd,from_server);
    max_fd++;
    FD_ZERO( &master_read_fds );    
    FD_SET( in_fd, &master_read_fds );
    FD_SET( from_server, &master_read_fds );
    
    while ( 1 ) {
        int n;
        read_fds = master_read_fds;
        n = select( max_fd, &read_fds, NULL, NULL, NULL );  /* wait for something to happen */
        if(0)fprintf( stderr, &quot;Select returned %d\n&quot;, n );
        if ( n == -1 ) {
            perror( &quot;select&quot; );
            break;  /* escape from infinity */
        }
        if ( FD_ISSET( in_fd, &read_fds ) ) {
            ssize_t amount;
            amount = read( in_fd, buff, BUFSIZ );
            if(0)fprintf( stderr, &quot;%d bytes from input to server\n&quot;, amount );
            if ( amount == 0 ) {
                fprintf( stderr, &quot;EOF from input&quot; );
                break;
            }
            if ( amount == -1 ) {
                perror( &quot;error reading input&quot; );
                break;
            }
            if ( amount != write( to_server, buff, amount ) ) {
                perror( &quot;write to server error&quot; );
            }
        }
        if ( FD_ISSET( from_server, &read_fds ) ) {
            ssize_t amount;
            amount = read( from_server, buff, BUFSIZ );
            if(0)fprintf( stderr, &quot;%d bytes from server to output\n&quot;, amount );
            if ( amount == 0 ) {
                fprintf( stderr, &quot;EOF from server&quot; );
                break;
            }
            if ( amount == -1 ) {
                perror( &quot;error reading server&quot; );
                break;
            }
            if ( amount != write( out_fd, buff, amount ) ) {
                perror( &quot;write to out error&quot; );
            }
        }
    }
}

int main ( ) {
    int     client_to_server[2];
    int     server_to_client[2];
    int     status;
    pid_t   pid;
    
    status = pipe( client_to_server );
    if ( status == -1 ) {
        perror( &quot;Cant create client_to_server pipes&quot; );
        return EXIT_FAILURE;
    }
    printf( &quot;client_to_server pipe FD's=%d,%d\n&quot;, client_to_server[0], client_to_server[1] );
    status = pipe( server_to_client );
    if ( status == -1 ) {
        perror( &quot;Cant create server_to_client pipes&quot; );
        return EXIT_FAILURE;
    }
    printf( &quot;server_to_client pipe FD's=%d,%d\n&quot;, server_to_client[0], server_to_client[1] );

    pid = fork();
    if ( pid == (pid_t)-1 ) {
        perror( &quot;Cant create process&quot; );
        return EXIT_FAILURE;
    }
    if ( pid == 0 ) {
        /* child */
        server( client_to_server, server_to_client );
    } else {
        /* parent */
        client( STDIN_FILENO, STDOUT_FILENO, client_to_server, server_to_client, pid );
    }
    return 0;
}

> 2. How do I start vi in such a way that prohibits the user from opening any files
No idea
I know 'rvi' prevents the user from running things like a shell, but I don't think that prevents the user from editing another file.
 
Nice idea Salem.

apatterno.
You may want to look at the expect extension for the
scripting language tcl and tcl's own socket interface.
This would simplify your second problem considerably.
You could sandbox vi by running it in an expect wrapper
examining all user input for commands that you don't
want executed.


HTH
 
Thank you salem and marsd.

I have solved my second problwm by using vim with the -Z option... seems to work fine.

Will
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top