xref: /original-bsd/old/talk/talk/ctl_transact.c (revision 27393bdf)
1 /*-
2  * Copyright (c) 1983, 1985
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[] = "@(#)ctl_transact.c	5.1 (Berkeley) 6/6/85";
10 #endif not lint
11 
12 #include "talk_ctl.h"
13 #include <sys/time.h>
14 #include <unistd.h>
15 
16 #define CTL_WAIT 2	/* time to wait for a response, in seconds */
17 
18 /*
19  * SOCKDGRAM is unreliable, so we must repeat messages if we have
20  * not recieved an acknowledgement within a reasonable amount
21  * of time
22  */
23 void
ctl_transact(target,msg,type,response)24 ctl_transact(target, msg, type, response)
25 	struct in_addr target;
26 	CTL_MSG msg;
27 	int type;
28 	CTL_RESPONSE *response;
29 {
30 	struct sockaddr junk;
31 	int read_mask;
32 	int ctl_mask;
33 	int nready;
34 	int cc;
35 	int junk_size;
36 	struct timeval wait;
37 
38 	msg.type = type;
39 	daemon_addr.sin_addr = target;
40 	daemon_addr.sin_port = daemon_port;
41 	ctl_mask = 1 << ctl_sockt;
42 
43 	/*
44 	 * keep sending the message until a response of the right
45 	 * type is obtained
46 	 */
47 	do {
48 		wait.tv_sec = CTL_WAIT;
49 		wait.tv_usec = 0;
50 
51 		/* keep sending the message until a response is obtained */
52 		do {
53 			cc = sendto(ctl_sockt, (char *)&msg, sizeof(CTL_MSG), 0,
54 			    (struct sockaddr *)&daemon_addr,
55 			    sizeof(daemon_addr));
56 			if (cc != sizeof(CTL_MSG)) {
57 				if (errno == EINTR)
58 					continue;
59 				p_error("Error on write to talk daemon");
60 			}
61 			read_mask = ctl_mask;
62 			if ((nready = select(32, (fd_set *)&read_mask, 0, 0, &wait)) < 0) {
63 				if (errno == EINTR)
64 					continue;
65 				p_error("Error waiting for daemon response");
66 			}
67 		} while (nready == 0);
68 		/* keep reading while there are queued messages
69 		   (this is not necessary, it just saves extra
70 		   request/acknowledgements being sent)
71 		 */
72 		do {
73 			junk_size = sizeof(junk);
74 			cc = recvfrom(ctl_sockt, (char *)response,
75 			    sizeof (CTL_RESPONSE), 0, &junk, &junk_size);
76 			if (cc < 0) {
77 				if (errno == EINTR)
78 					continue;
79 				p_error("Error on read from talk daemon");
80 			}
81 			read_mask = ctl_mask;
82 			/* an immediate poll */
83 			timerclear(&wait);
84 			nready = select(32, (fd_set *)&read_mask, 0, 0, &wait);
85 		} while (nready > 0 && response->type != type);
86 	} while (response->type != type);
87 }
88