server.c

// compile with -lncurses

#include <mine.h>
#include <ncurses.h>
#include <signal.h>
#include <fcntl.h>


void callpeer ();
short int getpeer (char *filename);
void disconnect (int clt);
void handlequit (int sig);
void sendclient (int clt);
void setin (); 
void takeclient (int fd);
void terminate (); 

short int EAR, IN[10], in=0, maxy, maxx, peers=0, acptsw=1;
char *scktfile, *clearline;

int main (int argc, char *argv[]) {
	char buffer[65], *tok;
	struct {char mtxt[70];}inbx[10];
	short int ch,i,x,I=0, bytes;
	struct sockaddr_un tmpSA;
	socklen_t tlen=sizeof(tmpSA);
	
	scktfile=ec_malloc(strlen(argv[1]));
	strcpy(scktfile,argv[1]);
	
	if ((EAR=loclsckt(scktfile)) < 0) {printf("loclsckt fail in main(): %d", EAR); return -1;}
	if ((listen(EAR,10)) !=0) {perror("listen fail in main()"); return -2;}
	signal(SIGINT,handlequit);
	for (i=0;i<10;i++) {inbx[i].mtxt[0]=0;IN[i]=-1;}
	
	initscr();
	getmaxyx(stdscr,maxy,maxx);
	clearline=ec_malloc(maxx);
	for (i=0;i<maxx;i++) clearline[i]=32; 
	clearline[maxx]=0;
	halfdelay(5);
	noecho();
	start_color();
	init_pair(1, COLOR_MAGENTA,COLOR_BLACK);
	init_pair(2, COLOR_BLACK,COLOR_MAGENTA);
	init_pair(3, COLOR_MAGENTA,COLOR_WHITE);
	init_pair(4, COLOR_GREEN,COLOR_BLACK);
	init_pair(5, COLOR_BLACK,COLOR_GREEN);

	attron(COLOR_PAIR(3));
	printw("local socket server open on %s", scktfile);
	attroff(COLOR_PAIR(3));	
	mvaddstr(1,0,"Ctrl-c to quit");
					mvprintw(2,0, "%s", clearline);
	refresh();
	
	fcntl(EAR,F_SETFL,O_NONBLOCK);

	while (ch=getch()) {
		if ((IN[in]=accept(EAR,(struct sockaddr*)&tmpSA,&tlen)) > 0) takeclient(IN[in]);
		if (ch=='T') terminate();
		if (ch=='C') callpeer();
		if ((ch > 47) && (ch < 58)) sendclient(ch-48);
		for (i=0;i<10;i++)  if (IN[i] > 2) if ((bytes=read(IN[i],buffer,64)) > 0) {
			buffer[bytes]=0;
			for (x=bytes;x>=0;x--) if (buffer[x]=='\n') buffer[x]=0;
			attron(COLOR_PAIR(1));
			for (x=1;x<10;x++) {
				strcpy(inbx[10-x].mtxt,inbx[9-x].mtxt);
				mvprintw((maxy-2)-x,0,"%s",clearline);
				mvprintw((maxy-2)-x,0,"%s",inbx[10-x].mtxt);
			}
			if ((strcmp(buffer,"TERMINATED")) == 0) {disconnect(i);
				sprintf(inbx[0].mtxt,"Client %d signed off.",i);
				setin();}
			else sprintf(inbx[0].mtxt,"fd%d: %s",IN[i],buffer);
			mvprintw(maxy-12,0,"%s",clearline);
			mvprintw(maxy-12,0,"%s",inbx[0].mtxt);
			attroff(COLOR_PAIR(1));
		}			
		mvprintw(1,50,"iteration %d", I); I++;    // main loop still running...
		refresh();
	}

	endwin();
	close(EAR);
	unlink(scktfile);
	return 0;
}	


void callpeer () {
	char blank[maxx], spath[70];
	short int i, peer;
	sprintf(blank,"Socket path");
	for(i=strlen(blank);i<maxx;i++) blank[i]=32;
	blank[maxx]=0;
	mvprintw(5,0,"%s",blank);
	mvprintw(5,11,": ");
	echo();
	getstr(spath);
	noecho();
	halfdelay(5);
	peer=getpeer(spath);
	if (peer < 0) {
		mvprintw(2,5,"%s",clearline);
		attron(COLOR_PAIR(4));
		mvprintw(7,5,"%s", clearline);
		mvprintw(7,5,"FAILED connect");
		attroff(COLOR_PAIR(4));
		return;}
	IN[in]=peer;
	mvprintw(3,0,"%s",clearline);
	mvprintw(3,0,"New connection on file descriptor %d",IN[in]);
	attron(COLOR_PAIR(2));
	mvprintw(maxy-1,in*8+1,"%d: FD%d",in,IN[in]);
	attroff(COLOR_PAIR(2));
	fcntl(IN[in],F_SETFL,O_NONBLOCK);
	setin();
}


void disconnect (int clt) {
	close(IN[clt]);
	IN[clt]=-1;
	mvprintw(maxy-1,clt*8,"        ");
}	


short int getpeer (char *filename) {
	char me[108],*ptr;
	short int i, cxt, retv;
	struct sockaddr_un peer;
	size_t size;

	strcpy(me,scktfile);
	i=strlen(me);
	ptr=strrchr(filename,'/');
	strcat(me,ptr);
	me[i]='-';
	unlink(me);

	if (strlen(me) > 107) {puts("filename too long"); handlequit(2);}
	cxt=loclsckt(me);

	peer.sun_family=AF_LOCAL;
	strcpy(peer.sun_path,filename);
	size=SUN_LEN(&peer);
	if ((retv=connect(cxt,(struct sockaddr*)&peer,size)) < 0) return retv;
	return cxt;
}


void handlequit (int sig) {
	short int pid=getpid(), i;
	for (i=0;i<10;i++) if (IN[i]>0) {
		write(IN[i],"TERMINATED\n",11);
		disconnect(i);}
	endwin();
	close(EAR);
	puts("DONE");
	unlink(scktfile);
	kill(pid,9);
}


void sendclient (int clt) {
	int i;        
	char messg[64],blank[maxx], *tok;
	if (IN[clt] < 0) sprintf(blank,"There is no client %d", clt);
	else strcpy(blank,"Message");
	for(i=strlen(blank);i<maxx;i++) blank[i]=32;
	blank[maxx]=0;
	mvprintw(3,0,"%s",blank);
	if (IN[clt] < 0) return;
	mvprintw(3,7,": ");
	echo();
	getstr(messg);
	noecho();
	halfdelay(5);
	if ((messg[0] == '\n') || ((write(IN[clt],messg,64)) == -1)) sprintf(blank,"Message NOT delivered.");
	else sprintf(blank,"Delivered message.");
	for(i=strlen(blank);i<maxx;i++) blank[i]=32;
	mvprintw(3,0,"%s",blank);
}    	


void setin () {
	short int i;
	for (i=0;i<10;i++) {
		if (IN[i] == -1) {
			if (i<9 && acptsw==0) {
				mvprintw(maxy-1,73,"       ");
				acptsw=1;} 
			break;}
		if (i==8) acptsw = 0;}
 	in=i;
}	


void takeclient (int fd) {
	short int i;
	char messg[64];
	mvprintw(3,0,"%s",clearline);
	if (acptsw == 1) {
		mvprintw(3,0,"New connection on file descriptor %d",IN[in]);
		sprintf(messg, "You are connected.\n");
		attron(COLOR_PAIR(2));
		mvprintw(maxy-1,in*8+1,"%d: FD%d",in,IN[in]);
		attroff(COLOR_PAIR(2));
		fcntl(IN[in],F_SETFL,O_NONBLOCK);}
	else if (acptsw == 0) {
		mvprintw(3,0,"Refused additional connection ");
		attron(COLOR_PAIR(5));
		mvprintw(maxy-1,73,"%d: FULL",in);
		attroff(COLOR_PAIR(5));
		sprintf(messg, "TERMINATED\n");
		close(IN[in]); IN[in]=-1;
	}	
	write(IN[in],messg,strlen(messg));
	setin();
}	


void terminate () {
	char messg[]="TERMINATED", blank[maxx];
	short int who,i;
	sprintf(blank,"Terminate who[0-9]");
	for(i=strlen(blank);i<maxx;i++) blank[i]=32;
	blank[maxx]=0;
	mvprintw(5,0,"%s",blank);
	mvprintw(5,18,"? ");
	nocbreak(); echo();
	who=getch();
	halfdelay(5); noecho();
	who-=48; 
	if ((who > 9) || (who < 0) || IN[who] < 0) {
		sprintf(blank,"%d can't be terminated",who);
		for(i=strlen(blank);i<maxx;i++) blank[i]=32;
		mvprintw(6,0,"%s",blank);
		return;}
	write(IN[who],messg,strlen(messg));
	disconnect(who);
	sprintf(blank,"Socket at FD %d closed.",who);
	for(i=strlen(blank);i<maxx;i++) blank[i]=32;
	mvprintw(5,0,"%s", blank);
	setin();
}


client.c

#include <mine.h>
#include <signal.h>

short int ME;

void handlequit (int sig) {
	short int pid=getpid();
	if (sig != 133) write(ME,"TERMINATED\n",11);
	close(ME);
	kill(pid,9);
}


int main(int argc, char *argv[]) {
	short int len, pid;
	char messg[80];
	struct sockaddr_un servr; 
	size_t size;
	if ((ME=socket(PF_LOCAL,SOCK_STREAM,0)) < 0) perror("socket");
	signal(SIGINT,handlequit);
	
	servr.sun_family=AF_LOCAL;
	strcpy(servr.sun_path,argv[1]);
	size=SUN_LEN(&servr);
	if ((connect(ME,(struct sockaddr*)&servr,size)) != 0) { 
		perror("connect fail in main()"); handlequit(2);}
	
	pid=fork();
	if (pid == 0) {
		while (1) {
			char *string=linein(stdin);
			write(ME,string,strlen(string));
		}
		return;
	}
	 
	while ((len=read(ME,messg,80)) > 0) {
		messg[len]=0;
		system("echo -en \"\033[1;33m\"");
		printf("From server: %s\n",messg);
		system("echo -en \"\033[1;00m\"");   
		fflush(stdout);	
		if (strncmp(messg,"TERMINATED",11) == 0) break;
	}
	handlequit(133);
	return 0;
}