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:
parent
46ed21d1a7
commit
285926046a
@ -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>
|
||||
|
@ -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');
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
99
usr.bin/talk/get_iface.c
Normal 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;
|
||||
}
|
@ -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[];
|
||||
|
@ -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()
|
||||
{
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
|
||||
|
@ -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;
|
||||
{
|
||||
|
@ -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;
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user