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 1994 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 * Copyright (c) 2016 by Delphix. All rights reserved. 41 */ 42 43 #pragma ident "%Z%%M% %I% %E% SMI" 44 45 #include "talk_ctl.h" 46 #include <sys/time.h> 47 #include <signal.h> 48 #include <setjmp.h> 49 #include <libintl.h> 50 51 #ifdef SYSV 52 #define signal(s, f) sigset(s, f) 53 #endif /* SYSV */ 54 55 /* 56 * There wasn't an invitation waiting, so send a request containing 57 * our socket address to the remote talk daemon so it can invite 58 * the remote. 59 */ 60 61 static int local_id, remote_id; 62 63 /* 64 * the msg.id's for the invitations 65 * on the local and remote machines. 66 * These are used to delete the invitations. 67 */ 68 69 static jmp_buf invitebuf; 70 71 static void re_invite(); 72 static void announce_invite(); 73 74 void 75 invite_remote() 76 { 77 int new_sockt; 78 struct itimerval itimer; 79 CTL_RESPONSE response; 80 81 itimer.it_value.tv_sec = RING_WAIT; 82 itimer.it_value.tv_usec = 0; 83 itimer.it_interval = itimer.it_value; 84 85 if (listen(sockt, 5) != 0) { 86 p_error(gettext("Error on attempt to listen for caller")); 87 } 88 89 msg.addr = my_addr; 90 msg.id_num = -1; /* an impossible id_num */ 91 92 invitation_waiting = 1; 93 94 announce_invite(); 95 96 /* 97 * shut off the automatic messages for a while, 98 * so we can use the interupt timer to resend the invitation 99 */ 100 101 end_msgs(); 102 setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); 103 message(gettext("Waiting for your party to respond")); 104 signal(SIGALRM, re_invite); 105 (void) setjmp(invitebuf); 106 107 while ((new_sockt = accept(sockt, 0, 0)) < 0) { 108 if (errno != EINTR) { 109 p_error(gettext("Unable to connect with your party")); 110 } else { 111 /* we just returned from a interupt, keep trying */ 112 continue; 113 } 114 } 115 116 close(sockt); 117 sockt = new_sockt; 118 119 /* 120 * have the daemons delete the invitations now that we have connected. 121 */ 122 123 current_state = strdup(gettext("Waiting for your party to respond")); 124 start_msgs(); 125 126 msg.id_num = local_id; 127 ctl_transact(my_machine_addr, msg, DELETE, &response); 128 msg.id_num = remote_id; 129 ctl_transact(rem_machine_addr, msg, DELETE, &response); 130 invitation_waiting = 0; 131 } 132 133 /* routine called on interupt to re-invite the callee */ 134 135 static void 136 re_invite() 137 { 138 message(gettext("Ringing your party again")); 139 current_line++; 140 /* force a re-announce */ 141 msg.id_num = remote_id + 1; 142 announce_invite(); 143 longjmp(invitebuf, 1); 144 } 145 146 /* transmit the invitation and process the response */ 147 148 static void 149 announce_invite() 150 { 151 CTL_RESPONSE response; 152 153 current_state = 154 gettext("Trying to connect to your party's talk daemon"); 155 156 ctl_transact(rem_machine_addr, msg, ANNOUNCE, &response); 157 remote_id = response.id_num; 158 159 if (response.answer != SUCCESS) { 160 161 switch (response.answer) { 162 163 case NOT_HERE : 164 message(gettext("Your party is not logged on")); 165 break; 166 167 case MACHINE_UNKNOWN : 168 message( 169 gettext("Target machine does not recognize us")); 170 break; 171 172 case UNKNOWN_REQUEST : 173 message( 174 gettext("Target machine can not handle remote talk")); 175 break; 176 177 case FAILED : 178 message( 179 gettext("Target machine is too confused to talk to us")); 180 break; 181 182 case PERMISSION_DENIED : 183 message(gettext("Your party is refusing messages")); 184 break; 185 } 186 187 quit(); 188 } 189 190 /* leave the actual invitation on my talk daemon */ 191 192 ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response); 193 local_id = response.id_num; 194 } 195 196 void 197 send_delete() 198 { 199 200 /* tell the daemon to remove your invitation */ 201 202 msg.type = DELETE; 203 204 /* 205 * this is just a extra clean up, so just send it 206 * and don't wait for an answer 207 */ 208 209 msg.id_num = remote_id; 210 daemon_addr.sin_addr = rem_machine_addr; 211 if (sendto(ctl_sockt, (char *)&msg, sizeof (CTL_MSG), 0, 212 (struct sockaddr *)&daemon_addr, 213 sizeof (daemon_addr)) != sizeof (CTL_MSG)) { 214 perror(gettext("send_delete remote")); 215 } 216 217 msg.id_num = local_id; 218 daemon_addr.sin_addr = my_machine_addr; 219 if (sendto(ctl_sockt, (char *)&msg, sizeof (CTL_MSG), 0, 220 (struct sockaddr *)&daemon_addr, 221 sizeof (daemon_addr)) != sizeof (CTL_MSG)) { 222 perror(gettext("send_delete local")); 223 } 224 } 225