/* rlsd.c - a remote ls server - with paranoia */ #include #include #include #include #include #include #include #include #define PORTNUM 15000 /* our remote ls server port */ #define HOSTLEN 256 #define oops(msg) { perror(msg) ; exit(1) ; } int main(int ac, char *av[]) { struct sockaddr_in saddr; /* build our address here */ struct hostent *hp; /* this is part of our */ char hostname[HOSTLEN]; /* address */ int sock_id,sock_fd; /* line id, file desc */ FILE *sock_fpi, *sock_fpo; /* streams for in and out */ FILE *pipe_fp; /* use popen to run ls */ char dirname[BUFSIZ]; /* from client */ char command[BUFSIZ]; /* for popen() */ int dirlen, c; /** Step 1: ask kernel for a socket **/ sock_id = socket( PF_INET, SOCK_STREAM, 0 ); /* get a socket */ if ( sock_id == -1 ) oops( "socket" ); /** Step 2: bind address to socket. Address is host,port **/ bzero( (void *)&saddr, sizeof(saddr) ); /* clear out struct */ gethostname( hostname, HOSTLEN ); /* where am I ? */ hp = gethostbyname( hostname ); /* get info about host */ bcopy( (void *)hp->h_addr, (void *)&saddr.sin_addr, hp->h_length); saddr.sin_port = htons(PORTNUM); /* fill in socket port */ saddr.sin_family = AF_INET ; /* fill in addr family */ if ( bind(sock_id, (struct sockaddr *)&saddr, sizeof(saddr)) != 0 ) oops( "bind" ); /** Step 3: allow incoming calls with Qsize=1 on socket **/ if ( listen(sock_id, 1) != 0 ) oops( "listen" ); /* * main loop: accept(), write(), close() */ while ( 1 ){ sock_fd = accept(sock_id, NULL, NULL); /* wait for call */ if ( sock_fd == -1 ) oops("accept"); /* open reading direction as buffered stream */ if( (sock_fpi = fdopen(sock_fd,"r")) == NULL ) oops("fdopen reading"); if ( fgets(dirname, BUFSIZ-5, sock_fpi) == NULL ) oops("reading dirname"); sanitize(dirname); /* open writing direction as buffered stream */ if ( (sock_fpo = fdopen(sock_fd,"w")) == NULL ) oops("fdopen writing"); sprintf(command,"ls %s", dirname); if ( (pipe_fp = popen(command, "r")) == NULL ) oops("popen"); /* transfer data from ls to socket */ while( (c = getc(pipe_fp)) != EOF ) putc(c, sock_fpo); pclose(pipe_fp); fclose(sock_fpo); fclose(sock_fpi); } } sanitize(char *str) /* * it would be very bad if someone passed us an dirname like * "; rm *" and we naively created a command "ls ; rm *" * * so..we remove everything but slashes and alphanumerics * There are nicer solutions, see exercises */ { char *src, *dest; for ( src = dest = str ; *src ; src++ ) if ( *src == '/' || isalnum(*src) ) *dest++ = *src; *dest = '\0'; }