this is a server client “rsh”program.This rsh (remote shell) allows me to execute a series of sh commands on a remote Unix system.
something like: if the command on client is
client linux03 uname -a
it should get an answer like:
Linux linux03 2.4.9-12 #1 Tue Oct 30 18:41:57 EST 2001 i686 unknown
the program is upposed to support till 3 pipes.
am spending so much time on it and i cant think clearly anymore.
any suggest please
server code:
Code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
//#include <iostream.h>
#include <unistd.h>
#define SADDR struct sockaddr *
#define MAXCMDS 3
#define MAXARGS 3
//function to output err to stderr and exit
void xerror(char msg[])
{
perror(msg);
exit(1);
}
//function to parse char array into tokens based on passed delimiters
int parse (char *line, char *delimitor, char *token[])
{
int i=1;
strtok(line, delimitor);
token[0]=line;
while((token[i]=(char *)strtok(NULL, delimitor))!=NULL)
{
while (*token[i] == ' ') token[i]++; /* eliminate leading spaces */
i++;
}
return i;
}
int execute_cmds(char commands[], char buffer[]) {
int i, k; //loop variables
int no_cmds, no_args, op_size; //number of commands, arguments, & output size
char *cmd[MAXCMDS]; //pointer to array of command 'strings'
char *args[MAXARGS]; // pointer to array of arguments
int pfds[MAXCMDS][2]; //array of pipe file descriptors
//debug
printf("in execute_cmds \n");
for(i=0 ; i<MAXCMDS ; i++) pipe(pfds[i]); //setup pipes
//debug
printf("pipes done \n");
for(i=0 ; i<MAXCMDS ; i++) cmd[i] = NULL;
no_cmds = parse(commands, "|", cmd); //null cmd array, parse command string
printf("Number of commands = %d\n", no_cmds);
for (i=0 ; i<no_cmds ; i++) printf("cmd[%d]=%s\n", i, cmd[i]);
for(i=0 ; i<no_cmds ; i++) //loop for numebr of commands' times
{
if(!fork()) //fork new child
{
//debug
printf("in child pid %d \n", getpid());
close(1); //close child stdout
no_args = parse(cmd[i], " ", args); //parse each command
args[no_args]=NULL; dup(pfds[i][1]); //make stdout = pfds[i][1] - input of pipe i
close(pfds[i][0]); //close input of same pipe
if(i!=0)
//if not child 1 connect child stdin to o/p of previous pipe
{
close(0); //close child stdin
dup(pfds[i-1][0]); //make stdin = pfds[i-1][0] - output of pipe before
close(pfds[i-1][1]); //close input of pipe before
}
for(k=0 ; k<MAXCMDS ; k++)
{
if(k!=i && k!=i-1) { close(pfds[k][0]); close(pfds[k][1]);}
}
no_args = parse(cmd[i], " ", args); //parse each command
args[no_args]=NULL;
//debug
fprintf(stderr, "%s\n", cmd[i]);
for(i=0 ; i<no_args ; i++) fprintf(stderr, "%s\n", args[i]);
execvp(cmd[i], args); //execute command i with args
exit(0);
}
}
for(i=0 ; i<MAXCMDS ; i++){ //close all unwanted pipes in parent
if(i!=(no_cmds-1)) { close(pfds[i][0]); close(pfds[i][1]);}
}
close(pfds[no_cmds-1][1]);
op_size = read(pfds[no_cmds-1][0],buffer,500); //store o/p in last pipe in buffer
buffer[op_size] = '\0';
close(pfds[no_cmds-1][0]);
//debug
printf("buffer = %s ; size = %d\n", buffer, op_size);
printf("leaving execute_cmds\n");
return op_size;
}
int main(int argc, char *argv[])
{
struct sockaddr_in sa; //struct to hold socket address variables
char cmd_line[501], buf[501]; //arrays for command line and data buffer
int s, new_s, length_recv, length_send, n = sizeof(sa);
//debug
printf("start\n");
if ((s=socket(AF_INET,SOCK_STREAM,0)) < 0) xerror("socket"); // make socket
sa.sin_family = AF_INET; // set type
sa.sin_addr.s_addr = htonl(INADDR_ANY); // set wildcard
sa.sin_port = htons(6001); // set port
if ( bind(s, (SADDR)&sa, n) < 0 ) xerror("bind"); // bind address
listen(s, 5); // queue callers
for( ; ; )
{
if ( ( new_s = accept(s, (SADDR)0, 0) ) < 0 ) xerror("accept");// accept call
if(!fork())
{ // child process
printf("in child server pid %d \n", getpid());
close(s);
length_recv = recv(new_s, cmd_line, 501, 0); // read
cmd_line[length_recv] = '\0'; // delimit string
printf("Command string recieved\n");
length_send = execute_cmds(cmd_line, buf);
//execute commands, store results in buffer buf[]
printf("Message being returned - %s\n", buf);
send(new_s, buf, length_send, 0); // return message
//debug
//send(new_s, "done something \0", 20, 0);
printf("Returned result\n");
close(new_s); //close server socket
exit(0);
}
// parent process
close(new_s); //close server socket
}
printf("Have exited forever loop!!!\n");
}
client code which works fine
Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
struct hostent *hp; struct sockaddr_in sa;
int s, n_chars, n = sizeof(struct sockaddr_in);
char buf[501];
if ((s=socket(AF_INET,SOCK_STREAM,0)) < 0) exit(1);// make socket
if ( (hp = gethostbyname(argv[1])) == 0 ) exit(1); // get host struct
memset(&sa, 0, n); // init struct
memcpy(&sa.sin_addr, hp->h_addr, hp->h_length); // set host
sa.sin_port = htons(6001); // set port
sa.sin_family = AF_INET; // set type
if (connect(s,(struct sockaddr *)&sa,n)<0) exit(1);// connect
send(s, argv[2], strlen(argv[2]), 0); // write message
printf("\nSent command string\n");
n_chars=recv(s, buf, 500, 0);
buf[n_chars]='\0';
printf("%d chars output returned, o/p=%s\n", n_chars, buf);
}
thanks