NetBSD/games/hunt/huntd/faketalk.c

231 lines
4.8 KiB
C

/* $NetBSD: faketalk.c,v 1.7 2002/09/20 20:54:16 mycroft Exp $ */
/*
* Hunt
* Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold
* San Francisco, California
*
* Copyright (c) 1985 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: faketalk.c,v 1.7 2002/09/20 20:54:16 mycroft Exp $");
#endif /* not lint */
#include "bsd.h"
#include "hunt.h"
#if defined(TALK_43) || defined(TALK_42)
# include <sys/time.h>
# include <sys/wait.h>
# include <ctype.h>
# include <netdb.h>
# include <signal.h>
# include <stdio.h>
# include <string.h>
# include <unistd.h>
# include "talk_ctl.h"
# define TRUE 1
# define FALSE 0
/* defines for fake talk message to announce start of game */
# ifdef TALK_43
# define MASQUERADE "\"Hunt Game\""
# else
# define MASQUERADE "HuntGame"
# endif
# define RENDEZVOUS "hunt-players"
# define ARGV0 "HUNT-ANNOUNCE"
extern char *my_machine_name;
extern char *First_arg, *Last_arg;
extern char **environ;
static void do_announce __P((char *));
SIGNAL_TYPE exorcise __P((int));
/*
* exorcise - disspell zombies
*/
SIGNAL_TYPE
exorcise(dummy)
int dummy;
{
(void) wait(0);
}
/*
* query the local SMTP daemon to expand the RENDEZVOUS mailing list
* and fake a talk request to each address thus found.
*/
void
faketalk()
{
struct servent *sp;
char buf[BUFSIZ];
FILE *f;
int service; /* socket of service */
struct sockaddr_in des; /* address of destination */
char *a, *b;
(void) signal(SIGCHLD, exorcise);
if (fork() != 0)
return;
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGPIPE, SIG_IGN);
/*
* change argv so that a ps shows ARGV0
*/
*environ = NULL;
for (a = First_arg, b = ARGV0; a < Last_arg; a++) {
if (*b)
*a = *b++;
else
*a = ' ';
}
/*
* initialize "talk"
*/
get_local_name(MASQUERADE);
open_ctl();
/*
* start fetching addresses
*/
if ((sp = getservbyname("smtp", (char *) NULL)) == NULL) {
# ifdef LOG
syslog(LOG_ERR, "faketalk: smtp protocol not supported\n");
# else
warn("faketalk: stmp protocol not supported");
# endif
_exit(1);
}
memset(&des, 0, sizeof (des));
des.sin_family = AF_INET;
des.sin_addr = my_machine_addr;
des.sin_port = sp->s_port;
if ((service = socket(des.sin_family, SOCK_STREAM, 0)) < 0) {
# ifdef LOG
syslog(LOG_ERR, "falktalk: socket");
# else
warn("falktalk: socket");
# endif
_exit(1);
}
if (connect(service, (struct sockaddr *) &des, sizeof(des)) != 0) {
# ifdef LOG
syslog(LOG_ERR, "faketalk: connect");
# else
warn("faketalk: connect");
# endif
_exit(1);
}
if ((f = fdopen(service, "r")) == NULL) {
# ifdef LOG
syslog(LOG_ERR, "fdopen failed\n");
# else
warn("faketalk: fdopen");
# endif
_exit(2);
}
(void) fgets(buf, BUFSIZ, f);
(void) sprintf(buf, "HELO HuntGame@%s\r\n", my_machine_name);
(void) write(service, buf, strlen(buf));
(void) fgets(buf, BUFSIZ, f);
(void) sprintf(buf, "EXPN %s@%s\r\n", RENDEZVOUS, my_machine_name);
(void) write(service, buf, strlen(buf));
while (fgets(buf, BUFSIZ, f) != NULL) {
char *s, *t;
if (buf[0] != '2' || buf[1] != '5' || buf[2] != '0')
break;
if ((s = strchr(buf + 4, '<')) == NULL)
s = buf + 4, t = buf + strlen(buf) - 1;
else {
s += 1;
if ((t = strrchr(s, '>')) == NULL)
t = s + strlen(s) - 1;
else
t -= 1;
}
while (isspace(*s))
s += 1;
if (*s == '\\')
s += 1;
while (isspace(*t))
t -= 1;
*(t + 1) = '\0';
do_announce(s); /* construct and send talk request */
if (buf[3] == ' ')
break;
}
(void) shutdown(service, 2);
(void) close(service);
_exit(0);
}
/*
* The msg.id's for the invitations on the local and remote machines.
* These are used to delete the invitations.
*/
static void
do_announce(s)
char *s;
{
CTL_RESPONSE response;
get_remote_name(s); /* setup his_machine_addr, msg.r_name */
# ifdef TALK_43
# if BSD_RELEASE >= 44
msg.ctl_addr = *(struct osockaddr *) &ctl_addr;
# else
msg.ctl_addr = *(struct sockaddr *) &ctl_addr;
# endif
msg.ctl_addr.sa_family = htons(msg.ctl_addr.sa_family);
# else
msg.ctl_addr = ctl_addr;
msg.ctl_addr.sin_family = htons(msg.ctl_addr.sin_family);
# endif
msg.id_num = (int) htonl((u_int32_t) -1); /* an impossible id_num */
ctl_transact(his_machine_addr, msg, ANNOUNCE, &response);
if (response.answer != SUCCESS)
return;
/*
* Have the daemons delete the invitations now that we
* have announced.
*/
/* we don't care if cleanup doesn't make it. */
msg.type = DELETE;
msg.id_num = (int) htonl(response.id_num);
daemon_addr.sin_addr = his_machine_addr;
if (sendto(ctl_sockt, (char *) &msg, sizeof (msg), 0,
(struct sockaddr *) &daemon_addr, sizeof(daemon_addr))
!= sizeof(msg))
p_error("send delete remote");
}
#else
void
faketalk()
{
return;
}
#endif