/* * sshchat.c * * Client component of sshchat, connects to server, identifies itself using ~/.sshchat file and forwards stdin/stdout. * * Author: Dario Rodriguez dario@softhome.net * This program is licensed under the terms of the GPL v2.1+ */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "socklib.h" #include "sbuf.h" #include "sshchat.h" #define MAXIDSIZE 128 #define CONNTIMEOUT 2000 #define SELECTTIMEOUT 1000 #define BUFSIZE 16384 #define INFD 0 #define OUTFD 1 int main(int argc, char *argv[]) { char id[MAXIDSIZE]; char *ptr; char *host; int port; long hostsize; int socket; sbuf *c2s,*s2c; sselect *ssel; int forcedexit; int readfds[2]; int writefds[2]; int nreadfds; int nwritefds; int i; int queued; if(argc!=2 || strcmp(argv[argc-1],"--help")==0) { fprintf(stderr,"Syntax: %s username",argv[0]); return(1); /* no id */ } strncpy(id,argv[1],sizeof(MAXIDSIZE)); id[MAXIDSIZE-1]='\0'; if((ptr=strchr(id,' '))!=NULL) *id='\0'; /* spaces not allowed */ /* open socket to server */ if((host=ipv4_genip("127.0.0.1",&hostsize))==NULL) return(-3); /* couldn't resolv localhost */ if((port=ipv4_genport("sshchat",SERVERPORT))==-1) { free(host),host=NULL; return(-4); /* couldn't resolv port */ } if((socket=ipv4_preconnect(host,hostsize,port))==-1) { free(host),host=NULL; return(-5); /* couldn't connect to localhost (1) */ } if(ipv4_connect(socket,CONNTIMEOUT)==-1) { free(host),host=NULL; return(-6); /* couldn't connect to localhost (2) */ } ipv4_postconnect(socket); free(host),host=NULL,hostsize=0; /* alloc I/O buffers */ if((c2s=sbuf_init(BUFSIZE))==NULL || (s2c=sbuf_init(BUFSIZE))==NULL) { close(socket),socket=-1,sbuf_free(c2s),c2s=NULL; return(-7); /* couldn't alloc buffers */ } if((ssel=sselect_init())==NULL) { close(socket),socket=-1,sbuf_free(c2s),c2s=NULL,sbuf_free(s2c),s2c=NULL; return(-8); /* couldn't alloc select struct */ } /* prefeed the identification */ sbuf_addstr(c2s,id); sbuf_addstr(c2s,"\n"); /* forward data */ forcedexit=0; while(!forcedexit) { sselect_reset(ssel); if(sbuf_count(c2s)<BUFSIZE) sselect_addread(ssel,INFD,NULL); if(sbuf_count(c2s)>0) sselect_addwrite(ssel,socket,NULL); if(sbuf_count(s2c)>0) sselect_addwrite(ssel,OUTFD,NULL); if(sbuf_count(s2c)<BUFSIZE) sselect_addread(ssel,socket,NULL); if(sselect_wait(ssel,SELECTTIMEOUT)<1) continue; nreadfds=sselect_getread(ssel,readfds,sizeof(readfds)/sizeof(readfds[1])); nwritefds=sselect_getwrite(ssel,writefds,sizeof(writefds)/sizeof(writefds[1])); for(i=0;i<nreadfds && i<(sizeof(readfds)/sizeof(readfds[0]));i++) { if(readfds[i]==INFD && sbuf_count(c2s)<BUFSIZE) { if((queued=sock_queued(readfds[i]))==0) { forcedexit=1; break; } sbuf_discard(c2s); sbuf_fill(c2s,INFD,queued); } if(readfds[i]==socket && sbuf_count(s2c)<BUFSIZE) { if((queued=sock_queued(readfds[i]))==0) { forcedexit=1; break; } sbuf_discard(s2c); sbuf_fill(s2c,socket,queued); } } for(i=0;i<nwritefds && i<(sizeof(writefds)/sizeof(writefds[0]));i++) { if(writefds[i]==OUTFD && sbuf_count(s2c)>0) sbuf_send(s2c,OUTFD,sbuf_count(s2c)); if(writefds[i]==socket && sbuf_count(c2s)>0) sbuf_send(c2s,socket,sbuf_count(c2s)); } } /* normal exit */ close(socket),socket=-1; sbuf_free(c2s),c2s=NULL; sbuf_free(s2c),s2c=NULL; sselect_free(ssel),ssel=NULL; return(0); }