Make talk automagically find out the interface IP address where the

remote peer will be connected through.  This avoids the ``Checking for
invitation on caller's machine'' problem for multi-homed hosts.

Thanks to: Garrett, for his `find_interface' example
This commit is contained in:
Joerg Wunsch 1996-03-09 19:23:01 +00:00
parent 46ed21d1a7
commit 285926046a
14 changed files with 207 additions and 54 deletions

View File

@ -1,10 +1,11 @@
# From: @(#)Makefile 8.1 (Berkeley) 6/6/93
# $Id$
# $Id: Makefile,v 1.3 1995/02/21 04:35:43 wollman Exp $
PROG= talk
DPADD= ${LIBCURSES} ${LIBTERMCAP}
LDADD= -lcurses -ltermcap
SRCS= ctl.c ctl_transact.c display.c get_addrs.c get_names.c \
CFLAGS+= -Wall -Wstrict-prototypes -Wno-unused
SRCS= ctl.c ctl_transact.c display.c get_addrs.c get_iface.c get_names.c \
init_disp.c invite.c io.c look_up.c msgs.c talk.c
.include <bsd.prog.mk>

View File

@ -64,6 +64,7 @@ int invitation_waiting = 0;
CTL_MSG msg;
void
open_sockt()
{
int length;
@ -81,6 +82,7 @@ open_sockt()
}
/* open the ctl socket */
void
open_ctl()
{
int length;
@ -100,13 +102,14 @@ open_ctl()
}
/* print_addr is a debug print routine */
void
print_addr(addr)
struct sockaddr_in addr;
{
int i;
printf("addr = %x, port = %o, family = %o zero = ",
addr.sin_addr, addr.sin_port, addr.sin_family);
printf("addr = %lx, port = %o, family = %o zero = ",
addr.sin_addr.s_addr, addr.sin_port, addr.sin_family);
for (i = 0; i<8;i++)
printf("%o ", (int)addr.sin_zero[i]);
putchar('\n');

View File

@ -35,12 +35,9 @@
static char sccsid[] = "@(#)ctl_transact.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <protocols/talkd.h>
#include <errno.h>
#include <string.h>
#include "talk.h"
#include "talk_ctl.h"
#define CTL_WAIT 2 /* time to wait for a response, in seconds */
@ -50,19 +47,22 @@ static char sccsid[] = "@(#)ctl_transact.c 8.1 (Berkeley) 6/6/93";
* not recieved an acknowledgement within a reasonable amount
* of time
*/
void
ctl_transact(target, msg, type, rp)
struct in_addr target;
CTL_MSG msg;
int type;
CTL_RESPONSE *rp;
{
int read_mask, ctl_mask, nready, cc;
fd_set read_mask, ctl_mask;
int nready = 0, cc;
struct timeval wait;
msg.type = type;
daemon_addr.sin_addr = target;
daemon_addr.sin_port = daemon_port;
ctl_mask = 1 << ctl_sockt;
FD_ZERO(&ctl_mask);
FD_SET(ctl_sockt, &ctl_mask);
/*
* Keep sending the message until a response of

View File

@ -52,6 +52,7 @@ int curses_initialized = 0;
* max HAS to be a function, it is called with
* a argument of the form --foo at least once.
*/
int
max(a,b)
int a, b;
{
@ -63,9 +64,10 @@ max(a,b)
* Display some text on somebody's window, processing some control
* characters while we are at it.
*/
void
display(win, text, size)
register xwin_t *win;
register unsigned char *text;
register char *text;
int size;
{
register int i;
@ -150,7 +152,7 @@ display(win, text, size)
cch = (*text & 63) + 64;
waddch(win->x_win, cch);
} else
waddch(win->x_win, *text);
waddch(win->x_win, (unsigned)*text);
getyx(win->x_win, win->x_line, win->x_col);
text++;
}
@ -160,8 +162,11 @@ display(win, text, size)
/*
* Read the character at the indicated position in win
*/
int
readwin(win, line, col)
WINDOW *win;
int line;
int col;
{
int oldline, oldcol;
register int c;

View File

@ -35,14 +35,13 @@
static char sccsid[] = "@(#)get_addrs.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <protocols/talkd.h>
#include <string.h>
#include <netdb.h>
#include <stdio.h>
#include "talk.h"
#include "talk_ctl.h"
void
get_addrs(my_machine_name, his_machine_name)
char *my_machine_name, *his_machine_name;
{
@ -50,28 +49,18 @@ get_addrs(my_machine_name, his_machine_name)
struct servent *sp;
msg.pid = htonl(getpid());
/* look up the address of the local host */
hp = gethostbyname(my_machine_name);
hp = gethostbyname(his_machine_name);
if (hp == NULL) {
fprintf(stderr, "talk: %s: ", my_machine_name);
fprintf(stderr, "talk: %s: ", his_machine_name);
herror((char *)NULL);
exit(-1);
}
bcopy(hp->h_addr, (char *)&my_machine_addr, hp->h_length);
/*
* If the callee is on-machine, just copy the
* network address, otherwise do a lookup...
*/
if (strcmp(his_machine_name, my_machine_name)) {
hp = gethostbyname(his_machine_name);
if (hp == NULL) {
fprintf(stderr, "talk: %s: ", his_machine_name);
herror((char *)NULL);
exit(-1);
}
bcopy(hp->h_addr, (char *) &his_machine_addr, hp->h_length);
} else
his_machine_addr = my_machine_addr;
bcopy(hp->h_addr, (char *) &his_machine_addr, hp->h_length);
if (get_iface(&his_machine_addr, &my_machine_addr) == -1) {
perror("failed to find my interface address");
exit(-1);
}
/* find the server's port */
sp = getservbyname("ntalk", "udp");
if (sp == 0) {

99
usr.bin/talk/get_iface.c Normal file
View File

@ -0,0 +1,99 @@
/*
* Copyright 1994, 1995 Massachusetts Institute of Technology
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
* granted, provided that both the above copyright notice and this
* permission notice appear in all copies, that both the above
* copyright notice and this permission notice appear in all
* supporting documentation, and that the name of M.I.T. not be used
* in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission. M.I.T. makes
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
* SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* From:
* Id: find_interface.c,v 1.1 1995/08/14 16:08:39 wollman Exp
*
* $Id$
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "talk.h"
/*
* Try to find the interface address that is used to route an IP
* packet to a remote peer.
*/
int
get_iface(dst, iface)
struct in_addr *dst;
struct in_addr *iface;
{
static struct sockaddr_in local;
struct sockaddr_in remote;
struct hostent *hp;
int s, rv, namelen;
memcpy(&remote.sin_addr, dst, sizeof remote.sin_addr);
remote.sin_port = htons(60000);
remote.sin_family = AF_INET;
remote.sin_len = sizeof remote;
local.sin_addr.s_addr = htonl(INADDR_ANY);
local.sin_port = htons(60000);
local.sin_family = AF_INET;
local.sin_len = sizeof local;
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s < 0)
return -1;
do {
rv = bind(s, (struct sockaddr *)&local, sizeof local);
local.sin_port++;
} while(rv < 0 && errno == EADDRINUSE);
if (rv < 0) {
close(s);
return -1;
}
do {
rv = connect(s, (struct sockaddr *)&remote, sizeof remote);
remote.sin_port++;
} while(rv < 0 && errno == EADDRINUSE);
if (rv < 0) {
close(s);
return -1;
}
namelen = sizeof local;
rv = getsockname(s, (struct sockaddr *)&local, &namelen);
close(s);
if (rv < 0)
return -1;
memcpy(iface, &local.sin_addr, sizeof local.sin_addr);
return 0;
}

View File

@ -35,20 +35,18 @@
static char sccsid[] = "@(#)get_names.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */
#include <unistd.h>
#include <string.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <protocols/talkd.h>
#include <pwd.h>
#include "talk.h"
char *getlogin();
char *ttyname();
char *rindex();
extern CTL_MSG msg;
/*
* Determine the local and remote user, tty, and machines
*/
void
get_names(argc, argv)
int argc;
char *argv[];

View File

@ -53,7 +53,8 @@ static char sccsid[] = "@(#)init_disp.c 8.2 (Berkeley) 2/16/94";
/*
* Make sure the callee can write to the screen
*/
void check_writeable()
void
check_writeable()
{
char *tty;
struct stat sb;
@ -70,9 +71,9 @@ void check_writeable()
* Set up curses, catch the appropriate signals,
* and build the various windows.
*/
void
init_display()
{
void sig_sent();
struct sigvec sigv;
if (initscr() == NULL)
@ -113,6 +114,7 @@ init_display()
* the first three characters each talk transmits after
* connection are the three edit characters.
*/
void
set_edit_chars()
{
char buf[3];
@ -142,8 +144,10 @@ set_edit_chars()
his_win.werase = buf[2];
}
/* ARGSUSED */
void
sig_sent()
sig_sent(signo)
int signo;
{
message("Connection closing. Exiting");
@ -153,6 +157,7 @@ sig_sent()
/*
* All done talking...hang up the phone and reset terminal thingy's
*/
void
quit()
{

View File

@ -59,9 +59,9 @@ static char sccsid[] = "@(#)invite.c 8.1 (Berkeley) 6/6/93";
* invitations.
*/
int local_id, remote_id;
void re_invite();
jmp_buf invitebuf;
void
invite_remote()
{
int nfd, read_mask, template, new_sockt;
@ -117,8 +117,10 @@ invite_remote()
/*
* Routine called on interupt to re-invite the callee
*/
/* ARGSUSED */
void
re_invite()
re_invite(signo)
int signo;
{
message("Ringing your party again");
@ -147,6 +149,7 @@ static char *answers[] = {
/*
* Transmit the invitation and process the response
*/
void
announce_invite()
{
CTL_RESPONSE response;
@ -167,6 +170,7 @@ announce_invite()
/*
* Tell the daemon to remove your invitation
*/
void
send_delete()
{

View File

@ -49,28 +49,28 @@ static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 6/6/93";
#include "talk.h"
#define A_LONG_TIME 10000000
#define STDIN_MASK (1<<fileno(stdin)) /* the bit mask for standard
input */
/*
* The routine to do the actual talking
*/
void
talk()
{
register int read_template, sockt_mask;
int read_set, nb;
int nb;
fd_set read_set, read_template;
char buf[BUFSIZ];
struct timeval wait;
message("Connection established\007\007\007");
current_line = 0;
sockt_mask = (1<<sockt);
/*
* Wait on both the other process (sockt_mask) and
* standard input ( STDIN_MASK )
*/
read_template = sockt_mask | STDIN_MASK;
FD_ZERO(&read_template);
FD_SET(sockt, &read_template);
FD_SET(fileno(stdin), &read_template);
for (;;) {
read_set = read_template;
wait.tv_sec = A_LONG_TIME;
@ -85,7 +85,7 @@ talk()
p_error("Unexpected error from select");
quit();
}
if (read_set & sockt_mask) {
if (FD_ISSET(sockt, &read_set)) {
/* There is data on sockt */
nb = read(sockt, buf, sizeof buf);
if (nb <= 0) {
@ -94,7 +94,7 @@ talk()
}
display(&his_win, buf, nb);
}
if (read_set & STDIN_MASK) {
if (FD_ISSET(fileno(stdin), &read_set)) {
/*
* We can't make the tty non_blocking, because
* curses's output routines would screw up
@ -115,6 +115,7 @@ extern int sys_nerr;
* p_error prints the system error message on the standard location
* on the screen and then exits. (i.e. a curses version of perror)
*/
void
p_error(string)
char *string;
{
@ -130,6 +131,7 @@ p_error(string)
/*
* Display string in the standard location
*/
void
message(string)
char *string;
{

View File

@ -46,6 +46,7 @@ static char sccsid[] = "@(#)look_up.c 8.1 (Berkeley) 6/6/93";
/*
* See if the local daemon has an invitation for us.
*/
int
check_local()
{
CTL_RESPONSE response;
@ -89,11 +90,13 @@ check_local()
}
p_error("Unable to connect with initiator");
/*NOTREACHED*/
return (0);
}
/*
* Look for an invitation on 'machine'
*/
int
look_for_invite(rp)
CTL_RESPONSE *rp;
{

View File

@ -50,12 +50,15 @@ static char sccsid[] = "@(#)msgs.c 8.1 (Berkeley) 6/6/93";
char *current_state;
int current_line = 0;
/* ARGSUSED */
void
disp_msg()
disp_msg(signo)
int signo;
{
message(current_state);
}
void
start_msgs()
{
struct itimerval itimer;
@ -67,6 +70,7 @@ start_msgs()
setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
}
void
end_msgs()
{
struct itimerval itimer;

View File

@ -59,6 +59,9 @@ static char sccsid[] = "@(#)talk.c 8.1 (Berkeley) 6/6/93";
* Fixed to not run with unwriteable terminals MRVM 28/12/94
*/
int main __P((int, char **));
int
main(argc, argv)
int argc;
char *argv[];
@ -76,4 +79,5 @@ main(argc, argv)
end_msgs();
set_edit_chars();
talk();
return 0;
}

View File

@ -33,7 +33,15 @@
* @(#)talk.h 8.1 (Berkeley) 6/6/93
*/
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <protocols/talkd.h>
#include <curses.h>
#include <unistd.h>
extern int sockt;
extern int curses_initialized;
@ -56,3 +64,31 @@ typedef struct xwin {
extern xwin_t my_win;
extern xwin_t his_win;
extern WINDOW *line_win;
extern void announce_invite __P((void));
extern int check_local __P((void));
extern void check_writeable __P((void));
extern void ctl_transact __P((struct in_addr,CTL_MSG,int,CTL_RESPONSE *));
extern void disp_msg __P((int));
extern void display __P((xwin_t *, char *, int));
extern void end_msgs __P((void));
extern void get_addrs __P((char *, char *));
extern int get_iface __P((struct in_addr *, struct in_addr *));
extern void get_names __P((int, char **));
extern void init_display __P((void));
extern void invite_remote __P((void));
extern int look_for_invite __P((CTL_RESPONSE *));
extern int max __P((int, int));
extern void message __P((char *));
extern void open_ctl __P((void));
extern void open_sockt __P((void));
extern void p_error __P((char *));
extern void print_addr __P((struct sockaddr_in));
extern void quit __P((void));
extern int readwin __P((WINDOW *, int, int));
extern void re_invite __P((int));
extern void send_delete __P((void));
extern void set_edit_chars __P((void));
extern void sig_sent __P((int));
extern void start_msgs __P((void));
extern void talk __P((void));