look_up.c revision 178642
190075Sobrien/*
290075Sobrien * Copyright (c) 1983, 1993
390075Sobrien *	The Regents of the University of California.  All rights reserved.
490075Sobrien *
590075Sobrien * Redistribution and use in source and binary forms, with or without
690075Sobrien * modification, are permitted provided that the following conditions
790075Sobrien * are met:
890075Sobrien * 1. Redistributions of source code must retain the above copyright
990075Sobrien *    notice, this list of conditions and the following disclaimer.
1090075Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1190075Sobrien *    notice, this list of conditions and the following disclaimer in the
1290075Sobrien *    documentation and/or other materials provided with the distribution.
1390075Sobrien * 3. All advertising materials mentioning features or use of this software
1490075Sobrien *    must display the following acknowledgement:
1590075Sobrien *	This product includes software developed by the University of
1690075Sobrien *	California, Berkeley and its contributors.
1790075Sobrien * 4. Neither the name of the University nor the names of its contributors
1890075Sobrien *    may be used to endorse or promote products derived from this software
1990075Sobrien *    without specific prior written permission.
2090075Sobrien *
2190075Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2290075Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2390075Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2490075Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2590075Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2690075Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2790075Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2890075Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2990075Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3090075Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3190075Sobrien * SUCH DAMAGE.
3290075Sobrien */
3390075Sobrien
3490075Sobrien#include <sys/cdefs.h>
3590075Sobrien
3690075Sobrien__FBSDID("$FreeBSD: head/usr.bin/talk/look_up.c 178642 2008-04-28 21:08:42Z delphij $");
3790075Sobrien
3890075Sobrien#ifndef lint
3990075Sobrienstatic const char sccsid[] = "@(#)look_up.c	8.1 (Berkeley) 6/6/93";
4090075Sobrien#endif
4190075Sobrien
4290075Sobrien#include <sys/types.h>
4390075Sobrien#include <sys/socket.h>
4490075Sobrien#include <protocols/talkd.h>
4590075Sobrien
4690075Sobrien#include <errno.h>
4790075Sobrien#include <string.h>
4890075Sobrien
4990075Sobrien#include "talk_ctl.h"
5090075Sobrien#include "talk.h"
5190075Sobrien
5290075Sobrien/*
5390075Sobrien * See if the local daemon has an invitation for us.
5490075Sobrien */
5590075Sobrienint
5690075Sobriencheck_local(void)
5790075Sobrien{
5890075Sobrien	CTL_RESPONSE response;
5990075Sobrien	CTL_RESPONSE *rp = &response;
6090075Sobrien	struct sockaddr addr;
61
62	/* the rest of msg was set up in get_names */
63#ifdef MSG_EOR
64	/* copy new style sockaddr to old, swap family (short in old) */
65	msg.ctl_addr = *(struct osockaddr *)&ctl_addr;
66	msg.ctl_addr.sa_family = htons(ctl_addr.sin_family);
67#else
68	msg.ctl_addr = *(struct sockaddr *)&ctl_addr;
69#endif
70	/* must be initiating a talk */
71	if (!look_for_invite(rp))
72		return (0);
73	/*
74	 * There was an invitation waiting for us,
75	 * so connect with the other (hopefully waiting) party
76	 */
77	current_state = "Waiting to connect with caller";
78	do {
79		if (rp->addr.sa_family != AF_INET)
80			p_error("Response uses invalid network address");
81		(void)memcpy(&addr, &rp->addr.sa_family, sizeof(addr));
82		addr.sa_family = rp->addr.sa_family;
83		addr.sa_len = sizeof(addr);
84		errno = 0;
85		if (connect(sockt, &addr, sizeof(addr)) != -1)
86			return (1);
87	} while (errno == EINTR);
88	if (errno == ECONNREFUSED) {
89		/*
90		 * The caller gave up, but his invitation somehow
91		 * was not cleared. Clear it and initiate an
92		 * invitation. (We know there are no newer invitations,
93		 * the talkd works LIFO.)
94		 */
95		ctl_transact(his_machine_addr, msg, DELETE, rp);
96		close(sockt);
97		open_sockt();
98		return (0);
99	}
100	p_error("Unable to connect with initiator");
101	/*NOTREACHED*/
102	return (0);
103}
104
105/*
106 * Look for an invitation on 'machine'
107 */
108int
109look_for_invite(CTL_RESPONSE *rp)
110{
111	current_state = "Checking for invitation on caller's machine";
112	ctl_transact(his_machine_addr, msg, LOOK_UP, rp);
113	/* the switch is for later options, such as multiple invitations */
114	switch (rp->answer) {
115
116	case SUCCESS:
117		msg.id_num = htonl(rp->id_num);
118		return (1);
119
120	default:
121		/* there wasn't an invitation waiting for us */
122		return (0);
123	}
124}
125