xref: /original-bsd/usr.bin/talk/look_up.c (revision 18f6d767)
1 #ifndef lint
2 static char sccsid[] = "@(#)look_up.c	1.3 (Berkeley) 05/11/84";
3 #endif
4 
5 #include "talk_ctl.h"
6 
7 
8 /*
9  * See if the local daemon has a invitation for us
10  */
11 check_local()
12 {
13 	CTL_RESPONSE response;
14 
15 	/* the rest of msg was set up in get_names */
16 	msg.ctl_addr = ctl_addr;
17 	/* must be initiating a talk */
18 	if (!look_for_invite(&response))
19 		return (0);
20 	/*
21 	 * There was an invitation waiting for us,
22 	 * so connect with the other (hopefully waiting) party
23 	 */
24 	current_state = "Waiting to connect with caller";
25 again:
26 	swapresponse(&response);
27 	if (connect(sockt, &response.addr, sizeof(response.addr)) != -1)
28 		return (1);
29 	if (errno == EINTR)
30 		goto again;
31 	if (errno == ECONNREFUSED) {
32 		/*
33 		 * The caller gave up, but his invitation somehow
34 		 * was not cleared. Clear it and initiate an
35 		 * invitation. (We know there are no newer invitations,
36 		 * the talkd works LIFO.)
37 		 */
38 		ctl_transact(his_machine_addr, msg, DELETE, &response);
39 		close(sockt);
40 		open_sockt();
41 		return (0);
42 	}
43 	p_error("Unable to connect with initiator");
44 	/*NOTREACHED*/
45 }
46 
47 /*
48  * Look for an invitation on 'machine'
49  */
50 look_for_invite(response)
51 	CTL_RESPONSE *response;
52 {
53 	struct in_addr machine_addr;
54 
55 	current_state = "Checking for invitation on caller's machine";
56 	ctl_transact(his_machine_addr, msg, LOOK_UP, response);
57 	/* the switch is for later options, such as multiple invitations */
58 	switch (response->answer) {
59 
60 	case SUCCESS:
61 		msg.id_num = response->id_num;
62 		return (1);
63 
64 	default :
65 		/* there wasn't an invitation waiting for us */
66 		return (0);
67 	}
68 }
69 
70 /*
71  * heuristic to detect if need to reshuffle CTL_RESPONSE structure
72  */
73 
74 #define swapshort(a) (((a << 8) | ((unsigned short) a >> 8)) & 0xffff)
75 #define swaplong(a) ((swapshort(a) << 16) | (swapshort(((unsigned)a >> 16))))
76 
77 #ifdef sun
78 struct ctl_response_vax {
79 	char type;
80 	char answer;
81 	short junk;
82 	int id_num;
83 	struct sockaddr_in addr;
84 };
85 
86 swapresponse(rsp)
87 	CTL_RESPONSE *rsp;
88 {
89 	struct ctl_response_vax swaprsp;
90 
91 	if (rsp->addr.sin_family != AF_INET) {
92 		bcopy(rsp, &swaprsp, sizeof(CTL_RESPONSE));
93 		swaprsp.addr.sin_family = swapshort(swaprsp.addr.sin_family);
94 		if (swaprsp.addr.sin_family == AF_INET) {
95 			rsp->addr = swaprsp.addr;
96 			rsp->type = swaprsp.type;
97 			rsp->answer = swaprsp.answer;
98 			rsp->id_num = swaplong(swaprsp.id_num);
99 		}
100 	}
101 }
102 #endif
103 
104 #ifdef vax
105 struct ctl_response_sun {
106 	char type;
107 	char answer;
108 	unsigned short id_num2;
109 	unsigned short id_num1;
110 	short sin_family;
111 	short sin_port;
112 	short sin_addr2;
113 	short sin_addr1;
114 };
115 
116 swapresponse(rsp)
117 	CTL_RESPONSE *rsp;
118 {
119 	struct ctl_response_sun swaprsp;
120 
121 	if (rsp->addr.sin_family != AF_INET) {
122 		bcopy(rsp, &swaprsp, sizeof(struct ctl_response_sun));
123 		if (swaprsp.sin_family == swapshort(AF_INET)) {
124 			rsp->type = swaprsp.type;
125 			rsp->answer = swaprsp.answer;
126 			rsp->id_num = swapshort(swaprsp.id_num1)
127 			    | (swapshort(swaprsp.id_num2) << 16);
128 			rsp->addr.sin_family = swapshort(swaprsp.sin_family);
129  			rsp->addr.sin_port = swaprsp.sin_port;
130 			rsp->addr.sin_addr.s_addr =
131 			    swaprsp.sin_addr2 | (swaprsp.sin_addr1 << 16);
132 		}
133 	}
134 }
135 #endif
136