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