1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 1997 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 #pragma ident "%Z%%M% %I% %E% SMI"
41
42 #include "talk_ctl.h"
43 #include <sys/time.h>
44 #include <libintl.h>
45
46 #define CTL_WAIT 2
47 /* the amount of time to wait for a response, in seconds */
48
49
50 /*
51 * SOCKDGRAM is unreliable, so we must repeat messages if we have
52 * not recieved an acknowledgement within a reasonable amount of time
53 */
54
55 void
ctl_transact(target,msg,type,response)56 ctl_transact(target, msg, type, response)
57 struct in_addr target;
58 CTL_MSG msg;
59 int type;
60 CTL_RESPONSE *response;
61 {
62 struct sockaddr junk;
63 int read_mask;
64 int ctl_mask;
65 int nready;
66 int cc;
67 socklen_t junk_size;
68 struct timeval wait;
69
70 wait.tv_sec = CTL_WAIT;
71 wait.tv_usec = 0;
72
73 msg.type = type;
74
75 daemon_addr.sin_addr = target;
76 daemon_addr.sin_port = daemon_port;
77
78 ctl_mask = 1 << ctl_sockt;
79
80 /*
81 * keep sending the message until a response of the right
82 * type is obtained
83 */
84
85 do {
86 /* keep sending the message until a response is obtained */
87
88 do {
89 cc = sendto(ctl_sockt,
90 (char *)&msg, sizeof (CTL_MSG), 0,
91 (struct sockaddr *)&daemon_addr, sizeof (daemon_addr));
92
93 if (cc != sizeof (CTL_MSG)) {
94 if (errno == EINTR) {
95 /* we are returning from an interupt */
96 continue;
97 } else {
98 p_error(
99 gettext("Error on write to talk daemon"));
100 }
101 }
102
103 read_mask = ctl_mask;
104
105 while ((nready = select(32, (fd_set *)&read_mask,
106 0, 0, &wait)) < 0) {
107 if (errno == EINTR) {
108 /* we are returning from an interupt */
109 continue;
110 } else {
111 p_error(
112 gettext("Error on waiting for response from daemon"));
113 }
114 }
115 } while (nready == 0);
116
117 /*
118 * keep reading while there are queued messages
119 * (this is not necessary, it just saves extra
120 * request/acknowledgements being sent)
121 */
122
123 do {
124
125 junk_size = (socklen_t)sizeof (junk);
126 cc = recvfrom(ctl_sockt, (char *)response,
127 sizeof (CTL_RESPONSE), 0, &junk, &junk_size);
128 if (cc < 0) {
129 if (errno == EINTR) {
130 continue;
131 }
132 p_error(gettext("Error on read from talk daemon"));
133 }
134
135 read_mask = ctl_mask;
136
137 /* an immediate poll */
138
139 timerclear(&wait);
140 nready = select(32, (fd_set *)&read_mask, 0, 0, &wait);
141
142 } while (nready > 0 && response->type != type);
143
144 } while (response->type != type);
145 }
146