xref: /original-bsd/usr.bin/talk/look_up.c (revision ec35a16d)
1 /*
2  * Copyright (c) 1983, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)look_up.c	8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11 
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <protocols/talkd.h>
16 #include <errno.h>
17 #include "talk_ctl.h"
18 #include "talk.h"
19 
20 /*
21  * See if the local daemon has an invitation for us.
22  */
23 check_local()
24 {
25 	CTL_RESPONSE response;
26 	register CTL_RESPONSE *rp = &response;
27 
28 	/* the rest of msg was set up in get_names */
29 #ifdef MSG_EOR
30 	/* copy new style sockaddr to old, swap family (short in old) */
31 	msg.ctl_addr = *(struct osockaddr *)&ctl_addr;
32 	msg.ctl_addr.sa_family = htons(ctl_addr.sin_family);
33 #else
34 	msg.ctl_addr = *(struct sockaddr *)&ctl_addr;
35 #endif
36 	/* must be initiating a talk */
37 	if (!look_for_invite(rp))
38 		return (0);
39 	/*
40 	 * There was an invitation waiting for us,
41 	 * so connect with the other (hopefully waiting) party
42 	 */
43 	current_state = "Waiting to connect with caller";
44 	do {
45 		if (rp->addr.sa_family != AF_INET)
46 			p_error("Response uses invalid network address");
47 		errno = 0;
48 		if (connect(sockt,
49 		    (struct sockaddr *)&rp->addr, sizeof (rp->addr)) != -1)
50 			return (1);
51 	} while (errno == EINTR);
52 	if (errno == ECONNREFUSED) {
53 		/*
54 		 * The caller gave up, but his invitation somehow
55 		 * was not cleared. Clear it and initiate an
56 		 * invitation. (We know there are no newer invitations,
57 		 * the talkd works LIFO.)
58 		 */
59 		ctl_transact(his_machine_addr, msg, DELETE, rp);
60 		close(sockt);
61 		open_sockt();
62 		return (0);
63 	}
64 	p_error("Unable to connect with initiator");
65 	/*NOTREACHED*/
66 }
67 
68 /*
69  * Look for an invitation on 'machine'
70  */
71 look_for_invite(rp)
72 	CTL_RESPONSE *rp;
73 {
74 	struct in_addr machine_addr;
75 
76 	current_state = "Checking for invitation on caller's machine";
77 	ctl_transact(his_machine_addr, msg, LOOK_UP, rp);
78 	/* the switch is for later options, such as multiple invitations */
79 	switch (rp->answer) {
80 
81 	case SUCCESS:
82 		msg.id_num = htonl(rp->id_num);
83 		return (1);
84 
85 	default:
86 		/* there wasn't an invitation waiting for us */
87 		return (0);
88 	}
89 }
90