Files
inetutils/talkd/announce.c
2025-01-01 18:21:25 +01:00

147 lines
3.2 KiB
C

/*
Copyright (C) 1994-2025 Free Software Foundation, Inc.
This file is part of GNU Inetutils.
GNU Inetutils is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Inetutils is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see `http://www.gnu.org/licenses/'. */
#include <config.h>
#include <intalkd.h>
#include <stdarg.h>
#include <sys/uio.h>
#undef MAX
#define MAX(a,b) ( (a) > (b) ? (a) : (b) )
#define N_LINES 5
#define N_CHARS 256
#include <libinetutils.h>
typedef struct
{
int ind;
int max_size;
char line[N_LINES][N_CHARS];
int size[N_LINES];
char buf[N_LINES * N_CHARS + 3];
} LINE;
static void
init_line (LINE *lp)
{
memset (lp, 0, sizeof *lp);
}
static void
format_line (LINE *lp, const char *fmt, ...)
{
va_list ap;
int i = lp->ind;
if (lp->ind >= N_LINES)
return;
lp->ind++;
va_start (ap, fmt);
lp->size[i] = vsnprintf (lp->line[i], sizeof lp->line[i], fmt, ap);
lp->max_size = MAX (lp->max_size, lp->size[i]);
va_end (ap);
}
static char *
finish_line (LINE *lp)
{
int i;
char *p;
p = lp->buf;
*p++ = '\a';
*p++ = '\r';
*p++ = '\n';
for (i = 0; i < lp->ind; i++)
{
char *q;
int j;
for (q = lp->line[i]; *q; q++)
*p++ = *q;
for (j = lp->size[i]; j < lp->max_size + 2; j++)
*p++ = ' ';
*p++ = '\r';
*p++ = '\n';
}
*p = 0;
return lp->buf;
}
static int
print_mesg (char *tty, CTL_MSG *request, char *remote_machine)
{
time_t t;
LINE ln;
char *buf;
struct tm *tm;
struct iovec iovec;
char *cp;
time (&t);
tm = localtime (&t);
init_line (&ln);
format_line (&ln, "");
format_line (&ln, "Message from Talk_Daemon@%s at %d:%02d ...",
hostname, tm->tm_hour, tm->tm_min);
format_line (&ln, "talk: connection requested by %s@%s",
request->l_name, remote_machine);
format_line (&ln, "talk: respond with: talk %s@%s",
request->l_name, remote_machine);
format_line (&ln, "");
format_line (&ln, "");
buf = finish_line (&ln);
iovec.iov_base = buf;
iovec.iov_len = strlen (buf);
if ((cp = inetutils_ttymsg (&iovec, 1, tty, RING_WAIT - 5)) != NULL)
{
syslog (LOG_ERR, "%s", cp);
return FAILED;
}
return SUCCESS;
}
/* See if the user is accepting messages. If so, announce that
a talk is requested. */
int
announce (CTL_MSG *request, char *remote_machine)
{
char *ttypath;
int len;
struct stat st;
int rc;
len = sizeof (PATH_TTY_PFX) + strlen (request->r_tty) + 2;
ttypath = malloc (len);
if (!ttypath)
{
syslog (LOG_ERR, "Out of memory");
exit (EXIT_FAILURE);
}
sprintf (ttypath, "%s/%s", PATH_TTY_PFX, request->r_tty);
rc = stat (ttypath, &st);
free (ttypath);
if (rc < 0 || (st.st_mode & S_IWGRP) == 0)
return PERMISSION_DENIED;
return print_mesg (request->r_tty, request, remote_machine);
}