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