1/* $NetBSD: faketalk.c,v 1.17 2009/07/04 07:51:35 dholland Exp $ */ 2/* 3 * Copyright (c) 1983-2003, Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * + Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * + Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * + Neither the name of the University of California, San Francisco nor 16 * the names of its contributors may be used to endorse or promote 17 * products derived from this software without specific prior written 18 * permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/cdefs.h> 34#ifndef lint 35__RCSID("$NetBSD: faketalk.c,v 1.17 2009/07/04 07:51:35 dholland Exp $"); 36#endif /* not lint */ 37 38#include "bsd.h" 39#include "hunt.h" 40 41#if defined(TALK_43) || defined(TALK_42) 42 43#include <sys/time.h> 44#include <sys/wait.h> 45#include <ctype.h> 46#include <netdb.h> 47#include <signal.h> 48#include <stdio.h> 49#include <string.h> 50#include <unistd.h> 51#include "talk_ctl.h" 52 53#define TRUE 1 54#define FALSE 0 55 56/* defines for fake talk message to announce start of game */ 57#ifdef TALK_43 58#define MASQUERADE "\"Hunt Game\"" 59#else 60#define MASQUERADE "HuntGame" 61#endif 62#define RENDEZVOUS "hunt-players" 63#define ARGV0 "HUNT-ANNOUNCE" 64 65extern char *my_machine_name; 66extern char *First_arg, *Last_arg; 67extern char **environ; 68 69static void do_announce(char *); 70void exorcise(int); 71 72/* 73 * exorcise - disspell zombies 74 */ 75 76void 77exorcise(int dummy __unused) 78{ 79 (void) wait(0); 80} 81 82/* 83 * query the local SMTP daemon to expand the RENDEZVOUS mailing list 84 * and fake a talk request to each address thus found. 85 */ 86 87void 88faketalk(void) 89{ 90 struct servent *sp; 91 char buf[BUFSIZ]; 92 FILE *f; 93 int service; /* socket of service */ 94 struct sockaddr_in des; /* address of destination */ 95 char *a, *b; 96 97 (void) signal(SIGCHLD, exorcise); 98 99 if (fork() != 0) 100 return; 101 102 (void) signal(SIGINT, SIG_IGN); 103 (void) signal(SIGPIPE, SIG_IGN); 104 105 /* 106 * change argv so that a ps shows ARGV0 107 */ 108 *environ = NULL; 109 for (a = First_arg, b = ARGV0; a < Last_arg; a++) { 110 if (*b) 111 *a = *b++; 112 else 113 *a = ' '; 114 } 115 116 /* 117 * initialize "talk" 118 */ 119 get_local_name(MASQUERADE); 120 open_ctl(); 121 122 /* 123 * start fetching addresses 124 */ 125 126 if ((sp = getservbyname("smtp", NULL)) == NULL) { 127#ifdef LOG 128 syslog(LOG_ERR, "faketalk: smtp protocol not supported\n"); 129#else 130 warn("faketalk: stmp protocol not supported"); 131#endif 132 _exit(1); 133 } 134 135 memset(&des, 0, sizeof (des)); 136 des.sin_family = AF_INET; 137 des.sin_addr = my_machine_addr; 138 des.sin_port = sp->s_port; 139 140 if ((service = socket(des.sin_family, SOCK_STREAM, 0)) < 0) { 141#ifdef LOG 142 syslog(LOG_ERR, "falktalk: socket"); 143#else 144 warn("falktalk: socket"); 145#endif 146 _exit(1); 147 } 148 149 if (connect(service, (struct sockaddr *) &des, sizeof(des)) != 0) { 150#ifdef LOG 151 syslog(LOG_ERR, "faketalk: connect"); 152#else 153 warn("faketalk: connect"); 154#endif 155 _exit(1); 156 } 157 if ((f = fdopen(service, "r")) == NULL) { 158#ifdef LOG 159 syslog(LOG_ERR, "fdopen failed\n"); 160#else 161 warn("faketalk: fdopen"); 162#endif 163 _exit(2); 164 } 165 166 (void) fgets(buf, BUFSIZ, f); 167 (void) snprintf(buf, sizeof(buf), 168 "HELO HuntGame@%s\r\n", my_machine_name); 169 (void) write(service, buf, strlen(buf)); 170 (void) fgets(buf, BUFSIZ, f); 171 (void) snprintf(buf, sizeof(buf), 172 "EXPN %s@%s\r\n", RENDEZVOUS, my_machine_name); 173 (void) write(service, buf, strlen(buf)); 174 while (fgets(buf, BUFSIZ, f) != NULL) { 175 char *s, *t; 176 177 if (buf[0] != '2' || buf[1] != '5' || buf[2] != '0') 178 break; 179 if ((s = strchr(buf + 4, '<')) == NULL) 180 s = buf + 4, t = buf + strlen(buf) - 1; 181 else { 182 s += 1; 183 if ((t = strrchr(s, '>')) == NULL) 184 t = s + strlen(s) - 1; 185 else 186 t -= 1; 187 } 188 while (isspace(*s)) 189 s += 1; 190 if (*s == '\\') 191 s += 1; 192 while (isspace(*t)) 193 t -= 1; 194 *(t + 1) = '\0'; 195 do_announce(s); /* construct and send talk request */ 196 if (buf[3] == ' ') 197 break; 198 } 199 (void) shutdown(service, 2); 200 (void) close(service); 201 _exit(0); 202} 203 204/* 205 * The msg.id's for the invitations on the local and remote machines. 206 * These are used to delete the invitations. 207 */ 208 209static void 210do_announce(char *s) 211{ 212 CTL_RESPONSE response; 213 214 get_remote_name(s); /* setup his_machine_addr, msg.r_name */ 215 216#ifdef TALK_43 217 msg.ctl_addr = *(struct osockaddr *) &ctl_addr; 218 msg.ctl_addr.sa_family = htons(msg.ctl_addr.sa_family); 219#else 220 msg.ctl_addr = ctl_addr; 221 msg.ctl_addr.sin_family = htons(msg.ctl_addr.sin_family); 222#endif 223 msg.id_num = (int) htonl((uint32_t) -1); /* an impossible id_num */ 224 ctl_transact(his_machine_addr, msg, ANNOUNCE, &response); 225 if (response.answer != SUCCESS) 226 return; 227 228 /* 229 * Have the daemons delete the invitations now that we 230 * have announced. 231 */ 232 233 /* we don't care if cleanup doesn't make it. */ 234 msg.type = DELETE; 235 msg.id_num = (int) htonl(response.id_num); 236 daemon_addr.sin_addr = his_machine_addr; 237 if (sendto(ctl_sockt, &msg, sizeof (msg), 0, 238 (struct sockaddr *) &daemon_addr, sizeof(daemon_addr)) 239 != sizeof(msg)) 240 p_error("send delete remote"); 241} 242 243#else 244 245void 246faketalk(void) 247{ 248 return; 249} 250 251#endif 252