238 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* talk.c Copyright Michael Temari 08/01/1996 All Rights Reserved */
 | |
| 
 | |
| #include <sys/types.h>
 | |
| #include <sys/stat.h>
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <unistd.h>
 | |
| #include <stdlib.h>
 | |
| #include <signal.h>
 | |
| #include <utmp.h>
 | |
| #include <termios.h>
 | |
| #include <net/gen/netdb.h>
 | |
| #include <net/hton.h>
 | |
| #include <net/gen/socket.h>
 | |
| #include <net/gen/in.h>
 | |
| #include <net/gen/inet.h>
 | |
| #include <net/gen/tcp.h>
 | |
| #include <net/gen/udp.h>
 | |
| 
 | |
| #include "talk.h"
 | |
| #include "proto.h"
 | |
| #include "net.h"
 | |
| #include "screen.h"
 | |
| 
 | |
| _PROTOTYPE(int main, (int argc, char *argv[]));
 | |
| _PROTOTYPE(void DoTalk, (void));
 | |
| 
 | |
| int main(argc, argv)
 | |
| int argc;
 | |
| char *argv[];
 | |
| {
 | |
| char *p;
 | |
| struct hostent *hp;
 | |
| struct stat st;
 | |
| struct utmp utmp;
 | |
| int slot;
 | |
| FILE *fp;
 | |
| 
 | |
|    if(argc < 2 || argc > 3) {
 | |
|    	fprintf(stderr, "Usage: talk user[@host] [tty]\n");
 | |
|    	return(-1);
 | |
|    }
 | |
| 
 | |
|    /* get local host name */
 | |
|    if(gethostname(lhost, HOST_SIZE) < 0) {
 | |
|    	fprintf(stderr, "talk: Error getting local host name\n");
 | |
|    	return(-1);
 | |
|    }
 | |
| 
 | |
|    /* get local user name and tty */
 | |
|    if((slot = ttyslot()) < 0) {
 | |
|    	fprintf(stderr, "talk: You are not on a terminal\n");
 | |
|    	return(-1);
 | |
|    }
 | |
|    if((fp = fopen(UTMP, "r")) == (FILE *)NULL) {
 | |
|    	fprintf(stderr, "talk: Could not open %s\n", UTMP);
 | |
|    	return(-1);
 | |
|    }
 | |
|    if(fseek(fp, (off_t) sizeof(utmp) * slot, SEEK_SET)) {
 | |
|    	fprintf(stderr, "talk: Could not seek %s\n", UTMP);
 | |
|    	fclose(fp);
 | |
|    	return(-1);
 | |
|    }
 | |
|    if(fread((char *)&utmp, sizeof(utmp), 1 , fp) != 1) {
 | |
|    	fprintf(stderr, "talk: Could not read %s\n", UTMP);
 | |
|    	fclose(fp);
 | |
|    	return(-1);
 | |
|    }
 | |
|    fclose(fp);
 | |
|    strncpy(luser, utmp.ut_user, USER_SIZE < sizeof(utmp.ut_user) ?
 | |
|    				USER_SIZE : sizeof(utmp.ut_user));
 | |
|    luser[USER_SIZE] = '\0';
 | |
| 
 | |
|    /* get local tty */
 | |
|    if((p = ttyname(0)) == (char *)NULL) {
 | |
|    	fprintf(stderr, "talk: You are not on a terminal\n");
 | |
|    	return(-1);
 | |
|    }
 | |
|    strncpy(ltty, p+5, TTY_SIZE);
 | |
|    ltty[TTY_SIZE] = '\0';
 | |
| 
 | |
|    /* check if local tty is going to be writable */
 | |
|    if(stat(p, &st) < 0) {
 | |
|    	perror("talk: Could not stat local tty");
 | |
|    	return(-1);
 | |
|    }
 | |
|    if((st.st_mode & S_IWGRP) == 0) {
 | |
|    	fprintf(stderr, "talk: Your terminal is not writable.  Use: mesg y\n");
 | |
|    	return(-1);
 | |
|    }
 | |
| 
 | |
|    /* get remote user and host name */
 | |
|    if((p = strchr(argv[1], '@')) != (char *)NULL)
 | |
|    	*p++ = '\0';
 | |
|    else
 | |
|    	p = lhost;
 | |
|    strncpy(ruser, argv[1], USER_SIZE);
 | |
|    ruser[USER_SIZE] = '\0';
 | |
|    strncpy(rhost, p, HOST_SIZE);
 | |
|    rhost[HOST_SIZE] = '\0';
 | |
| 
 | |
|    /* get remote tty */
 | |
|    if(argc > 2)
 | |
|    	strncpy(rtty, argv[2], TTY_SIZE);
 | |
|    else
 | |
|    	rtty[0] = '\0';
 | |
|    rtty[TTY_SIZE] = '\0';
 | |
| 
 | |
|    if((hp = gethostbyname(rhost)) == (struct hostent *)NULL) {
 | |
|    	fprintf(stderr, "talk: Could not determine address of %s\n", rhost);
 | |
|    	return(-1);
 | |
|    }
 | |
|    memcpy((char *)&raddr, (char *)hp->h_addr, hp->h_length);
 | |
| 
 | |
|    if(NetInit()) {
 | |
|    	fprintf(stderr, "talk: Error in NetInit\n");
 | |
|    	return(-1);
 | |
|    }
 | |
| 
 | |
|    if(ScreenInit())
 | |
|    	return(-1);
 | |
| 
 | |
|    if(!TalkInit())
 | |
| 	DoTalk();
 | |
| 
 | |
|    ScreenEnd();
 | |
| 
 | |
|    return(0);
 | |
| }
 | |
| 
 | |
| struct pdata {
 | |
| 	int win;
 | |
| 	int len;
 | |
| 	char buffer[64];
 | |
| } pdata;
 | |
| 
 | |
| void DoTalk()
 | |
| {
 | |
| int s;
 | |
| int s2;
 | |
| int kid;
 | |
| int pfd[2];
 | |
| int win;
 | |
| int len;
 | |
| struct termios termios;
 | |
| char lcc[3];
 | |
| char rcc[3];
 | |
| 
 | |
|    ScreenMsg("");
 | |
|    ScreenWho(ruser, rhost);
 | |
| 
 | |
|    /* Get and send edit characters */
 | |
|    s = tcgetattr(0, &termios);
 | |
|    if(s < 0) {
 | |
|    	perror("talk: tcgetattr");
 | |
|    	return;
 | |
|    }
 | |
|    lcc[0] = termios.c_cc[VERASE];
 | |
|    lcc[1] = termios.c_cc[VKILL];
 | |
|    lcc[2] = 0x17; /* Control - W */
 | |
|    s = write(tcp_fd, lcc, sizeof(lcc));
 | |
|    if(s != sizeof(lcc)) {
 | |
|    	ScreenMsg("Connection Closing due to error");
 | |
|    	return;
 | |
|    }
 | |
|    s = read(tcp_fd, rcc, sizeof(rcc));
 | |
|    if(s != sizeof(rcc)) {
 | |
|    	ScreenMsg("Connection Closing due to error");
 | |
|    	return;
 | |
|    }
 | |
|    ScreenEdit(lcc, rcc);
 | |
| 
 | |
|    s = pipe(pfd);
 | |
|    if(s < 0) {
 | |
|    	ScreenMsg("Could not create pipes");
 | |
|    	return;
 | |
|    }
 | |
| 
 | |
|    if((kid = fork()) < 0) {
 | |
|    	ScreenMsg("Could not fork");
 | |
|    	close(pfd[0]);
 | |
|    	close(pfd[1]);
 | |
|    	return;
 | |
|    }
 | |
| 
 | |
|    if(kid == 0) {
 | |
|    	close(tcp_fd);
 | |
|    	close(pfd[1]);
 | |
|    	while(1) {
 | |
|    		s = read(pfd[0], &pdata, sizeof(pdata));
 | |
|    		if(s != sizeof(pdata)) {
 | |
|    			close(pfd[0]);
 | |
|    			exit(-1);
 | |
|    		}
 | |
|    		ScreenPut(pdata.buffer, pdata.len, pdata.win);
 | |
|    	}
 | |
|    }
 | |
| 
 | |
|    close(pfd[0]);
 | |
| 
 | |
|    if((kid = fork()) < 0) {
 | |
|    	ScreenMsg("Could not fork");
 | |
|    	close(pfd[1]);
 | |
|    	return;
 | |
|    }
 | |
| 
 | |
|    if(kid == 0) {
 | |
|    	pdata.win = REMOTEWIN;
 | |
|    	while(!ScreenDone) {
 | |
| 	   	s = read(tcp_fd, pdata.buffer, sizeof(pdata.buffer));
 | |
|    		if(s <= 0)
 | |
|    			break;
 | |
|    		pdata.len = s;
 | |
| 		write(pfd[1], &pdata, sizeof(pdata));
 | |
|    	}
 | |
|    	close(pfd[1]);
 | |
|    	close(tcp_fd);
 | |
| 	kill(getppid(), SIGINT);
 | |
|    	exit(-1);
 | |
|    }
 | |
| 
 | |
|    pdata.win = LOCALWIN;
 | |
|    while(!ScreenDone) {
 | |
| 	s = read(0, pdata.buffer, sizeof(pdata.buffer));
 | |
| 	if(s <= 0)
 | |
| 		break;
 | |
| 	pdata.len = s;
 | |
| 	write(pfd[1], &pdata, sizeof(pdata));
 | |
| 	s2 = write(tcp_fd, pdata.buffer, s);
 | |
| 	if(s2 != s)
 | |
| 		break;
 | |
|    }
 | |
|    kill(kid, SIGINT);
 | |
|    close(pfd[1]);
 | |
|    close(tcp_fd);
 | |
|    return;
 | |
| }
 | 
