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 #include "talk_ctl.h" 41 #include <sys/time.h> 42 #include <libintl.h> 43 44 #define CTL_WAIT 2 45 /* the amount of time to wait for a response, in seconds */ 46 47 48 /* 49 * SOCKDGRAM is unreliable, so we must repeat messages if we have 50 * not recieved an acknowledgement within a reasonable amount of time 51 */ 52 53 void 54 ctl_transact(target, msg, type, response) 55 struct in_addr target; 56 CTL_MSG msg; 57 int type; 58 CTL_RESPONSE *response; 59 { 60 struct sockaddr junk; 61 int read_mask; 62 int ctl_mask; 63 int nready; 64 int cc; 65 socklen_t junk_size; 66 struct timeval wait; 67 68 wait.tv_sec = CTL_WAIT; 69 wait.tv_usec = 0; 70 71 msg.type = type; 72 73 daemon_addr.sin_addr = target; 74 daemon_addr.sin_port = daemon_port; 75 76 ctl_mask = 1 << ctl_sockt; 77 78 /* 79 * keep sending the message until a response of the right 80 * type is obtained 81 */ 82 83 do { 84 /* keep sending the message until a response is obtained */ 85 86 do { 87 cc = sendto(ctl_sockt, 88 (char *)&msg, sizeof (CTL_MSG), 0, 89 (struct sockaddr *)&daemon_addr, sizeof (daemon_addr)); 90 91 if (cc != sizeof (CTL_MSG)) { 92 if (errno == EINTR) { 93 /* we are returning from an interupt */ 94 continue; 95 } else { 96 p_error( 97 gettext("Error on write to talk daemon")); 98 } 99 } 100 101 read_mask = ctl_mask; 102 103 while ((nready = select(32, (fd_set *)&read_mask, 104 0, 0, &wait)) < 0) { 105 if (errno == EINTR) { 106 /* we are returning from an interupt */ 107 continue; 108 } else { 109 p_error( 110 gettext("Error on waiting for response from daemon")); 111 } 112 } 113 } while (nready == 0); 114 115 /* 116 * keep reading while there are queued messages 117 * (this is not necessary, it just saves extra 118 * request/acknowledgements being sent) 119 */ 120 121 do { 122 123 junk_size = (socklen_t)sizeof (junk); 124 cc = recvfrom(ctl_sockt, (char *)response, 125 sizeof (CTL_RESPONSE), 0, &junk, &junk_size); 126 if (cc < 0) { 127 if (errno == EINTR) { 128 continue; 129 } 130 p_error(gettext("Error on read from talk daemon")); 131 } 132 133 read_mask = ctl_mask; 134 135 /* an immediate poll */ 136 137 timerclear(&wait); 138 nready = select(32, (fd_set *)&read_mask, 0, 0, &wait); 139 140 } while (nready > 0 && response->type != type); 141 142 } while (response->type != type); 143 } 144