xref: /csrg-svn/usr.bin/talk/ctl_transact.c (revision 62301)
122389Sdist /*
2*62301Sbostic  * Copyright (c) 1983, 1993
3*62301Sbostic  *	The Regents of the University of California.  All rights reserved.
434373Sbostic  *
542770Sbostic  * %sccs.include.redist.c%
622389Sdist  */
722389Sdist 
816363Skarels #ifndef lint
9*62301Sbostic static char sccsid[] = "@(#)ctl_transact.c	8.1 (Berkeley) 06/06/93";
1034373Sbostic #endif /* not lint */
1116363Skarels 
1246858Sbostic #include <sys/types.h>
1346858Sbostic #include <sys/socket.h>
1446858Sbostic #include <sys/time.h>
1546858Sbostic #include <netinet/in.h>
1646858Sbostic #include <protocols/talkd.h>
1746858Sbostic #include <errno.h>
1816345Skarels #include "talk_ctl.h"
1916345Skarels 
2016363Skarels #define CTL_WAIT 2	/* time to wait for a response, in seconds */
2116345Skarels 
2216363Skarels /*
2316363Skarels  * SOCKDGRAM is unreliable, so we must repeat messages if we have
2416363Skarels  * not recieved an acknowledgement within a reasonable amount
2516363Skarels  * of time
2616363Skarels  */
2726846Smckusick ctl_transact(target, msg, type, rp)
2816363Skarels 	struct in_addr target;
2916363Skarels 	CTL_MSG msg;
3016363Skarels 	int type;
3126846Smckusick 	CTL_RESPONSE *rp;
3216345Skarels {
3326846Smckusick 	int read_mask, ctl_mask, nready, cc;
3416363Skarels 	struct timeval wait;
3516345Skarels 
3616363Skarels 	msg.type = type;
3716363Skarels 	daemon_addr.sin_addr = target;
3816363Skarels 	daemon_addr.sin_port = daemon_port;
3916363Skarels 	ctl_mask = 1 << ctl_sockt;
4016345Skarels 
4116345Skarels 	/*
4226846Smckusick 	 * Keep sending the message until a response of
4326846Smckusick 	 * the proper type is obtained.
4416345Skarels 	 */
4516345Skarels 	do {
4621905Sbloom 		wait.tv_sec = CTL_WAIT;
4721905Sbloom 		wait.tv_usec = 0;
4826846Smckusick 		/* resend message until a response is obtained */
4916363Skarels 		do {
5026846Smckusick 			cc = sendto(ctl_sockt, (char *)&msg, sizeof (msg), 0,
5146858Sbostic 			    (struct sockaddr *)&daemon_addr,
5246858Sbostic 			    sizeof (daemon_addr));
5326846Smckusick 			if (cc != sizeof (msg)) {
5416363Skarels 				if (errno == EINTR)
5516363Skarels 					continue;
5616363Skarels 				p_error("Error on write to talk daemon");
5716363Skarels 			}
5816363Skarels 			read_mask = ctl_mask;
5926846Smckusick 			nready = select(32, &read_mask, 0, 0, &wait);
6026846Smckusick 			if (nready < 0) {
6116363Skarels 				if (errno == EINTR)
6216363Skarels 					continue;
6316363Skarels 				p_error("Error waiting for daemon response");
6416363Skarels 			}
6516363Skarels 		} while (nready == 0);
6626846Smckusick 		/*
6726846Smckusick 		 * Keep reading while there are queued messages
6826846Smckusick 		 * (this is not necessary, it just saves extra
6926846Smckusick 		 * request/acknowledgements being sent)
7016363Skarels 		 */
7116363Skarels 		do {
7226846Smckusick 			cc = recv(ctl_sockt, (char *)rp, sizeof (*rp), 0);
7316363Skarels 			if (cc < 0) {
7416363Skarels 				if (errno == EINTR)
7516363Skarels 					continue;
7616363Skarels 				p_error("Error on read from talk daemon");
7716363Skarels 			}
7816363Skarels 			read_mask = ctl_mask;
7916363Skarels 			/* an immediate poll */
8016363Skarels 			timerclear(&wait);
8116363Skarels 			nready = select(32, &read_mask, 0, 0, &wait);
8226846Smckusick 		} while (nready > 0 && (rp->vers != TALK_VERSION ||
8326846Smckusick 		    rp->type != type));
8426846Smckusick 	} while (rp->vers != TALK_VERSION || rp->type != type);
8526846Smckusick 	rp->id_num = ntohl(rp->id_num);
8626846Smckusick 	rp->addr.sa_family = ntohs(rp->addr.sa_family);
8716345Skarels }
88